|
||||
File indexing completed on 2025-01-18 09:39:27
0001 /* 0002 * Copyright Lingxi Li 2015. 0003 * Copyright Andrey Semashev 2016. 0004 * Distributed under the Boost Software License, Version 1.0. 0005 * (See accompanying file LICENSE_1_0.txt or copy at 0006 * http://www.boost.org/LICENSE_1_0.txt) 0007 */ 0008 /*! 0009 * \file utility/ipc/reliable_message_queue.hpp 0010 * \author Lingxi Li 0011 * \author Andrey Semashev 0012 * \date 01.01.2016 0013 * 0014 * The header contains declaration of a reliable interprocess message queue. 0015 */ 0016 0017 #ifndef BOOST_LOG_UTILITY_IPC_RELIABLE_MESSAGE_QUEUE_HPP_INCLUDED_ 0018 #define BOOST_LOG_UTILITY_IPC_RELIABLE_MESSAGE_QUEUE_HPP_INCLUDED_ 0019 0020 #include <boost/log/detail/config.hpp> 0021 #include <cstddef> 0022 #include <boost/cstdint.hpp> 0023 #include <boost/move/core.hpp> 0024 #include <boost/log/keywords/open_mode.hpp> 0025 #include <boost/log/keywords/name.hpp> 0026 #include <boost/log/keywords/capacity.hpp> 0027 #include <boost/log/keywords/block_size.hpp> 0028 #include <boost/log/keywords/overflow_policy.hpp> 0029 #include <boost/log/keywords/permissions.hpp> 0030 #include <boost/log/utility/open_mode.hpp> 0031 #include <boost/log/utility/permissions.hpp> 0032 #include <boost/log/utility/ipc/object_name.hpp> 0033 #include <boost/log/detail/parameter_tools.hpp> 0034 #include <boost/log/detail/header.hpp> 0035 0036 #ifdef BOOST_HAS_PRAGMA_ONCE 0037 #pragma once 0038 #endif 0039 0040 namespace boost { 0041 0042 BOOST_LOG_OPEN_NAMESPACE 0043 0044 namespace ipc { 0045 0046 namespace aux { 0047 0048 template< typename T, typename R > 0049 struct enable_if_byte {}; 0050 template< typename R > 0051 struct enable_if_byte< char, R > { typedef R type; }; 0052 template< typename R > 0053 struct enable_if_byte< signed char, R > { typedef R type; }; 0054 template< typename R > 0055 struct enable_if_byte< unsigned char, R > { typedef R type; }; 0056 #if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603 0057 template< typename R > 0058 struct enable_if_byte< std::byte, R > { typedef R type; }; 0059 #endif 0060 0061 } // namespace aux 0062 0063 /*! 0064 * \brief A reliable interprocess message queue 0065 * 0066 * The queue implements a reliable one-way channel of passing messages from one or multiple writers to a single reader. 0067 * The format of the messages is user-defined and must be consistent across all writers and the reader. The queue does 0068 * not enforce any specific format of the messages, other than they should be supplied as a contiguous array of bytes. 0069 * 0070 * The queue internally uses a process-shared storage identified by an \c object_name (the queue name). Refer to \c object_name 0071 * documentation for details on restrictions imposed on object names. 0072 * 0073 * The queue storage is organized as a fixed number of blocks of a fixed size. The block size must be an integer power of 2 and 0074 * is expressed in bytes. Each written message, together with some metadata added by the queue, consumes an integer number 0075 * of blocks. Each read message received by the reader releases the blocks allocated for that message. As such the maximum size 0076 * of a message is slightly less than block size times capacity of the queue. For efficiency, it is recommended to choose 0077 * block size large enough to accommodate most of the messages to be passed through the queue. 0078 * 0079 * The queue is considered empty when no messages are enqueued (all blocks are free). The queue is considered full at the point 0080 * of enqueueing a message when there is not enough free blocks to accommodate the message. 0081 * 0082 * The queue is reliable in that it will not drop successfully sent messages that are not received by the reader, other than the 0083 * case when a non-empty queue is destroyed by the last user. If a message cannot be enqueued by the writer because the queue is 0084 * full, the queue can either block the writer or return an error or throw an exception, depending on the policy specified at 0085 * the queue creation. The policy is object local, i.e. different writers and the reader can have different overflow policies. 0086 * 0087 * If the queue is empty and the reader attempts to dequeue a message, it will block until a message is enqueued by a writer. 0088 * 0089 * A blocked reader or writer can be unblocked by calling \c stop_local. After this method is called, all threads blocked on 0090 * this particular object are released and return \c operation_result::aborted. The other instances of the queue (in the current 0091 * or other processes) are unaffected. In order to restore the normal functioning of the queue instance after the \c stop_local 0092 * call the user has to invoke \c reset_local. 0093 * 0094 * The queue does not guarantee any particular order of received messages from different writer threads. Messages sent by a 0095 * particular writer thread will be received in the order of sending. 0096 * 0097 * Methods of this class are not thread-safe, unless otherwise specified. 0098 */ 0099 class reliable_message_queue 0100 { 0101 public: 0102 //! Result codes for various operations on the queue 0103 enum operation_result 0104 { 0105 succeeded, //!< The operation has completed successfully 0106 no_space, //!< The message could not be sent because the queue is full 0107 aborted //!< The operation has been aborted because the queue method <tt>stop_local()</tt> has been called 0108 }; 0109 0110 //! Interprocess queue overflow policies 0111 enum overflow_policy 0112 { 0113 //! Block the send operation when the queue is full 0114 block_on_overflow, 0115 //! Return \c operation_result::no_space when the queue is full 0116 fail_on_overflow, 0117 //! Throw \c capacity_limit_reached exception when the queue is full 0118 throw_on_overflow 0119 }; 0120 0121 //! Queue message size type 0122 typedef uint32_t size_type; 0123 0124 #if !defined(BOOST_LOG_DOXYGEN_PASS) 0125 0126 BOOST_MOVABLE_BUT_NOT_COPYABLE(reliable_message_queue) 0127 0128 private: 0129 typedef void (*receive_handler)(void* state, const void* data, size_type size); 0130 0131 struct fixed_buffer_state 0132 { 0133 uint8_t* data; 0134 size_type size; 0135 }; 0136 0137 struct implementation; 0138 implementation* m_impl; 0139 0140 #endif // !defined(BOOST_LOG_DOXYGEN_PASS) 0141 0142 public: 0143 /*! 0144 * Default constructor. The method constructs an object that is not associated with any 0145 * message queue. 0146 * 0147 * \post <tt>is_open() == false</tt> 0148 */ 0149 BOOST_CONSTEXPR reliable_message_queue() BOOST_NOEXCEPT : m_impl(NULL) 0150 { 0151 } 0152 0153 /*! 0154 * Constructor. The method is used to construct an object and create the associated 0155 * message queue. The constructed object will be in running state if the message queue is 0156 * successfully created. 0157 * 0158 * \post <tt>is_open() == true</tt> 0159 * 0160 * \param name Name of the message queue to be associated with. 0161 * \param capacity Maximum number of allocation blocks the queue can hold. 0162 * \param block_size Size in bytes of allocation block. Must be a power of 2. 0163 * \param oflow_policy Queue behavior policy in case of overflow. 0164 * \param perms Access permissions for the associated message queue. 0165 */ 0166 reliable_message_queue 0167 ( 0168 open_mode::create_only_tag, 0169 object_name const& name, 0170 uint32_t capacity, 0171 size_type block_size, 0172 overflow_policy oflow_policy = block_on_overflow, 0173 permissions const& perms = permissions() 0174 ) : 0175 m_impl(NULL) 0176 { 0177 this->create(name, capacity, block_size, oflow_policy, perms); 0178 } 0179 0180 /*! 0181 * Constructor. The method is used to construct an object and create or open the associated 0182 * message queue. The constructed object will be in running state if the message queue is 0183 * successfully created or opened. If the message queue that is identified by the name already 0184 * exists then the other queue parameters are ignored. The actual queue parameters can be obtained 0185 * with accessors from the constructed object. 0186 * 0187 * \post <tt>is_open() == true</tt> 0188 * 0189 * \param name Name of the message queue to be associated with. 0190 * \param capacity Maximum number of allocation blocks the queue can hold. 0191 * \param block_size Size in bytes of allocation block. Must be a power of 2. 0192 * \param oflow_policy Queue behavior policy in case of overflow. 0193 * \param perms Access permissions for the associated message queue. 0194 */ 0195 reliable_message_queue 0196 ( 0197 open_mode::open_or_create_tag, 0198 object_name const& name, 0199 uint32_t capacity, 0200 size_type block_size, 0201 overflow_policy oflow_policy = block_on_overflow, 0202 permissions const& perms = permissions() 0203 ) : 0204 m_impl(NULL) 0205 { 0206 this->open_or_create(name, capacity, block_size, oflow_policy, perms); 0207 } 0208 0209 /*! 0210 * Constructor. The method is used to construct an object and open the existing 0211 * message queue. The constructed object will be in running state if the message queue is 0212 * successfully opened. 0213 * 0214 * \post <tt>is_open() == true</tt> 0215 * 0216 * \param name Name of the message queue to be associated with. 0217 * \param oflow_policy Queue behavior policy in case of overflow. 0218 * \param perms Access permissions for the associated message queue. The permissions will only be used 0219 * if the queue implementation has to create system objects while operating. 0220 * This parameter is currently not used on POSIX systems. 0221 */ 0222 reliable_message_queue 0223 ( 0224 open_mode::open_only_tag, 0225 object_name const& name, 0226 overflow_policy oflow_policy = block_on_overflow, 0227 permissions const& perms = permissions() 0228 ) : 0229 m_impl(NULL) 0230 { 0231 this->open(name, oflow_policy, perms); 0232 } 0233 0234 /*! 0235 * Constructor with named parameters. The method is used to construct an object and create or open 0236 * the associated message queue. The constructed object will be in running state if the message queue is 0237 * successfully created. 0238 * 0239 * The following named parameters are accepted: 0240 * 0241 * * open_mode - One of the open mode tags: \c open_mode::create_only, \c open_mode::open_only or 0242 * \c open_mode::open_or_create. 0243 * * name - Name of the message queue to be associated with. 0244 * * capacity - Maximum number of allocation blocks the queue can hold. Used only if the queue is created. 0245 * * block_size - Size in bytes of allocation block. Must be a power of 2. Used only if the queue is created. 0246 * * overflow_policy - Queue behavior policy in case of overflow, see \c overflow_policy. 0247 * * permissions - Access permissions for the associated message queue. 0248 * 0249 * \post <tt>is_open() == true</tt> 0250 */ 0251 #if !defined(BOOST_LOG_DOXYGEN_PASS) 0252 BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(reliable_message_queue, construct) 0253 #else 0254 template< typename... Args > 0255 explicit reliable_message_queue(Args const&... args); 0256 #endif 0257 0258 /*! 0259 * Destructor. Calls <tt>close()</tt>. 0260 */ 0261 ~reliable_message_queue() BOOST_NOEXCEPT 0262 { 0263 this->close(); 0264 } 0265 0266 /*! 0267 * Move constructor. The method move-constructs an object from \c other. After 0268 * the call, the constructed object becomes \c other, while \c other is left in 0269 * default constructed state. 0270 * 0271 * \param that The object to be moved. 0272 */ 0273 reliable_message_queue(BOOST_RV_REF(reliable_message_queue) that) BOOST_NOEXCEPT : 0274 m_impl(that.m_impl) 0275 { 0276 that.m_impl = NULL; 0277 } 0278 0279 /*! 0280 * Move assignment operator. If the object is associated with a message queue, 0281 * <tt>close()</tt> is first called and the precondition to calling <tt>close()</tt> 0282 * applies. After the call, the object becomes \a that while \a that is left 0283 * in default constructed state. 0284 * 0285 * \param that The object to be moved. 0286 * 0287 * \return A reference to the assigned object. 0288 */ 0289 reliable_message_queue& operator= (BOOST_RV_REF(reliable_message_queue) that) BOOST_NOEXCEPT 0290 { 0291 reliable_message_queue other(static_cast< BOOST_RV_REF(reliable_message_queue) >(that)); 0292 this->swap(other); 0293 return *this; 0294 } 0295 0296 /*! 0297 * The method swaps the object with \a that. 0298 * 0299 * \param that The other object to swap with. 0300 */ 0301 void swap(reliable_message_queue& that) BOOST_NOEXCEPT 0302 { 0303 implementation* p = m_impl; 0304 m_impl = that.m_impl; 0305 that.m_impl = p; 0306 } 0307 0308 //! Swaps the two \c reliable_message_queue objects. 0309 friend void swap(reliable_message_queue& a, reliable_message_queue& b) BOOST_NOEXCEPT 0310 { 0311 a.swap(b); 0312 } 0313 0314 /*! 0315 * The method creates the message queue to be associated with the object. After the call, 0316 * the object will be in running state if a message queue is successfully created. 0317 * 0318 * \pre <tt>is_open() == false</tt> 0319 * \post <tt>is_open() == true</tt> 0320 * 0321 * \param name Name of the message queue to be associated with. 0322 * \param capacity Maximum number of allocation blocks the queue can hold. 0323 * \param block_size Size in bytes of allocation block. Must be a power of 2. 0324 * \param oflow_policy Queue behavior policy in case of overflow. 0325 * \param perms Access permissions for the associated message queue. 0326 */ 0327 BOOST_LOG_API void create 0328 ( 0329 object_name const& name, 0330 uint32_t capacity, 0331 size_type block_size, 0332 overflow_policy oflow_policy = block_on_overflow, 0333 permissions const& perms = permissions() 0334 ); 0335 0336 /*! 0337 * The method creates or opens the message queue to be associated with the object. 0338 * After the call, the object will be in running state if a message queue is successfully 0339 * created or opened. If the message queue that is identified by the name already exists then 0340 * the other queue parameters are ignored. The actual queue parameters can be obtained 0341 * with accessors from this object after this method returns. 0342 * 0343 * \pre <tt>is_open() == false</tt> 0344 * \post <tt>is_open() == true</tt> 0345 * 0346 * \param name Name of the message queue to be associated with. 0347 * \param capacity Maximum number of allocation blocks the queue can hold. 0348 * \param block_size Size in bytes of allocation block. Must be a power of 2. 0349 * \param oflow_policy Queue behavior policy in case of overflow. 0350 * \param perms Access permissions for the associated message queue. 0351 */ 0352 BOOST_LOG_API void open_or_create 0353 ( 0354 object_name const& name, 0355 uint32_t capacity, 0356 size_type block_size, 0357 overflow_policy oflow_policy = block_on_overflow, 0358 permissions const& perms = permissions() 0359 ); 0360 0361 /*! 0362 * The method opens the existing message queue to be associated with the object. 0363 * After the call, the object will be in running state if a message queue is successfully 0364 * opened. 0365 * 0366 * \pre <tt>is_open() == false</tt> 0367 * \post <tt>is_open() == true</tt> 0368 * 0369 * \param name Name of the message queue to be associated with. 0370 * \param oflow_policy Queue behavior policy in case of overflow. 0371 * \param perms Access permissions for the associated message queue. The permissions will only be used 0372 * if the queue implementation has to create system objects while operating. 0373 * This parameter is currently not used on POSIX systems. 0374 */ 0375 BOOST_LOG_API void open 0376 ( 0377 object_name const& name, 0378 overflow_policy oflow_policy = block_on_overflow, 0379 permissions const& perms = permissions() 0380 ); 0381 0382 /*! 0383 * Tests whether the object is associated with any message queue. 0384 * 0385 * \return \c true if the object is associated with a message queue, and \c false otherwise. 0386 */ 0387 bool is_open() const BOOST_NOEXCEPT 0388 { 0389 return m_impl != NULL; 0390 } 0391 0392 /*! 0393 * This method empties the associated message queue. Concurrent calls to this method, <tt>send()</tt>, 0394 * <tt>try_send()</tt>, <tt>receive()</tt>, <tt>try_receive()</tt>, and <tt>stop_local()</tt> are allowed. 0395 * 0396 * \pre <tt>is_open() == true</tt> 0397 */ 0398 BOOST_LOG_API void clear(); 0399 0400 /*! 0401 * The method returns the name of the associated message queue. 0402 * 0403 * \pre <tt>is_open() == true</tt> 0404 * 0405 * \return Name of the associated message queue 0406 */ 0407 BOOST_LOG_API object_name const& name() const; 0408 0409 /*! 0410 * The method returns the maximum number of allocation blocks the associated message queue 0411 * can hold. Note that the returned value may be different from the corresponding 0412 * value passed to the constructor or <tt>open_or_create()</tt>, for the message queue may 0413 * not have been created by this object. 0414 * 0415 * \pre <tt>is_open() == true</tt> 0416 * 0417 * \return Maximum number of allocation blocks the associated message queue can hold. 0418 */ 0419 BOOST_LOG_API uint32_t capacity() const; 0420 0421 /*! 0422 * The method returns the allocation block size, in bytes. Each message in the 0423 * associated message queue consumes an integer number of allocation blocks. 0424 * Note that the returned value may be different from the corresponding value passed 0425 * to the constructor or <tt>open_or_create()</tt>, for the message queue may not 0426 * have been created by this object. 0427 * 0428 * \pre <tt>is_open() == true</tt> 0429 * 0430 * \return Allocation block size, in bytes. 0431 */ 0432 BOOST_LOG_API size_type block_size() const; 0433 0434 /*! 0435 * The method wakes up all threads that are blocked in calls to <tt>send()</tt> or 0436 * <tt>receive()</tt>. Those calls would then return <tt>operation_result::aborted</tt>. 0437 * Note that, the method does not block until the woken-up threads have actually 0438 * returned from <tt>send()</tt> or <tt>receive()</tt>. Other means is needed to ensure 0439 * that calls to <tt>send()</tt> or <tt>receive()</tt> have returned, e.g., joining the 0440 * threads that might be blocking on the calls. 0441 * 0442 * The method also puts the object in stopped state. When in stopped state, calls to 0443 * <tt>send()</tt> or <tt>receive()</tt> will return immediately with return value 0444 * <tt>operation_result::aborted</tt> when they would otherwise block in running state. 0445 * 0446 * Concurrent calls to this method, <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, 0447 * <tt>try_receive()</tt>, and <tt>clear()</tt> are allowed. 0448 * 0449 * \pre <tt>is_open() == true</tt> 0450 */ 0451 BOOST_LOG_API void stop_local(); 0452 0453 /*! 0454 * The method puts the object in running state where calls to <tt>send()</tt> or 0455 * <tt>receive()</tt> may block. This method is not thread-safe. 0456 * 0457 * \pre <tt>is_open() == true</tt> 0458 */ 0459 BOOST_LOG_API void reset_local(); 0460 0461 /*! 0462 * The method disassociates the associated message queue, if any. No other threads 0463 * should be using this object before calling this method. The <tt>stop_local()</tt> method 0464 * can be used to have any threads currently blocked in <tt>send()</tt> or 0465 * <tt>receive()</tt> return, and prevent further calls to them from blocking. Typically, 0466 * before calling this method, one would first call <tt>stop_local()</tt> and then join all 0467 * threads that might be blocking on <tt>send()</tt> or <tt>receive()</tt> to ensure that 0468 * they have returned from the calls. The associated message queue is destroyed if the 0469 * object represents the last outstanding reference to it. 0470 * 0471 * \post <tt>is_open() == false</tt> 0472 */ 0473 void close() BOOST_NOEXCEPT 0474 { 0475 if (is_open()) 0476 do_close(); 0477 } 0478 0479 /*! 0480 * The method sends a message to the associated message queue. When the object is in 0481 * running state and the queue has no free space for the message, the method either blocks 0482 * or throws an exception, depending on the overflow policy that was specified on the queue 0483 * opening/creation. If blocking policy is in effect, the blocking can be interrupted by 0484 * calling <tt>stop_local()</tt>, in which case the method returns \c operation_result::aborted. 0485 * When the object is already in the stopped state, the method does not block but returns 0486 * immediately with return value \c operation_result::aborted. 0487 * 0488 * It is possible to send an empty message by passing \c 0 to the parameter \c message_size. 0489 * 0490 * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, <tt>try_receive()</tt>, 0491 * <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed. 0492 * 0493 * \pre <tt>is_open() == true</tt> 0494 * 0495 * \param message_data The message data to send. Ignored when \c message_size is \c 0. 0496 * \param message_size Size of the message data in bytes. If the size is larger than 0497 * the associated message queue capacity, an <tt>std::logic_error</tt> exception is thrown. 0498 * 0499 * \retval operation_result::succeeded if the operation is successful 0500 * \retval operation_result::no_space if \c overflow_policy::fail_on_overflow is in effect and the queue is full 0501 * \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt> 0502 * 0503 * <b>Throws:</b> <tt>std::logic_error</tt> in case if the message size exceeds the queue 0504 * capacity, <tt>system_error</tt> in case if a native OS method fails. 0505 */ 0506 BOOST_LOG_API operation_result send(void const* message_data, size_type message_size); 0507 0508 /*! 0509 * The method performs an attempt to send a message to the associated message queue. 0510 * The method is non-blocking, and always returns immediately. 0511 * <tt>boost::system::system_error</tt> is thrown for errors resulting from native 0512 * operating system calls. Note that it is possible to send an empty message by passing 0513 * \c 0 to the parameter \c message_size. Concurrent calls to <tt>send()</tt>, 0514 * <tt>try_send()</tt>, <tt>receive()</tt>, <tt>try_receive()</tt>, <tt>stop_local()</tt>, 0515 * and <tt>clear()</tt> are allowed. 0516 * 0517 * \pre <tt>is_open() == true</tt> 0518 * 0519 * \param message_data The message data to send. Ignored when \c message_size is \c 0. 0520 * \param message_size Size of the message data in bytes. If the size is larger than the 0521 * maximum size allowed by the associated message queue, an 0522 * <tt>std::logic_error</tt> exception is thrown. 0523 * 0524 * \return \c true if the message is successfully sent, and \c false otherwise (e.g., 0525 * when the queue is full). 0526 * 0527 * <b>Throws:</b> <tt>std::logic_error</tt> in case if the message size exceeds the queue 0528 * capacity, <tt>system_error</tt> in case if a native OS method fails. 0529 */ 0530 BOOST_LOG_API bool try_send(void const* message_data, size_type message_size); 0531 0532 /*! 0533 * The method takes a message from the associated message queue. When the object is in 0534 * running state and the queue is empty, the method blocks. The blocking is interrupted 0535 * when <tt>stop_local()</tt> is called, in which case the method returns \c operation_result::aborted. 0536 * When the object is already in the stopped state and the queue is empty, the method 0537 * does not block but returns immediately with return value \c operation_result::aborted. 0538 * 0539 * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, 0540 * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed. 0541 * 0542 * \pre <tt>is_open() == true</tt> 0543 * 0544 * \param buffer The memory buffer to store the received message in. 0545 * \param buffer_size The size of the buffer, in bytes. 0546 * \param message_size Receives the size of the received message, in bytes. 0547 * 0548 * \retval operation_result::succeeded if the operation is successful 0549 * \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt> 0550 */ 0551 operation_result receive(void* buffer, size_type buffer_size, size_type& message_size) 0552 { 0553 fixed_buffer_state state = { static_cast< uint8_t* >(buffer), buffer_size }; 0554 operation_result result = do_receive(&reliable_message_queue::fixed_buffer_receive_handler, &state); 0555 message_size = buffer_size - state.size; 0556 return result; 0557 } 0558 0559 /*! 0560 * The method takes a message from the associated message queue. When the object is in 0561 * running state and the queue is empty, the method blocks. The blocking is interrupted 0562 * when <tt>stop_local()</tt> is called, in which case the method returns \c operation_result::aborted. 0563 * When the object is already in the stopped state and the queue is empty, the method 0564 * does not block but returns immediately with return value \c operation_result::aborted. 0565 * 0566 * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, 0567 * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed. 0568 * 0569 * \pre <tt>is_open() == true</tt> 0570 * 0571 * \param buffer The memory buffer to store the received message in. 0572 * \param message_size Receives the size of the received message, in bytes. 0573 * 0574 * \retval operation_result::succeeded if the operation is successful 0575 * \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt> 0576 */ 0577 template< typename ElementT, size_type SizeV > 0578 #if !defined(BOOST_LOG_DOXYGEN_PASS) 0579 typename aux::enable_if_byte< ElementT, operation_result >::type 0580 #else 0581 operation_result 0582 #endif 0583 receive(ElementT (&buffer)[SizeV], size_type& message_size) 0584 { 0585 return receive(buffer, SizeV, message_size); 0586 } 0587 0588 /*! 0589 * The method takes a message from the associated message queue. When the object is in 0590 * running state and the queue is empty, the method blocks. The blocking is interrupted 0591 * when <tt>stop_local()</tt> is called, in which case the method returns \c operation_result::aborted. 0592 * When the object is already in the stopped state and the queue is empty, the method 0593 * does not block but returns immediately with return value \c operation_result::aborted. 0594 * 0595 * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, 0596 * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed. 0597 * 0598 * \pre <tt>is_open() == true</tt> 0599 * 0600 * \param container The container to store the received message in. The container should have 0601 * value type of <tt>char</tt>, <tt>signed char</tt> or <tt>unsigned char</tt> 0602 * and support inserting elements at the end. 0603 * 0604 * \retval operation_result::succeeded if the operation is successful 0605 * \retval operation_result::aborted if the call was interrupted by <tt>stop_local()</tt> 0606 */ 0607 template< typename ContainerT > 0608 #if !defined(BOOST_LOG_DOXYGEN_PASS) 0609 typename aux::enable_if_byte< typename ContainerT::value_type, operation_result >::type 0610 #else 0611 operation_result 0612 #endif 0613 receive(ContainerT& container) 0614 { 0615 return do_receive(&reliable_message_queue::container_receive_handler< ContainerT >, &container); 0616 } 0617 0618 /*! 0619 * The method performs an attempt to take a message from the associated message queue. The 0620 * method is non-blocking, and always returns immediately. 0621 * 0622 * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, 0623 * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed. 0624 * 0625 * \pre <tt>is_open() == true</tt> 0626 * 0627 * \param buffer The memory buffer to store the received message in. 0628 * \param buffer_size The size of the buffer, in bytes. 0629 * \param message_size Receives the size of the received message, in bytes. 0630 * 0631 * \return \c true if a message is successfully received, and \c false otherwise (e.g., 0632 * when the queue is empty). 0633 */ 0634 bool try_receive(void* buffer, size_type buffer_size, size_type& message_size) 0635 { 0636 fixed_buffer_state state = { static_cast< uint8_t* >(buffer), buffer_size }; 0637 bool result = do_try_receive(&reliable_message_queue::fixed_buffer_receive_handler, &state); 0638 message_size = buffer_size - state.size; 0639 return result; 0640 } 0641 0642 /*! 0643 * The method performs an attempt to take a message from the associated message queue. The 0644 * method is non-blocking, and always returns immediately. 0645 * 0646 * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, 0647 * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed. 0648 * 0649 * \pre <tt>is_open() == true</tt> 0650 * 0651 * \param buffer The memory buffer to store the received message in. 0652 * \param message_size Receives the size of the received message, in bytes. 0653 * 0654 * \return \c true if a message is successfully received, and \c false otherwise (e.g., 0655 * when the queue is empty). 0656 */ 0657 template< typename ElementT, size_type SizeV > 0658 #if !defined(BOOST_LOG_DOXYGEN_PASS) 0659 typename aux::enable_if_byte< ElementT, bool >::type 0660 #else 0661 bool 0662 #endif 0663 try_receive(ElementT (&buffer)[SizeV], size_type& message_size) 0664 { 0665 return try_receive(buffer, SizeV, message_size); 0666 } 0667 0668 /*! 0669 * The method performs an attempt to take a message from the associated message queue. The 0670 * method is non-blocking, and always returns immediately. 0671 * 0672 * Concurrent calls to <tt>send()</tt>, <tt>try_send()</tt>, <tt>receive()</tt>, 0673 * <tt>try_receive()</tt>, <tt>stop_local()</tt>, and <tt>clear()</tt> are allowed. 0674 * 0675 * \pre <tt>is_open() == true</tt> 0676 * 0677 * \param container The container to store the received message in. The container should have 0678 * value type of <tt>char</tt>, <tt>signed char</tt> or <tt>unsigned char</tt> 0679 * and support inserting elements at the end. 0680 * 0681 * \return \c true if a message is successfully received, and \c false otherwise (e.g., 0682 * when the queue is empty). 0683 */ 0684 template< typename ContainerT > 0685 #if !defined(BOOST_LOG_DOXYGEN_PASS) 0686 typename aux::enable_if_byte< typename ContainerT::value_type, bool >::type 0687 #else 0688 bool 0689 #endif 0690 try_receive(ContainerT& container) 0691 { 0692 return do_try_receive(&reliable_message_queue::container_receive_handler< ContainerT >, &container); 0693 } 0694 0695 /*! 0696 * The method frees system-wide resources, associated with the interprocess queue with the supplied name. 0697 * The queue referred to by the specified name must not be opened in any process at the point of this call. 0698 * After this call succeeds a new queue with the specified name can be created. 0699 * 0700 * This call can be useful to recover from an earlier process misbehavior (e.g. a crash without properly 0701 * closing the message queue). In this case resources allocated for the interprocess queue may remain 0702 * allocated after the last process closed the queue, which in turn may prevent creating a new queue with 0703 * the same name. By calling this method before creating a queue the application can attempt to ensure 0704 * it starts with a clean slate. 0705 * 0706 * On some platforms resources associated with the queue are automatically reclaimed by the operating system 0707 * when the last process using those resources terminates (even if it terminates abnormally). On these 0708 * platforms this call may be a no-op. However, portable code should still call this method at appropriate 0709 * places to ensure compatibility with other platforms and future library versions, which may change implementation 0710 * of the queue. 0711 * 0712 * \param name Name of the message queue to be removed. 0713 */ 0714 static BOOST_LOG_API void remove(object_name const& name); 0715 0716 #if !defined(BOOST_LOG_DOXYGEN_PASS) 0717 private: 0718 //! Implementation of the constructor with named arguments 0719 template< typename ArgsT > 0720 void construct(ArgsT const& args) 0721 { 0722 m_impl = NULL; 0723 construct_dispatch(args[keywords::open_mode], args); 0724 } 0725 0726 //! Implementation of the constructor with named arguments 0727 template< typename ArgsT > 0728 void construct_dispatch(open_mode::create_only_tag, ArgsT const& args) 0729 { 0730 this->create(args[keywords::name], args[keywords::capacity], args[keywords::block_size], args[keywords::overflow_policy | block_on_overflow], args[keywords::permissions | permissions()]); 0731 } 0732 0733 //! Implementation of the constructor with named arguments 0734 template< typename ArgsT > 0735 void construct_dispatch(open_mode::open_or_create_tag, ArgsT const& args) 0736 { 0737 this->open_or_create(args[keywords::name], args[keywords::capacity], args[keywords::block_size], args[keywords::overflow_policy | block_on_overflow], args[keywords::permissions | permissions()]); 0738 } 0739 0740 //! Implementation of the constructor with named arguments 0741 template< typename ArgsT > 0742 void construct_dispatch(open_mode::open_only_tag, ArgsT const& args) 0743 { 0744 this->open(args[keywords::name], args[keywords::overflow_policy | block_on_overflow], args[keywords::permissions | permissions()]); 0745 } 0746 0747 //! Closes the message queue, if it's open 0748 BOOST_LOG_API void do_close() BOOST_NOEXCEPT; 0749 0750 //! Receives the message from the queue and calls the handler to place the data in the user's storage 0751 BOOST_LOG_API operation_result do_receive(receive_handler handler, void* state); 0752 //! Attempts to receives the message from the queue and calls the handler to place the data in the user's storage 0753 BOOST_LOG_API bool do_try_receive(receive_handler handler, void* state); 0754 0755 //! Fixed buffer receive handler 0756 static BOOST_LOG_API void fixed_buffer_receive_handler(void* state, const void* data, size_type size); 0757 //! Receive handler for a container 0758 template< typename ContainerT > 0759 static void container_receive_handler(void* state, const void* data, size_type size) 0760 { 0761 ContainerT* const container = static_cast< ContainerT* >(state); 0762 container->insert 0763 ( 0764 container->end(), 0765 static_cast< typename ContainerT::value_type const* >(data), 0766 static_cast< typename ContainerT::value_type const* >(data) + size 0767 ); 0768 } 0769 #endif 0770 }; 0771 0772 } // namespace ipc 0773 0774 BOOST_LOG_CLOSE_NAMESPACE // namespace log 0775 0776 } // namespace boost 0777 0778 #include <boost/log/detail/footer.hpp> 0779 0780 #endif // BOOST_LOG_UTILITY_IPC_RELIABLE_MESSAGE_QUEUE_HPP_INCLUDED_
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |