/Src/Dependencies/Boost/boost/interprocess/ipc/message_queue.hpp

http://hadesmem.googlecode.com/ · C++ Header · 644 lines · 367 code · 95 blank · 182 comment · 26 complexity · bc9571e92723361c7a88d75db23c6174 MD5 · raw file

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/interprocess for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP
  11. #define BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP
  12. #include <boost/interprocess/detail/config_begin.hpp>
  13. #include <boost/interprocess/detail/workaround.hpp>
  14. #include <boost/interprocess/shared_memory_object.hpp>
  15. #include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
  16. #include <boost/interprocess/sync/interprocess_condition.hpp>
  17. #include <boost/interprocess/sync/interprocess_mutex.hpp>
  18. #include <boost/interprocess/detail/utilities.hpp>
  19. #include <boost/interprocess/offset_ptr.hpp>
  20. #include <boost/interprocess/creation_tags.hpp>
  21. #include <boost/interprocess/exceptions.hpp>
  22. #include <boost/interprocess/permissions.hpp>
  23. #include <boost/detail/no_exceptions_support.hpp>
  24. #include <boost/interprocess/detail/type_traits.hpp>
  25. #include <algorithm> //std::lower_bound
  26. #include <cstddef> //std::size_t
  27. #include <cstring> //memcpy
  28. //!\file
  29. //!Describes an inter-process message queue. This class allows sending
  30. //!messages between processes and allows blocking, non-blocking and timed
  31. //!sending and receiving.
  32. namespace boost{ namespace interprocess{
  33. //!A class that allows sending messages
  34. //!between processes.
  35. class message_queue
  36. {
  37. /// @cond
  38. //Blocking modes
  39. enum block_t { blocking, timed, non_blocking };
  40. message_queue();
  41. /// @endcond
  42. public:
  43. //!Creates a process shared message queue with name "name". For this message queue,
  44. //!the maximum number of messages will be "max_num_msg" and the maximum message size
  45. //!will be "max_msg_size". Throws on error and if the queue was previously created.
  46. message_queue(create_only_t create_only,
  47. const char *name,
  48. std::size_t max_num_msg,
  49. std::size_t max_msg_size,
  50. const permissions &perm = permissions());
  51. //!Opens or creates a process shared message queue with name "name".
  52. //!If the queue is created, the maximum number of messages will be "max_num_msg"
  53. //!and the maximum message size will be "max_msg_size". If queue was previously
  54. //!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters
  55. //!are ignored. Throws on error.
  56. message_queue(open_or_create_t open_or_create,
  57. const char *name,
  58. std::size_t max_num_msg,
  59. std::size_t max_msg_size,
  60. const permissions &perm = permissions());
  61. //!Opens a previously created process shared message queue with name "name".
  62. //!If the was not previously created or there are no free resources,
  63. //!throws an error.
  64. message_queue(open_only_t open_only,
  65. const char *name);
  66. //!Destroys *this and indicates that the calling process is finished using
  67. //!the resource. All opened message queues are still
  68. //!valid after destruction. The destructor function will deallocate
  69. //!any system resources allocated by the system for use by this process for
  70. //!this resource. The resource can still be opened again calling
  71. //!the open constructor overload. To erase the message queue from the system
  72. //!use remove().
  73. ~message_queue();
  74. //!Sends a message stored in buffer "buffer" with size "buffer_size" in the
  75. //!message queue with priority "priority". If the message queue is full
  76. //!the sender is blocked. Throws interprocess_error on error.*/
  77. void send (const void *buffer, std::size_t buffer_size,
  78. unsigned int priority);
  79. //!Sends a message stored in buffer "buffer" with size "buffer_size" through the
  80. //!message queue with priority "priority". If the message queue is full
  81. //!the sender is not blocked and returns false, otherwise returns true.
  82. //!Throws interprocess_error on error.
  83. bool try_send (const void *buffer, std::size_t buffer_size,
  84. unsigned int priority);
  85. //!Sends a message stored in buffer "buffer" with size "buffer_size" in the
  86. //!message queue with priority "priority". If the message queue is full
  87. //!the sender retries until time "abs_time" is reached. Returns true if
  88. //!the message has been successfully sent. Returns false if timeout is reached.
  89. //!Throws interprocess_error on error.
  90. bool timed_send (const void *buffer, std::size_t buffer_size,
  91. unsigned int priority, const boost::posix_time::ptime& abs_time);
  92. //!Receives a message from the message queue. The message is stored in buffer
  93. //!"buffer", which has size "buffer_size". The received message has size
  94. //!"recvd_size" and priority "priority". If the message queue is empty
  95. //!the receiver is blocked. Throws interprocess_error on error.
  96. void receive (void *buffer, std::size_t buffer_size,
  97. std::size_t &recvd_size,unsigned int &priority);
  98. //!Receives a message from the message queue. The message is stored in buffer
  99. //!"buffer", which has size "buffer_size". The received message has size
  100. //!"recvd_size" and priority "priority". If the message queue is empty
  101. //!the receiver is not blocked and returns false, otherwise returns true.
  102. //!Throws interprocess_error on error.
  103. bool try_receive (void *buffer, std::size_t buffer_size,
  104. std::size_t &recvd_size,unsigned int &priority);
  105. //!Receives a message from the message queue. The message is stored in buffer
  106. //!"buffer", which has size "buffer_size". The received message has size
  107. //!"recvd_size" and priority "priority". If the message queue is empty
  108. //!the receiver retries until time "abs_time" is reached. Returns true if
  109. //!the message has been successfully sent. Returns false if timeout is reached.
  110. //!Throws interprocess_error on error.
  111. bool timed_receive (void *buffer, std::size_t buffer_size,
  112. std::size_t &recvd_size,unsigned int &priority,
  113. const boost::posix_time::ptime &abs_time);
  114. //!Returns the maximum number of messages allowed by the queue. The message
  115. //!queue must be opened or created previously. Otherwise, returns 0.
  116. //!Never throws
  117. std::size_t get_max_msg() const;
  118. //!Returns the maximum size of message allowed by the queue. The message
  119. //!queue must be opened or created previously. Otherwise, returns 0.
  120. //!Never throws
  121. std::size_t get_max_msg_size() const;
  122. //!Returns the number of messages currently stored.
  123. //!Never throws
  124. std::size_t get_num_msg();
  125. //!Removes the message queue from the system.
  126. //!Returns false on error. Never throws
  127. static bool remove(const char *name);
  128. /// @cond
  129. private:
  130. typedef boost::posix_time::ptime ptime;
  131. bool do_receive(block_t block,
  132. void *buffer, std::size_t buffer_size,
  133. std::size_t &recvd_size, unsigned int &priority,
  134. const ptime &abs_time);
  135. bool do_send(block_t block,
  136. const void *buffer, std::size_t buffer_size,
  137. unsigned int priority, const ptime &abs_time);
  138. //!Returns the needed memory size for the shared message queue.
  139. //!Never throws
  140. static std::size_t get_mem_size(std::size_t max_msg_size, std::size_t max_num_msg);
  141. detail::managed_open_or_create_impl<shared_memory_object> m_shmem;
  142. /// @endcond
  143. };
  144. /// @cond
  145. namespace detail {
  146. //!This header is the prefix of each message in the queue
  147. class msg_hdr_t
  148. {
  149. public:
  150. std::size_t len; // Message length
  151. unsigned int priority;// Message priority
  152. //!Returns the data buffer associated with this this message
  153. void * data(){ return this+1; } //
  154. };
  155. //!This functor is the predicate to order stored messages by priority
  156. class priority_functor
  157. {
  158. public:
  159. bool operator()(const offset_ptr<msg_hdr_t> &msg1,
  160. const offset_ptr<msg_hdr_t> &msg2) const
  161. { return msg1->priority < msg2->priority; }
  162. };
  163. //!This header is placed in the beginning of the shared memory and contains
  164. //!the data to control the queue. This class initializes the shared memory
  165. //!in the following way: in ascending memory address with proper alignment
  166. //!fillings:
  167. //!
  168. //!-> mq_hdr_t:
  169. //! Main control block that controls the rest of the elements
  170. //!
  171. //!-> offset_ptr<msg_hdr_t> index [max_num_msg]
  172. //! An array of pointers with size "max_num_msg" called index. Each pointer
  173. //! points to a preallocated message. The elements of this array are
  174. //! reordered in runtime in the following way:
  175. //!
  176. //! When the current number of messages is "cur_num_msg", the first
  177. //! "cur_num_msg" pointers point to inserted messages and the rest
  178. //! point to free messages. The first "cur_num_msg" pointers are
  179. //! ordered by the priority of the pointed message and by insertion order
  180. //! if two messages have the same priority. So the next message to be
  181. //! used in a "receive" is pointed by index [cur_num_msg-1] and the first free
  182. //! message ready to be used in a "send" operation is index [cur_num_msg].
  183. //! This transforms index in a fixed size priority queue with an embedded free
  184. //! message queue.
  185. //!
  186. //!-> struct message_t
  187. //! {
  188. //! msg_hdr_t header;
  189. //! char[max_msg_size] data;
  190. //! } messages [max_num_msg];
  191. //!
  192. //! An array of buffers of preallocated messages, each one prefixed with the
  193. //! msg_hdr_t structure. Each of this message is pointed by one pointer of
  194. //! the index structure.
  195. class mq_hdr_t
  196. : public detail::priority_functor
  197. {
  198. typedef offset_ptr<msg_hdr_t> msg_hdr_ptr_t;
  199. public:
  200. //!Constructor. This object must be constructed in the beginning of the
  201. //!shared memory of the size returned by the function "get_mem_size".
  202. //!This constructor initializes the needed resources and creates
  203. //!the internal structures like the priority index. This can throw.*/
  204. mq_hdr_t(std::size_t max_num_msg, std::size_t max_msg_size)
  205. : m_max_num_msg(max_num_msg),
  206. m_max_msg_size(max_msg_size),
  207. m_cur_num_msg(0)
  208. { this->initialize_memory(); }
  209. //!Returns the inserted message with top priority
  210. msg_hdr_t * top_msg()
  211. { return mp_index[m_cur_num_msg-1].get(); }
  212. //!Returns true if the message queue is full
  213. bool is_full() const
  214. { return m_cur_num_msg == m_max_num_msg; }
  215. //!Returns true if the message queue is empty
  216. bool is_empty() const
  217. { return !m_cur_num_msg; }
  218. //!Frees the top priority message and saves it in the free message list
  219. void free_top_msg()
  220. { --m_cur_num_msg; }
  221. //!Returns the first free msg of the free message queue
  222. msg_hdr_t * free_msg()
  223. { return mp_index[m_cur_num_msg].get(); }
  224. //!Inserts the first free message in the priority queue
  225. void queue_free_msg()
  226. {
  227. //Get free msg
  228. msg_hdr_ptr_t free = mp_index[m_cur_num_msg];
  229. //Get priority queue's range
  230. msg_hdr_ptr_t *it = &mp_index[0], *it_end = &mp_index[m_cur_num_msg];
  231. //Check where the free message should be placed
  232. it = std::lower_bound(it, it_end, free, static_cast<priority_functor&>(*this));
  233. //Make room in that position
  234. std::copy_backward(it, it_end, it_end+1);
  235. //Insert the free message in the correct position
  236. *it = free;
  237. ++m_cur_num_msg;
  238. }
  239. //!Returns the number of bytes needed to construct a message queue with
  240. //!"max_num_size" maximum number of messages and "max_msg_size" maximum
  241. //!message size. Never throws.
  242. static std::size_t get_mem_size
  243. (std::size_t max_msg_size, std::size_t max_num_msg)
  244. {
  245. const std::size_t
  246. msg_hdr_align = detail::alignment_of<detail::msg_hdr_t>::value,
  247. index_align = detail::alignment_of<msg_hdr_ptr_t>::value,
  248. r_hdr_size = detail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value,
  249. r_index_size = detail::get_rounded_size(sizeof(msg_hdr_ptr_t)*max_num_msg, msg_hdr_align),
  250. r_max_msg_size = detail::get_rounded_size(max_msg_size, msg_hdr_align) + sizeof(detail::msg_hdr_t);
  251. return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) +
  252. detail::managed_open_or_create_impl<shared_memory_object>::ManagedOpenOrCreateUserOffset;
  253. }
  254. //!Initializes the memory structures to preallocate messages and constructs the
  255. //!message index. Never throws.
  256. void initialize_memory()
  257. {
  258. const std::size_t
  259. msg_hdr_align = detail::alignment_of<detail::msg_hdr_t>::value,
  260. index_align = detail::alignment_of<msg_hdr_ptr_t>::value,
  261. r_hdr_size = detail::ct_rounded_size<sizeof(mq_hdr_t), index_align>::value,
  262. r_index_size = detail::get_rounded_size(sizeof(msg_hdr_ptr_t)*m_max_num_msg, msg_hdr_align),
  263. r_max_msg_size = detail::get_rounded_size(m_max_msg_size, msg_hdr_align) + sizeof(detail::msg_hdr_t);
  264. //Pointer to the index
  265. msg_hdr_ptr_t *index = reinterpret_cast<msg_hdr_ptr_t*>
  266. (reinterpret_cast<char*>(this)+r_hdr_size);
  267. //Pointer to the first message header
  268. detail::msg_hdr_t *msg_hdr = reinterpret_cast<detail::msg_hdr_t*>
  269. (reinterpret_cast<char*>(this)+r_hdr_size+r_index_size);
  270. //Initialize the pointer to the index
  271. mp_index = index;
  272. //Initialize the index so each slot points to a preallocated message
  273. for(std::size_t i = 0; i < m_max_num_msg; ++i){
  274. index[i] = msg_hdr;
  275. msg_hdr = reinterpret_cast<detail::msg_hdr_t*>
  276. (reinterpret_cast<char*>(msg_hdr)+r_max_msg_size);
  277. }
  278. }
  279. public:
  280. //Pointer to the index
  281. offset_ptr<msg_hdr_ptr_t> mp_index;
  282. //Maximum number of messages of the queue
  283. const std::size_t m_max_num_msg;
  284. //Maximum size of messages of the queue
  285. const std::size_t m_max_msg_size;
  286. //Current number of messages
  287. std::size_t m_cur_num_msg;
  288. //Mutex to protect data structures
  289. interprocess_mutex m_mutex;
  290. //Condition block receivers when there are no messages
  291. interprocess_condition m_cond_recv;
  292. //Condition block senders when the queue is full
  293. interprocess_condition m_cond_send;
  294. };
  295. //!This is the atomic functor to be executed when creating or opening
  296. //!shared memory. Never throws
  297. class initialization_func_t
  298. {
  299. public:
  300. initialization_func_t(std::size_t maxmsg = 0,
  301. std::size_t maxmsgsize = 0)
  302. : m_maxmsg (maxmsg), m_maxmsgsize(maxmsgsize) {}
  303. bool operator()(void *address, std::size_t, bool created)
  304. {
  305. char *mptr;
  306. if(created){
  307. mptr = reinterpret_cast<char*>(address);
  308. //Construct the message queue header at the beginning
  309. BOOST_TRY{
  310. new (mptr) mq_hdr_t(m_maxmsg, m_maxmsgsize);
  311. }
  312. BOOST_CATCH(...){
  313. return false;
  314. }
  315. BOOST_CATCH_END
  316. }
  317. return true;
  318. }
  319. const std::size_t m_maxmsg;
  320. const std::size_t m_maxmsgsize;
  321. };
  322. } //namespace detail {
  323. inline message_queue::~message_queue()
  324. {}
  325. inline std::size_t message_queue::get_mem_size
  326. (std::size_t max_msg_size, std::size_t max_num_msg)
  327. { return detail::mq_hdr_t::get_mem_size(max_msg_size, max_num_msg); }
  328. inline message_queue::message_queue(create_only_t create_only,
  329. const char *name,
  330. std::size_t max_num_msg,
  331. std::size_t max_msg_size,
  332. const permissions &perm)
  333. //Create shared memory and execute functor atomically
  334. : m_shmem(create_only,
  335. name,
  336. get_mem_size(max_msg_size, max_num_msg),
  337. read_write,
  338. static_cast<void*>(0),
  339. //Prepare initialization functor
  340. detail::initialization_func_t (max_num_msg, max_msg_size),
  341. perm)
  342. {}
  343. inline message_queue::message_queue(open_or_create_t open_or_create,
  344. const char *name,
  345. std::size_t max_num_msg,
  346. std::size_t max_msg_size,
  347. const permissions &perm)
  348. //Create shared memory and execute functor atomically
  349. : m_shmem(open_or_create,
  350. name,
  351. get_mem_size(max_msg_size, max_num_msg),
  352. read_write,
  353. static_cast<void*>(0),
  354. //Prepare initialization functor
  355. detail::initialization_func_t (max_num_msg, max_msg_size),
  356. perm)
  357. {}
  358. inline message_queue::message_queue(open_only_t open_only,
  359. const char *name)
  360. //Create shared memory and execute functor atomically
  361. : m_shmem(open_only,
  362. name,
  363. read_write,
  364. static_cast<void*>(0),
  365. //Prepare initialization functor
  366. detail::initialization_func_t ())
  367. {}
  368. inline void message_queue::send
  369. (const void *buffer, std::size_t buffer_size, unsigned int priority)
  370. { this->do_send(blocking, buffer, buffer_size, priority, ptime()); }
  371. inline bool message_queue::try_send
  372. (const void *buffer, std::size_t buffer_size, unsigned int priority)
  373. { return this->do_send(non_blocking, buffer, buffer_size, priority, ptime()); }
  374. inline bool message_queue::timed_send
  375. (const void *buffer, std::size_t buffer_size
  376. ,unsigned int priority, const boost::posix_time::ptime &abs_time)
  377. {
  378. if(abs_time == boost::posix_time::pos_infin){
  379. this->send(buffer, buffer_size, priority);
  380. return true;
  381. }
  382. return this->do_send(timed, buffer, buffer_size, priority, abs_time);
  383. }
  384. inline bool message_queue::do_send(block_t block,
  385. const void *buffer, std::size_t buffer_size,
  386. unsigned int priority, const boost::posix_time::ptime &abs_time)
  387. {
  388. detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
  389. //Check if buffer is smaller than maximum allowed
  390. if (buffer_size > p_hdr->m_max_msg_size) {
  391. throw interprocess_exception(size_error);
  392. }
  393. //---------------------------------------------
  394. scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
  395. //---------------------------------------------
  396. {
  397. //If the queue is full execute blocking logic
  398. if (p_hdr->is_full()) {
  399. switch(block){
  400. case non_blocking :
  401. return false;
  402. break;
  403. case blocking :
  404. do{
  405. p_hdr->m_cond_send.wait(lock);
  406. }
  407. while (p_hdr->is_full());
  408. break;
  409. case timed :
  410. do{
  411. if(!p_hdr->m_cond_send.timed_wait(lock, abs_time)){
  412. if(p_hdr->is_full())
  413. return false;
  414. break;
  415. }
  416. }
  417. while (p_hdr->is_full());
  418. break;
  419. default:
  420. break;
  421. }
  422. }
  423. //Get the first free message from free message queue
  424. detail::msg_hdr_t *free_msg = p_hdr->free_msg();
  425. if (free_msg == 0) {
  426. throw interprocess_exception("boost::interprocess::message_queue corrupted");
  427. }
  428. //Copy control data to the free message
  429. free_msg->priority = priority;
  430. free_msg->len = buffer_size;
  431. //Copy user buffer to the message
  432. std::memcpy(free_msg->data(), buffer, buffer_size);
  433. // bool was_empty = p_hdr->is_empty();
  434. //Insert the first free message in the priority queue
  435. p_hdr->queue_free_msg();
  436. //If this message changes the queue empty state, notify it to receivers
  437. // if (was_empty){
  438. p_hdr->m_cond_recv.notify_one();
  439. // }
  440. } // Lock end
  441. return true;
  442. }
  443. inline void message_queue::receive(void *buffer, std::size_t buffer_size,
  444. std::size_t &recvd_size, unsigned int &priority)
  445. { this->do_receive(blocking, buffer, buffer_size, recvd_size, priority, ptime()); }
  446. inline bool
  447. message_queue::try_receive(void *buffer, std::size_t buffer_size,
  448. std::size_t &recvd_size, unsigned int &priority)
  449. { return this->do_receive(non_blocking, buffer, buffer_size, recvd_size, priority, ptime()); }
  450. inline bool
  451. message_queue::timed_receive(void *buffer, std::size_t buffer_size,
  452. std::size_t &recvd_size, unsigned int &priority,
  453. const boost::posix_time::ptime &abs_time)
  454. {
  455. if(abs_time == boost::posix_time::pos_infin){
  456. this->receive(buffer, buffer_size, recvd_size, priority);
  457. return true;
  458. }
  459. return this->do_receive(timed, buffer, buffer_size, recvd_size, priority, abs_time);
  460. }
  461. inline bool
  462. message_queue::do_receive(block_t block,
  463. void *buffer, std::size_t buffer_size,
  464. std::size_t &recvd_size, unsigned int &priority,
  465. const boost::posix_time::ptime &abs_time)
  466. {
  467. detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
  468. //Check if buffer is big enough for any message
  469. if (buffer_size < p_hdr->m_max_msg_size) {
  470. throw interprocess_exception(size_error);
  471. }
  472. //---------------------------------------------
  473. scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
  474. //---------------------------------------------
  475. {
  476. //If there are no messages execute blocking logic
  477. if (p_hdr->is_empty()) {
  478. switch(block){
  479. case non_blocking :
  480. return false;
  481. break;
  482. case blocking :
  483. do{
  484. p_hdr->m_cond_recv.wait(lock);
  485. }
  486. while (p_hdr->is_empty());
  487. break;
  488. case timed :
  489. do{
  490. if(!p_hdr->m_cond_recv.timed_wait(lock, abs_time)){
  491. if(p_hdr->is_empty())
  492. return false;
  493. break;
  494. }
  495. }
  496. while (p_hdr->is_empty());
  497. break;
  498. //Paranoia check
  499. default:
  500. break;
  501. }
  502. }
  503. //Thre is at least message ready to pick, get the top one
  504. detail::msg_hdr_t *top_msg = p_hdr->top_msg();
  505. //Paranoia check
  506. if (top_msg == 0) {
  507. throw interprocess_exception("boost::interprocess::message_queue corrupted");
  508. }
  509. //Get data from the message
  510. recvd_size = top_msg->len;
  511. priority = top_msg->priority;
  512. //Copy data to receiver's bufers
  513. std::memcpy(buffer, top_msg->data(), recvd_size);
  514. // bool was_full = p_hdr->is_full();
  515. //Free top message and put it in the free message list
  516. p_hdr->free_top_msg();
  517. //If this reception changes the queue full state, notify senders
  518. // if (was_full){
  519. p_hdr->m_cond_send.notify_one();
  520. // }
  521. } //Lock end
  522. return true;
  523. }
  524. inline std::size_t message_queue::get_max_msg() const
  525. {
  526. detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
  527. return p_hdr ? p_hdr->m_max_num_msg : 0; }
  528. inline std::size_t message_queue::get_max_msg_size() const
  529. {
  530. detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
  531. return p_hdr ? p_hdr->m_max_msg_size : 0;
  532. }
  533. inline std::size_t message_queue::get_num_msg()
  534. {
  535. detail::mq_hdr_t *p_hdr = static_cast<detail::mq_hdr_t*>(m_shmem.get_user_address());
  536. if(p_hdr){
  537. //---------------------------------------------
  538. scoped_lock<interprocess_mutex> lock(p_hdr->m_mutex);
  539. //---------------------------------------------
  540. return p_hdr->m_cur_num_msg;
  541. }
  542. return 0;
  543. }
  544. inline bool message_queue::remove(const char *name)
  545. { return shared_memory_object::remove(name); }
  546. /// @endcond
  547. }} //namespace boost{ namespace interprocess{
  548. #include <boost/interprocess/detail/config_end.hpp>
  549. #endif //#ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP