[C++-sig] boost python wrapping boost message queue problem

袁振飞 zf.yuan.y at gmail.com
Wed Jan 7 15:19:57 CET 2015


Hi all.

I wrapped the boost ipc message queue into Python using Boost.Python.
Everything goes fine except I found that

1. the try_receive / try_send will block python when the mq is empty / full.
2. when I use the wrapped message queue in one Python thread, any
other Python thread would be blocked and won't execute.

I'd appreciate a lot for your help!

Below is my C++ wrapping codes.

===============================================

class message_queue {
public:
  message_queue(unsigned int, const char*, size_t, size_t);
  ~message_queue();
  void send(boost::python::str str_buffer, size_t m_size);
  void try_send(boost::python::str str_buffer, size_t m_size);
  boost::python::str receive(size_t m_size);
  boost::python::str try_receive(size_t m_size);
private:
  bi::message_queue* p_message_queue;
};

message_queue::message_queue(unsigned int flag, const char* mq_name,
size_t mq_length = 1, size_t m_size = 1) {
  switch(flag) {
  case 0:
    p_message_queue = new bi::message_queue(bi::create_only, mq_name,
mq_length, m_size);
    break;
  case 1:
    p_message_queue = new bi::message_queue(bi::open_or_create,
mq_name, mq_length, m_size);
    break;
  case 2:
    p_message_queue = new bi::message_queue(bi::open_only, mq_name);
    break;
  }
}

message_queue::~message_queue() {
  delete p_message_queue;
}

void message_queue::send(boost::python::str str_buffer, size_t m_size) {
  assert(m_size ==
boost::python::extract<size_t>(str_buffer.attr("__len__")()));
  const char* buffer = boost::python::extract<const char*>(str_buffer);

  p_message_queue->send(buffer, m_size, 0);
}

void message_queue::try_send(boost::python::str str_buffer, size_t m_size) {
  assert(m_size ==
boost::python::extract<size_t>(str_buffer.attr("__len__")()));
  const char* buffer = boost::python::extract<const char*>(str_buffer);
  p_message_queue->try_send(buffer, m_size, 0);
  return;
}

boost::python::str message_queue::receive(size_t m_size) {
  char* buffer = new char[m_size];
  bi::message_queue::size_type recvd_size;
  unsigned int priority;
  p_message_queue->receive(buffer, m_size, recvd_size, priority);
  return boost::python::str(buffer, m_size);
}

boost::python::str message_queue::try_receive(size_t m_size) {
  char* buffer = new char[m_size];
  bi::message_queue::size_type recvd_size;
  unsigned int priority;
  p_message_queue->try_receive(buffer, m_size, recvd_size, priority);
  return boost::python::str(buffer, m_size);
}

bool shared_memory_object_remove(const char* shm_name) {
  return bi::shared_memory_object::remove(shm_name);
}

BOOST_PYTHON_MODULE(boost_ipc) {
  using namespace boost::python;
  class_<message_queue>("message_queue", init<unsigned int, const
char*, optional<size_t, size_t> >())
    .def("send", &message_queue::send)
    .def("receive", &message_queue::receive)
    .def("try_send", &message_queue::send)
    .def("try_receive", &message_queue::receive);
  def("message_queue_remove", message_queue_remove);
  scope().attr("O_CREATE_ONLY") = 0;
  scope().attr("O_OPEN_OR_CREATE") = 1;
  scope().attr("O_OPEN_ONLY") = 2;
}

===========================================

Below is the Python Script that will block on try_receive
function.

===========================================

#!/usr/bin/python

import boost_ipc

boost_ipc.message_queue_remove("test_mq")
mq1 = boost_ipc.message_queue(boost_ipc.O_CREATE_ONLY, "test_mq", 1, 5)
mq2 = boost_ipc.message_queue(boost_ipc.O_OPEN_ONLY,      "test_mq")

mq1.try_send("hello", 5)
print mq2.receive(5)
print mq2.try_receive(5)


More information about the Cplusplus-sig mailing list