PageRenderTime 58ms CodeModel.GetById 19ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

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

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