/* -*- C++ -*- */ //============================================================================= /** * @file Message_Queue_T.h * * @author Douglas C. Schmidt */ //============================================================================= #ifndef ACE_MESSAGE_QUEUE_T_H #define ACE_MESSAGE_QUEUE_T_H #include /**/ "ace/pre.h" #include "ace/Message_Queue.h" #include "ace/Dynamic_Message_Strategy.h" #include "ace/Synch_Traits.h" #include "ace/Guard_T.h" #include "ace/Time_Policy.h" #include "ace/Time_Value_T.h" #if defined (ACE_HAS_THREADS) # include "ace/Condition_Attributes.h" #endif #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ ACE_BEGIN_VERSIONED_NAMESPACE_DECL #if defined (ACE_VXWORKS) class ACE_Message_Queue_Vx; #endif /* defined (ACE_VXWORKS) */ #if defined (ACE_HAS_WIN32_OVERLAPPED_IO) class ACE_Message_Queue_NT; #endif /* ACE_HAS_WIN32_OVERLAPPED_IO*/ #if defined (ACE_HAS_MONITOR_POINTS) && ACE_HAS_MONITOR_POINTS == 1 namespace ACE { namespace Monitor_Control { class Size_Monitor; } } #endif /* ACE_HAS_MONITOR_POINTS==1 */ /** * @class ACE_Message_Queue * * @brief A message queuing facility with parameterized synchronization * capability. ACE_Message_Queue is modeled after the queueing facilities * in System V STREAMs. * * ACE_Message_Queue is the primary queuing facility for * messages in the ACE framework. It's one template argument parameterizes * the queue's synchronization. The argument specifies a synchronization * strategy. The two main strategies available for ACE_SYNCH_DECL are: * -# ACE_MT_SYNCH: all operations are thread-safe * -# ACE_NULL_SYNCH: no synchronization and no locking overhead * * All data passing through ACE_Message_Queue is in the form of * ACE_Message_Block objects. @sa ACE_Message_Block. */ template class ACE_Message_Queue : public ACE_Message_Queue_Base { public: friend class ACE_Message_Queue_Iterator; friend class ACE_Message_Queue_Reverse_Iterator; // = Traits typedef ACE_Message_Queue_Iterator ITERATOR; typedef ACE_Message_Queue_Reverse_Iterator REVERSE_ITERATOR; /** * @name Initialization methods */ //@{ /** * Initialize an ACE_Message_Queue. * * @param hwm High water mark. Determines how many bytes can be stored in a * queue before it's considered full. Supplier threads must block * until the queue is no longer full. * @param lwm Low water mark. Determines how many bytes must be in the queue * before supplier threads are allowed to enqueue additional * data. By default, the @a hwm equals @a lwm, which means * that suppliers will be able to enqueue new messages as soon as * a consumer removes any message from the queue. Making the low * water mark smaller than the high water mark forces consumers to * drain more messages from the queue before suppliers can enqueue * new messages, which can minimize the "silly window syndrome." * @param ns Notification strategy. Pointer to an object conforming to the * ACE_Notification_Strategy interface. If set, the object's * notify() method will be called each time data is added to * this ACE_Message_Queue. @see ACE_Reactor_Notification_Strategy. */ ACE_Message_Queue (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM, size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM, ACE_Notification_Strategy *ns = 0); virtual int open (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM, size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM, ACE_Notification_Strategy *ns = 0); //@} /// Releases all resources from the message queue and marks it deactivated. /// @sa flush(). /// /// @retval The number of messages released from the queue; -1 on error. virtual int close (); /// Releases all resources from the message queue and marks it deactivated. virtual ~ACE_Message_Queue (); /** * Releases all resources from the message queue but does not mark it * deactivated. This method holds the queue lock during this operation. * @sa close(). * * @return The number of messages flushed; -1 on error. */ virtual int flush (); /** * Release all resources from the message queue but do not mark it * as deactivated. * * @pre The caller must be holding the queue lock before calling this * method. * * @return The number of messages flushed. */ virtual int flush_i (); /** @name Enqueue and dequeue methods * * The enqueue and dequeue methods accept a timeout value passed as * an ACE_Time_Value *. In all cases, if the timeout pointer is 0, * the caller will block until action is possible. If the timeout pointer * is non-zero, the call will wait (if needed, subject to water mark * settings) until the absolute time specified in the referenced * ACE_Time_Value object is reached. If the time is reached before the * desired action is possible, the method will return -1 with errno set * to @c EWOULDBLOCK. Regardless of the timeout setting, however, * these methods will also fail and return -1 when the queue is closed, * deactivated, pulsed, or when a signal occurs. * * See C++NPv2 Section 6.2 and APG Section 12.3 for a fuller treatment of * ACE_Message_Queue, enqueueing, dequeueing, and how these operations are * affected by queue state transitions. */ //@{ /** * Retrieve a pointer to the first ACE_Message_Block in the queue * without removing it. * * @note Because the block whose pointer is returned is still on the queue, * another thread may dequeue the referenced block at any time, * including before the calling thread examines the peeked-at block. * Be very careful with this method in multithreaded queueing * situations. * * @param first_item Reference to an ACE_Message_Block * that will * point to the first block on the queue. The block * remains on the queue until this or another thread * dequeues it. * @param timeout The absolute time the caller will wait until * for a block to be queued. * * @retval >0 The number of ACE_Message_Blocks on the queue. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int peek_dequeue_head (ACE_Message_Block *&first_item, ACE_Time_Value *timeout = 0); /** * Enqueue an ACE_Message_Block into the queue in accordance with * the ACE_Message_Block's priority (0 is lowest priority). FIFO * order is maintained when messages of the same priority are * inserted consecutively. * * @param new_item Pointer to an ACE_Message_Block that will be * added to the queue. The block's @c msg_priority() * method will be called to obtain the queueing priority. * @param timeout The absolute time the caller will wait until * for the block to be queued. * * @retval >0 The number of ACE_Message_Blocks on the queue after adding * the specified block. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int enqueue_prio (ACE_Message_Block *new_item, ACE_Time_Value *timeout = 0); /** * Enqueue an ACE_Message_Block into the queue in accordance with the * block's deadline time. FIFO order is maintained when messages of * the same deadline time are inserted consecutively. * * @param new_item Pointer to an ACE_Message_Block that will be * added to the queue. The block's @c msg_deadline_time() * method will be called to obtain the relative queueing * position. * @param timeout The absolute time the caller will wait until * for the block to be queued. * * @retval >0 The number of ACE_Message_Blocks on the queue after adding * the specified block. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int enqueue_deadline (ACE_Message_Block *new_item, ACE_Time_Value *timeout = 0); /** * @deprecated This is an alias for enqueue_prio(). It's only here for * backwards compatibility and will go away in a subsequent release. * Please use enqueue_prio() instead. */ virtual int enqueue (ACE_Message_Block *new_item, ACE_Time_Value *timeout = 0); /** * Enqueue one or more ACE_Message_Block objects at the tail of the queue. * If the @a new_item @c next() pointer is non-zero, it is assumed to be the * start of a series of ACE_Message_Block objects connected via their * @c next() pointers. The series of blocks will be added to the queue in * the same order they are passed in as. * * @param new_item Pointer to an ACE_Message_Block that will be * added to the queue. If the block's @c next() pointer * is non-zero, all blocks chained from the @c next() * pointer are enqueued as well. * @param timeout The absolute time the caller will wait until * for the block to be queued. * * @retval >0 The number of ACE_Message_Blocks on the queue after adding * the specified block(s). * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int enqueue_tail (ACE_Message_Block *new_item, ACE_Time_Value *timeout = 0); /** * Enqueue one or more ACE_Message_Block objects at the head of the queue. * If the @a new_item @c next() pointer is non-zero, it is assumed to be the * start of a series of ACE_Message_Block objects connected via their * @c next() pointers. The series of blocks will be added to the queue in * the same order they are passed in as. * * @param new_item Pointer to an ACE_Message_Block that will be * added to the queue. If the block's @c next() pointer * is non-zero, all blocks chained from the @c next() * pointer are enqueued as well. * @param timeout The absolute time the caller will wait until * for the block to be queued. * * @retval >0 The number of ACE_Message_Blocks on the queue after adding * the specified block(s). * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int enqueue_head (ACE_Message_Block *new_item, ACE_Time_Value *timeout = 0); /// This method is an alias for the dequeue_head() method. virtual int dequeue (ACE_Message_Block *&first_item, ACE_Time_Value *timeout = 0); /** * Dequeue the ACE_Message_Block at the head of the queue and return * a pointer to the dequeued block. * * @param first_item Reference to an ACE_Message_Block * that will * be set to the address of the dequeued block. * @param timeout The absolute time the caller will wait until * for a block to be dequeued. * * @retval >=0 The number of ACE_Message_Blocks remaining in the queue. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int dequeue_head (ACE_Message_Block *&first_item, ACE_Time_Value *timeout = 0); /** * Dequeue the ACE_Message_Block that has the lowest priority (preserves * FIFO order for messages with the same priority) and return a pointer * to the dequeued block. * * @param first_item Reference to an ACE_Message_Block * that will * be set to the address of the dequeued block. * @param timeout The absolute time the caller will wait until * for a block to be dequeued. * * @retval >=0 The number of ACE_Message_Blocks remaining in the queue. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int dequeue_prio (ACE_Message_Block *&first_item, ACE_Time_Value *timeout = 0); /** * Dequeue the ACE_Message_Block at the tail of the queue and return * a pointer to the dequeued block. * * @param dequeued Reference to an ACE_Message_Block * that will * be set to the address of the dequeued block. * @param timeout The absolute time the caller will wait until * for a block to be dequeued. * * @retval >=0 The number of ACE_Message_Blocks remaining in the queue. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int dequeue_tail (ACE_Message_Block *&dequeued, ACE_Time_Value *timeout = 0); /** * Dequeue the ACE_Message_Block with the earliest deadline time and return * a pointer to the dequeued block. * * @param dequeued Reference to an ACE_Message_Block * that will * be set to the address of the dequeued block. * @param timeout The absolute time the caller will wait until * for a block to be dequeued. * * @retval >=0 The number of ACE_Message_Blocks remaining in the queue. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int dequeue_deadline (ACE_Message_Block *&dequeued, ACE_Time_Value *timeout = 0); //@} /** @name Queue statistics methods */ //@{ /// True if queue is full, else false. virtual bool is_full (); /// True if queue is empty, else false. virtual bool is_empty (); /** * Number of total bytes on the queue, i.e., sum of the message * block sizes. */ virtual size_t message_bytes (); /** * Number of total length on the queue, i.e., sum of the message * block lengths. */ virtual size_t message_length (); /** * Number of total messages on the queue. */ virtual size_t message_count (); // = Manual changes to these stats (used when queued message blocks // change size or lengths). /** * New value of the number of total bytes on the queue, i.e., sum of * the message block sizes. */ virtual void message_bytes (size_t new_size); /** * New value of the number of total length on the queue, i.e., sum * of the message block lengths. */ virtual void message_length (size_t new_length); //@} /** @name Water mark (flow control) methods */ //@{ /** * Get high watermark. */ virtual size_t high_water_mark (); /** * Set the high watermark, which determines how many bytes can be * stored in a queue before it's considered "full." */ virtual void high_water_mark (size_t hwm); /** * Get low watermark. */ virtual size_t low_water_mark (); /** * Set the low watermark, which determines how many bytes must be in * the queue before supplier threads are allowed to enqueue * additional ACE_Message_Blocks. */ virtual void low_water_mark (size_t lwm); //@} /** @name Activation and queue state methods * See C++NPv2 Section 6.2 and APG Section 12.3 for a fuller treatment of * queue states and transitions and how the transitions affect message * enqueueing and dequeueing operations. */ //@{ /** * Deactivate the queue and wakeup all threads waiting on the queue * so they can continue. No messages are removed from the queue, * however. Any other operations called until the queue is * activated again will immediately return -1 with @c errno == * ESHUTDOWN. Returns WAS_INACTIVE if queue was inactive before the * call and WAS_ACTIVE if queue was active before the call. */ virtual int deactivate (); /** * Reactivate the queue so that threads can enqueue and dequeue * messages again. Returns the state of the queue before the call. */ virtual int activate (); /** * Pulse the queue to wake up any waiting threads. Changes the * queue state to PULSED; future enqueue/dequeue operations proceed * as in ACTIVATED state. * * @return The queue's state before this call. */ virtual int pulse (); /// Returns the current state of the queue, which can be one of /// ACTIVATED, DEACTIVATED, or PULSED. virtual int state (); /// Returns true if the state of the queue is , /// but false if the queue's is or . virtual int deactivated (); //@} /** @name Notification strategy methods */ //@{ /** * This hook is automatically invoked by , * , and when a new item is inserted * into the queue. Subclasses can override this method to perform * specific notification strategies (e.g., signaling events for a * , notifying a , etc.). In a * multi-threaded application with concurrent consumers, there is no * guarantee that the queue will be still be non-empty by the time * the notification occurs. */ virtual int notify (); /// Get the notification strategy for the virtual ACE_Notification_Strategy *notification_strategy (); /// Set the notification strategy for the virtual void notification_strategy (ACE_Notification_Strategy *s); //@} /// Returns a reference to the lock used by the ACE_Message_Queue. virtual ACE_SYNCH_MUTEX_T &lock (); /// Get the current time of day according to the queue's TIME_POLICY. /// Allows users to initialize timeout values using correct time policy. ACE_Time_Value_T gettimeofday () const; /// Allows applications to control how the timer queue gets the time /// of day. void set_time_policy (TIME_POLICY const & time_policy); /// Dump the state of an object. virtual void dump () const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: // = Routines that actually do the enqueueing and dequeueing. // These routines assume that locks are held by the corresponding // public methods. Since they are virtual, you can change the // queueing mechanism by subclassing from ACE_Message_Queue. /// Enqueue an in accordance with its priority. virtual int enqueue_i (ACE_Message_Block *new_item); /// Enqueue an in accordance with its deadline time. virtual int enqueue_deadline_i (ACE_Message_Block *new_item); /// Enqueue an at the end of the queue. virtual int enqueue_tail_i (ACE_Message_Block *new_item); /// Enqueue an at the head of the queue. virtual int enqueue_head_i (ACE_Message_Block *new_item); /// Dequeue and return the at the head of the /// queue. virtual int dequeue_head_i (ACE_Message_Block *&first_item); /// Dequeue and return the with the lowest /// priority. virtual int dequeue_prio_i (ACE_Message_Block *&dequeued); /// Dequeue and return the at the tail of the /// queue. virtual int dequeue_tail_i (ACE_Message_Block *&first_item); /// Dequeue and return the with the lowest /// deadline time. virtual int dequeue_deadline_i (ACE_Message_Block *&first_item); // = Check the boundary conditions (assumes locks are held). /// True if queue is full, else false. virtual bool is_full_i (); /// True if queue is empty, else false. virtual bool is_empty_i (); // = Implementation of the public and methods. // These methods assume locks are held. /** * Notifies all waiting threads that the queue has been deactivated * so they can wakeup and continue other processing. * No messages are removed from the queue. * * @param pulse If 0, the queue's state is changed to DEACTIVATED * and any other operations called until the queue is * reactivated will immediately return -1 with * errno == ESHUTDOWN. * If not zero, only the waiting threads are notified and * the queue's state changes to PULSED. * * @return The state of the queue before the call. */ virtual int deactivate_i (int pulse = 0); /// Activate the queue. virtual int activate_i (); // = Helper methods to factor out common #ifdef code. /// Wait for the queue to become non-full. virtual int wait_not_full_cond (ACE_Time_Value *timeout); /// Wait for the queue to become non-empty. virtual int wait_not_empty_cond (ACE_Time_Value *timeout); /// Inform any threads waiting to enqueue that they can procede. virtual int signal_enqueue_waiters (); /// Inform any threads waiting to dequeue that they can procede. virtual int signal_dequeue_waiters (); /// Pointer to head of ACE_Message_Block list. ACE_Message_Block *head_; /// Pointer to tail of ACE_Message_Block list. ACE_Message_Block *tail_; /// Lowest number before unblocking occurs. size_t low_water_mark_; /// Greatest number of bytes before blocking. size_t high_water_mark_; /// Current number of bytes in the queue. size_t cur_bytes_; /// Current length of messages in the queue. size_t cur_length_; /// Current number of messages in the queue. size_t cur_count_; /// The notification strategy used when a new message is enqueued. ACE_Notification_Strategy *notification_strategy_; // = Synchronization primitives for controlling concurrent access. /// Protect queue from concurrent access. ACE_SYNCH_MUTEX_T lock_; #if defined (ACE_HAS_THREADS) /// Attributes to initialize conditions with. /* We only need this because some crappy compilers can't properly handle initializing the conditions with temporary objects. */ ACE_Condition_Attributes_T cond_attr_; #endif /// Used to make threads sleep until the queue is no longer empty. ACE_SYNCH_CONDITION_T not_empty_cond_; /// Used to make threads sleep until the queue is no longer full. ACE_SYNCH_CONDITION_T not_full_cond_; /// The policy to return the current time of day TIME_POLICY time_policy_; /// Sends the size of the queue whenever it changes. #if defined (ACE_HAS_MONITOR_POINTS) && (ACE_HAS_MONITOR_POINTS == 1) ACE::Monitor_Control::Size_Monitor *monitor_; #endif private: // = Disallow these operations. void operator= (const ACE_Message_Queue &) = delete; ACE_Message_Queue (const ACE_Message_Queue &) = delete; }; // This typedef is used to get around a compiler bug in g++/vxworks. typedef ACE_Message_Queue ACE_DEFAULT_MESSAGE_QUEUE_TYPE; /** * @class ACE_Message_Queue_Iterator * * @brief Iterator for the ACE_Message_Queue. */ template class ACE_Message_Queue_Iterator { public: ACE_Message_Queue_Iterator (ACE_Message_Queue &queue); // = Iteration methods. /// Pass back the @a entry that hasn't been seen in the queue. /// Returns 0 when all items have been seen, else 1. int next (ACE_Message_Block *&entry); /// Returns 1 when all items have been seen, else 0. int done () const; /// Move forward by one element in the queue. Returns 0 when all the /// items in the set have been seen, else 1. int advance (); /// Dump the state of an object. void dump () const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; private: /// Message_Queue we are iterating over. ACE_Message_Queue &queue_; protected: /// Keeps track of how far we've advanced... ACE_Message_Block *curr_; }; /** * @class ACE_Message_Queue_Reverse_Iterator * * @brief Reverse Iterator for the ACE_Message_Queue. */ template class ACE_Message_Queue_Reverse_Iterator { public: ACE_Message_Queue_Reverse_Iterator (ACE_Message_Queue &queue); // = Iteration methods. /// Pass back the @a entry that hasn't been seen in the queue. /// Returns 0 when all items have been seen, else 1. int next (ACE_Message_Block *&entry); /// Returns 1 when all items have been seen, else 0. int done () const; /// Move forward by one element in the queue. Returns 0 when all the /// items in the set have been seen, else 1. int advance (); /// Dump the state of an object. void dump () const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; private: /// Message_Queue we are iterating over. ACE_Message_Queue &queue_; protected: /// Keeps track of how far we've advanced... ACE_Message_Block *curr_; }; /** * @class ACE_Dynamic_Message_Queue * * @brief A derived class which adapts the ACE_Message_Queue * class in order to maintain dynamic priorities for enqueued * and manage the queue order according * to these dynamic priorities. * * The messages in the queue are managed so as to preserve * a logical ordering with minimal overhead per enqueue and * dequeue operation. For this reason, the actual order of * messages in the linked list of the queue may differ from * their priority order. As time passes, a message may change * from pending status to late status, and eventually to beyond * late status. To minimize reordering overhead under this * design force, three separate boundaries are maintained * within the linked list of messages. Messages are dequeued * preferentially from the head of the pending portion, then * the head of the late portion, and finally from the head * of the beyond late portion. In this way, only the boundaries * need to be maintained (which can be done efficiently, as * aging messages maintain the same linked list order as they * progress from one status to the next), with no reordering * of the messages themselves, while providing correct priority * ordered dequeueing semantics. * Head and tail enqueue methods inherited from ACE_Message_Queue * are made private to prevent out-of-order messages from confusing * management of the various portions of the queue. Messages in * the pending portion of the queue whose priority becomes late * (according to the specific dynamic strategy) advance into * the late portion of the queue. Messages in the late portion * of the queue whose priority becomes later than can be represented * advance to the beyond_late portion of the queue. These behaviors * support a limited schedule overrun, with pending messages prioritized * ahead of late messages, and late messages ahead of beyond late * messages. These behaviors can be modified in derived classes by * providing alternative definitions for the appropriate virtual methods. * When filled with messages, the queue's linked list should look like: * H T * | | * B - B - B - B - L - L - L - P - P - P - P - P * | | | | | | * BH BT LH LT PH PT * Where the symbols are as follows: * H = Head of the entire list * T = Tail of the entire list * B = Beyond late message * BH = Beyond late messages Head * BT = Beyond late messages Tail * L = Late message * LH = Late messages Head * LT = Late messages Tail * P = Pending message * PH = Pending messages Head * PT = Pending messages Tail * Caveat: the virtual methods enqueue_tail, enqueue_head, * and peek_dequeue_head have semantics for the static * message queues that cannot be guaranteed for dynamic * message queues. The peek_dequeue_head method just * calls the base class method, while the two enqueue * methods call the priority enqueue method. The * order of messages in the dynamic queue is a function * of message deadlines and how long they are in the * queues. You can manipulate these in some cases to * ensure the correct semantics, but that is not a * very stable or portable approach (discouraged). */ template class ACE_Dynamic_Message_Queue : public ACE_Message_Queue { public: ACE_Dynamic_Message_Queue (ACE_Dynamic_Message_Strategy & message_strategy, size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM, size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM, ACE_Notification_Strategy * = 0); /// Close down the message queue and release all resources. virtual ~ACE_Dynamic_Message_Queue (); /** * Detach all messages with status given in the passed flags from * the queue and return them by setting passed head and tail pointers * to the linked list they comprise. This method is intended primarily * as a means of periodically harvesting messages that have missed * their deadlines, but is available in its most general form. All * messages are returned in priority order, from head to tail, as of * the time this method was called. */ virtual int remove_messages (ACE_Message_Block *&list_head, ACE_Message_Block *&list_tail, u_int status_flags); /** * Dequeue and return the at the head of the * queue. Returns -1 on failure, else the number of items still on * the queue. */ virtual int dequeue_head (ACE_Message_Block *&first_item, ACE_Time_Value *timeout = 0); /// Dump the state of the queue. virtual void dump () const; /** * Just call priority enqueue method: tail enqueue semantics for dynamic * message queues are unstable: the message may or may not be where * it was placed after the queue is refreshed prior to the next * enqueue or dequeue operation. */ virtual int enqueue_tail (ACE_Message_Block *new_item, ACE_Time_Value *timeout = 0); /** * Just call priority enqueue method: head enqueue semantics for dynamic * message queues are unstable: the message may or may not be where * it was placed after the queue is refreshed prior to the next * enqueue or dequeue operation. */ virtual int enqueue_head (ACE_Message_Block *new_item, ACE_Time_Value *timeout = 0); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: /** * Enqueue an in accordance with its priority. * priority may be *dynamic* or *static* or a combination or *both* * It calls the priority evaluation function passed into the Dynamic * Message Queue constructor to update the priorities of all * enqueued messages. */ virtual int enqueue_i (ACE_Message_Block *new_item); /// Enqueue a message in priority order within a given priority status sublist virtual int sublist_enqueue_i (ACE_Message_Block *new_item, const ACE_Time_Value ¤t_time, ACE_Message_Block *&sublist_head, ACE_Message_Block *&sublist_tail, ACE_Dynamic_Message_Strategy::Priority_Status status); /** * Dequeue and return the at the head of the * logical queue. Attempts first to dequeue from the pending * portion of the queue, or if that is empty from the late portion, * or if that is empty from the beyond late portion, or if that is * empty just sets the passed pointer to zero and returns -1. */ virtual int dequeue_head_i (ACE_Message_Block *&first_item); /// Refresh the queue using the strategy /// specific priority status function. virtual int refresh_queue (const ACE_Time_Value & current_time); /// Refresh the pending queue using the strategy /// specific priority status function. virtual int refresh_pending_queue (const ACE_Time_Value & current_time); /// Refresh the late queue using the strategy /// specific priority status function. virtual int refresh_late_queue (const ACE_Time_Value & current_time); /// Pointer to head of the pending messages ACE_Message_Block *pending_head_; /// Pointer to tail of the pending messages ACE_Message_Block *pending_tail_; /// Pointer to head of the late messages ACE_Message_Block *late_head_; /// Pointer to tail of the late messages ACE_Message_Block *late_tail_; /// Pointer to head of the beyond late messages ACE_Message_Block *beyond_late_head_; /// Pointer to tail of the beyond late messages ACE_Message_Block *beyond_late_tail_; /// Pointer to a dynamic priority evaluation function. ACE_Dynamic_Message_Strategy &message_strategy_; private: // = Disallow public access to these operations. void operator= (const ACE_Dynamic_Message_Queue &) = delete; ACE_Dynamic_Message_Queue (const ACE_Dynamic_Message_Queue &) = delete; // provide definitions for these (just call base class method), // but make them private so they're not accessible outside the class /// Private method to hide public base class method: just calls base class method virtual int peek_dequeue_head (ACE_Message_Block *&first_item, ACE_Time_Value *timeout = 0); }; /** * @class ACE_Message_Queue_Factory * * @brief ACE_Message_Queue_Factory is a static factory class template which * provides a separate factory method for each of the major kinds of * priority based message dispatching: static, earliest deadline first * (EDF), and minimum laxity first (MLF). * * The ACE_Dynamic_Message_Queue class assumes responsibility for * releasing the resources of the strategy with which it was * constructed: the user of a message queue constructed by * any of these factory methods is only responsible for * ensuring destruction of the message queue itself. */ template class ACE_Message_Queue_Factory { public: /// Factory method for a statically prioritized ACE_Message_Queue static ACE_Message_Queue * create_static_message_queue (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM, size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM, ACE_Notification_Strategy * = 0); /// Factory method for a dynamically prioritized (by time to deadline) ACE_Dynamic_Message_Queue static ACE_Dynamic_Message_Queue * create_deadline_message_queue (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM, size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM, ACE_Notification_Strategy * = 0, u_long static_bit_field_mask = 0x3FFUL, // 2^(10) - 1 u_long static_bit_field_shift = 10, // 10 low order bits u_long dynamic_priority_max = 0x3FFFFFUL, // 2^(22)-1 u_long dynamic_priority_offset = 0x200000UL); // 2^(22-1) /// Factory method for a dynamically prioritized (by laxity) ACE_Dynamic_Message_Queue static ACE_Dynamic_Message_Queue * create_laxity_message_queue (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM, size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM, ACE_Notification_Strategy * = 0, u_long static_bit_field_mask = 0x3FFUL, // 2^(10) - 1 u_long static_bit_field_shift = 10, // 10 low order bits u_long dynamic_priority_max = 0x3FFFFFUL, // 2^(22)-1 u_long dynamic_priority_offset = 0x200000UL); // 2^(22-1) #if defined (ACE_VXWORKS) /// Factory method for a wrapped VxWorks message queue static ACE_Message_Queue_Vx * create_Vx_message_queue (size_t max_messages, size_t max_message_length, ACE_Notification_Strategy *ns = 0); #endif /* defined (ACE_VXWORKS) */ #if defined (ACE_HAS_WIN32_OVERLAPPED_IO) /// Factory method for a NT message queue. static ACE_Message_Queue_NT * create_NT_message_queue (size_t max_threads); #endif /* ACE_HAS_WIN32_OVERLAPPED_IO */ }; // Forward decls. template class ACE_Message_Queue_Ex_Iterator; template class ACE_Message_Queue_Ex_Reverse_Iterator; /** * @class ACE_Message_Queue_Ex * * @brief A threaded message queueing facility, modeled after the * queueing facilities in System V STREAMs. * * ACE_Message_Queue_Ex is a strongly-typed version of the * ACE_Message_Queue class. Rather than queueing in terms of ACE_Message_Block * objects, ACE_Message_Queue_Ex has a template argument to specify the * type of objects that are queued. * * The second template argument parameterizes the queue's synchronization. * The argument specifies a synchronization strategy. The two main * strategies available for ACE_SYNCH_DECL are: * -# ACE_MT_SYNCH: all operations are thread-safe * -# ACE_NULL_SYNCH: no synchronization and no locking overhead */ template class ACE_Message_Queue_Ex { public: enum { /// Default priority value. This is the lowest priority. DEFAULT_PRIORITY = 0 }; friend class ACE_Message_Queue_Ex_Iterator ; friend class ACE_Message_Queue_Ex_Reverse_Iterator; // = Traits typedef ACE_Message_Queue_Ex_Iterator ITERATOR; typedef ACE_Message_Queue_Ex_Reverse_Iterator REVERSE_ITERATOR; /** * @name Initialization methods */ //@{ /** * Initialize an ACE_Message_Queue_Ex. * * @param high_water_mark High water mark. Determines how many bytes can be * stored in a queue before it's considered full. Supplier threads * must block until the queue is no longer full. * @param low_water_mark Low water mark. Determines how many bytes must be in * the queue before supplier threads are allowed to enqueue additional * data. By default, the @a hwm equals @a lwm, which means * that suppliers will be able to enqueue new messages as soon as * a consumer removes any message from the queue. Making the low * water mark smaller than the high water mark forces consumers to * drain more messages from the queue before suppliers can enqueue * new messages, which can minimize the "silly window syndrome." * @param ns Notification strategy. Pointer to an object conforming to the * ACE_Notification_Strategy interface. If set, the object's * notify() method will be called each time data is added to * this ACE_Message_Queue. @see ACE_Reactor_Notification_Strategy. */ ACE_Message_Queue_Ex (size_t high_water_mark = ACE_Message_Queue_Base::DEFAULT_HWM, size_t low_water_mark = ACE_Message_Queue_Base::DEFAULT_LWM, ACE_Notification_Strategy * ns = 0); virtual int open (size_t hwm = ACE_Message_Queue_Base::DEFAULT_HWM, size_t lwm = ACE_Message_Queue_Base::DEFAULT_LWM, ACE_Notification_Strategy * = 0); //@} /// Releases all resources from the message queue and marks it deactivated. /// @sa flush(). /// /// @retval The number of messages released from the queue; -1 on error. virtual int close (); /// Releases all resources from the message queue and marks it deactivated. virtual ~ACE_Message_Queue_Ex (); /** * Releases all resources from the message queue but does not mark it * deactivated. This method holds the queue lock during this operation. * @sa close(). * * @return The number of messages flushed; -1 on error. */ virtual int flush (); /** * Release all resources from the message queue but do not mark it * as deactivated. * * @pre The caller must be holding the queue lock before calling this * method. * * @return The number of messages flushed. */ virtual int flush_i (); /** @name Enqueue and dequeue methods * * The enqueue and dequeue methods accept a timeout value passed as * an ACE_Time_Value *. In all cases, if the timeout pointer is 0, * the caller will block until action is possible. If the timeout pointer * is non-zero, the call will wait (if needed, subject to water mark * settings) until the absolute time specified in the referenced * ACE_Time_Value object is reached. If the time is reached before the * desired action is possible, the method will return -1 with errno set * to @c EWOULDBLOCK. Regardless of the timeout setting, however, * these methods will also fail and return -1 when the queue is closed, * deactivated, pulsed, or when a signal occurs. * * The time parameters are handled the same as in ACE_Message_Queue, so * you can see C++NPv2 Section 6.2 and APG Section 12.3 for a fuller * treatment of ACE_Message_Queue, enqueueing, dequeueing, and how these * operations are affected by queue state transitions. */ //@{ /** * Retrieve a pointer to the first item in the queue without removing it. * * @note Because the item whose pointer is returned is still on the queue, * another thread may dequeue that item at any time, * including before the calling thread examines the peeked-at item. * Be very careful with this method in multithreaded queueing * situations. * * @param first_item Reference to an ACE_MESSAGE_TYPE * that will * point to the first item on the queue. The item * remains on the queue until this or another thread * dequeues it. * @param timeout The absolute time the caller will wait until * for an item to be queued. * * @retval >0 The number of items on the queue. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int peek_dequeue_head (ACE_MESSAGE_TYPE *&first_item, ACE_Time_Value *timeout = 0); /** * Enqueue an ACE_MESSAGE TYPE into the queue in accordance with * the specified priority (0 is lowest priority). FIFO * order is maintained when items of the same priority are * inserted consecutively. * * @param new_item Pointer to an item that will be added to the queue. * @param timeout The absolute time the caller will wait until * for the block to be queued. * @param priority The priority to use when enqueueing the item. * * @retval >0 The number of items on the queue after adding * the specified item. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int enqueue_prio (ACE_MESSAGE_TYPE *new_item, ACE_Time_Value *timeout = 0, unsigned long priority = DEFAULT_PRIORITY); /** * This method acts just like enqueue_tail(). There's no deadline * time associated with items. */ virtual int enqueue_deadline (ACE_MESSAGE_TYPE *new_item, ACE_Time_Value *timeout = 0); /** * @deprecated This is an alias for enqueue_prio(). It's only here for * backwards compatibility and will go away in a subsequent release. * Please use enqueue_prio() instead. */ virtual int enqueue (ACE_MESSAGE_TYPE *new_item, ACE_Time_Value *timeout = 0); /** * Enqueue an item at the tail of the queue. * * @param new_item Pointer to an item that will be added to the queue. * @param timeout The absolute time the caller will wait until * for the item to be queued. * * @retval >0 The number of items on the queue after adding * the specified item. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int enqueue_tail (ACE_MESSAGE_TYPE *new_item, ACE_Time_Value *timeout = 0); /** * Enqueue an item at the head of the queue. * * @param new_item Pointer to an item that will be added to the queue. * @param timeout The absolute time the caller will wait until * for the item to be queued. * * @retval >0 The number of items on the queue after adding * the specified item. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int enqueue_head (ACE_MESSAGE_TYPE *new_item, ACE_Time_Value *timeout = 0); /// This method is an alias for the following method. virtual int dequeue (ACE_MESSAGE_TYPE *&first_item, ACE_Time_Value *timeout = 0); /** * Dequeue the item at the head of the queue and return a pointer to it. * * @param first_item Reference to an ACE_MESSAGE_TYPE * that will * be set to the address of the dequeued item. * @param timeout The absolute time the caller will wait until * for an item to be dequeued. * * @retval >=0 The number of items remaining in the queue. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int dequeue_head (ACE_MESSAGE_TYPE *&first_item, ACE_Time_Value *timeout = 0); /** * Dequeue the item that has the lowest priority (preserves * FIFO order for items with the same priority) and return a pointer * to it. * * @param dequeued Reference to an ACE_MESSAGE_TYPE * that will * be set to the address of the dequeued item. * @param timeout The absolute time the caller will wait until * for an item to be dequeued. * * @retval >=0 The number of items remaining in the queue. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int dequeue_prio (ACE_MESSAGE_TYPE *&dequeued, ACE_Time_Value *timeout = 0); /** * Dequeue the item at the tail of the queue and return a pointer to it. * * @param dequeued Reference to an ACE_MESSAGE_TYPE * that will * be set to the address of the dequeued item. * @param timeout The absolute time the caller will wait until * for an item to be dequeued. * * @retval >=0 The number of items remaining in the queue. * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int dequeue_tail (ACE_MESSAGE_TYPE *&dequeued, ACE_Time_Value *timeout = 0); /** * Because there's deadline associated with enqueue_deadline(), this * method will behave just as dequeue_head(). */ virtual int dequeue_deadline (ACE_MESSAGE_TYPE *&dequeued, ACE_Time_Value *timeout = 0); //@} /** @name Queue statistics methods */ //@{ /// True if queue is full, else false. virtual bool is_full (); /// True if queue is empty, else false. virtual bool is_empty (); /** * Number of total bytes on the queue, i.e., sum of the message * block sizes. */ virtual size_t message_bytes (); /** * Number of total length on the queue, i.e., sum of the message * block lengths. */ virtual size_t message_length (); /** * Number of total messages on the queue. */ virtual size_t message_count (); // = Manual changes to these stats (used when queued message blocks // change size or lengths). /** * New value of the number of total bytes on the queue, i.e., sum of * the message block sizes. */ virtual void message_bytes (size_t new_size); /** * New value of the number of total length on the queue, i.e., sum * of the message block lengths. */ virtual void message_length (size_t new_length); //@} /** @name Water mark (flow control) methods */ //@{ /** * Get high watermark. */ virtual size_t high_water_mark (); /** * Set the high watermark, which determines how many bytes can be * stored in a queue before it's considered "full." */ virtual void high_water_mark (size_t hwm); /** * Get low watermark. */ virtual size_t low_water_mark (); /** * Set the low watermark, which determines how many bytes must be in * the queue before supplier threads are allowed to enqueue * additional s. */ virtual void low_water_mark (size_t lwm); //@} /** @name Activation and queue state methods * See C++NPv2 Section 6.2 and APG Section 12.3 for a fuller treatment of * queue states and transitions and how the transitions affect message * enqueueing and dequeueing operations. */ //@{ /** * Deactivate the queue and wakeup all threads waiting on the queue * so they can continue. No messages are removed from the queue, * however. Any other operations called until the queue is * activated again will immediately return -1 with @c errno == * ESHUTDOWN. Returns WAS_INACTIVE if queue was inactive before the * call and WAS_ACTIVE if queue was active before the call. */ virtual int deactivate (); /** * Reactivate the queue so that threads can enqueue and dequeue * messages again. Returns the state of the queue before the call. */ virtual int activate (); /** * Pulse the queue to wake up any waiting threads. Changes the * queue state to PULSED; future enqueue/dequeue operations proceed * as in ACTIVATED state. * * @retval The queue's state before this call. */ virtual int pulse (); /// Returns the current state of the queue, which can be one of /// ACTIVATED, DEACTIVATED, or PULSED. virtual int state (); /// Returns true if the state of the queue is DEACTIVATED, /// but false if the queue's state is ACTIVATED or PULSED. virtual int deactivated (); //@} /** @name Notification strategy methods */ //@{ /** * This hook is automatically invoked by , * , and when a new item is inserted * into the queue. Subclasses can override this method to perform * specific notification strategies (e.g., signaling events for a * , notifying a , etc.). In a * multi-threaded application with concurrent consumers, there is no * guarantee that the queue will be still be non-empty by the time * the notification occurs. */ virtual int notify (); /// Get the notification strategy for the virtual ACE_Notification_Strategy *notification_strategy (); /// Set the notification strategy for the virtual void notification_strategy (ACE_Notification_Strategy *s); //@} /// Returns a reference to the lock used by the ACE_Message_Queue_Ex. virtual ACE_SYNCH_MUTEX_T &lock (); /// Get the current time of day according to the queue's TIME_POLICY. /// Allows users to initialize timeout ACE_Time_Value_T gettimeofday (); /// Allows applications to control how the timer queue gets the time /// of day. void set_time_policy (TIME_POLICY const & time_policy); /// Dump the state of an object. virtual void dump () const; /// Support access to the underlying . Note that /// manipulating the lower level queue directly may be hazardous (, but /// necessary in some scenarios); be sure to lock the queue first. ACE_Message_Queue &queue (); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: /// Implement this via an ACE_Message_Queue. ACE_Message_Queue queue_; }; /** * @class ACE_Message_Queue_Ex_Iterator * * @brief Iterator for the ACE_Message_Queue_Ex. */ template class ACE_Message_Queue_Ex_Iterator { public: ACE_Message_Queue_Ex_Iterator (ACE_Message_Queue_Ex & queue); // = Iteration methods. /// Pass back the @a entry that hasn't been seen in the queue. /// Returns 0 when all items have been seen, else 1. int next (ACE_MESSAGE_TYPE *&entry); /// Returns 1 when all items have been seen, else 0. int done () const; /// Move forward by one element in the queue. Returns 0 when all the /// items in the set have been seen, else 1. int advance (); /// Dump the state of an object. void dump () const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; private: /// Implement this via the ACE_Message_Queue_Iterator ACE_Message_Queue_Iterator iter_; }; /** * @class ACE_Message_Queue_Ex_Iterator * * @brief Reverse iterator for the ACE_Message_Queue_Ex. */ template class ACE_Message_Queue_Ex_Reverse_Iterator { public: ACE_Message_Queue_Ex_Reverse_Iterator (ACE_Message_Queue_Ex & queue); // = Iteration methods. /// Pass back the @a entry that hasn't been seen in the queue. /// Returns 0 when all items have been seen, else 1. int next (ACE_MESSAGE_TYPE *&entry); /// Returns 1 when all items have been seen, else 0. int done () const; /// Move forward by one element in the queue. Returns 0 when all the /// items in the set have been seen, else 1. int advance (); /// Dump the state of an object. void dump () const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; private: /// Implement this via the ACE_Message_Queue_Reverse_Iterator ACE_Message_Queue_Reverse_Iterator iter_; }; /** * @class ACE_Message_Queue_Ex_N * * @brief A threaded message queueing facility, modeled after the * queueing facilities in System V STREAMs which can enqueue * multiple messages in one call. * * As ACE_Message_Queue_Ex, ACE_Message_Queue_Ex_N is a strongly-typed * version of the ACE_Message_Queue. If @c ACE_SYNCH_DECL is @c ACE_MT_SYNCH * then all operations are thread-safe. Otherwise, if it's @c ACE_NULL_SYNCH * then there's no locking overhead. * * The @c ACE_MESSAGE_TYPE messages that are sent to this * queue can be chained. Messages are expected to have a * @c next method that returns the next message in the chain; * ACE_Message_Queue_Ex_N uses this method to run through * all the incoming messages and enqueue them in one call. */ template class ACE_Message_Queue_Ex_N : public ACE_Message_Queue_Ex { public: /** * Initialize an ACE_Message_Queue_Ex_N. The @a high_water_mark * determines how many bytes can be stored in a queue before it's * considered "full." Supplier threads must block until the queue * is no longer full. The @a low_water_mark determines how many * bytes must be in the queue before supplier threads are allowed to * enqueue additional messages. By default, the @a high_water_mark * equals the @a low_water_mark, which means that suppliers will be * able to enqueue new messages as soon as a consumer removes any message * from the queue. Making the @a low_water_mark smaller than the * @a high_water_mark forces consumers to drain more messages from the * queue before suppliers can enqueue new messages, which can minimize * the "silly window syndrome." */ ACE_Message_Queue_Ex_N (size_t high_water_mark = ACE_Message_Queue_Base::DEFAULT_HWM, size_t low_water_mark = ACE_Message_Queue_Base::DEFAULT_LWM, ACE_Notification_Strategy * ns = 0); /// Close down the message queue and release all resources. virtual ~ACE_Message_Queue_Ex_N (); /** * Enqueue one or more @c ACE_MESSAGE_TYPE objects at the head of the queue. * If the @a new_item @c next() pointer is non-zero, it is assumed to be the * start of a series of @c ACE_MESSAGE_TYPE objects connected via their * @c next() pointers. The series of blocks will be added to the queue in * the same order they are passed in as. * * @param new_item Pointer to an @c ACE_MESSAGE_TYPE that will be * added to the queue. If the block's @c next() pointer * is non-zero, all blocks chained from the @c next() * pointer are enqueued as well. * @param tv The absolute time the caller will wait until * for the block to be queued. * * @retval >0 The number of @c ACE_MESSAGE_TYPE objects on the queue after * adding the specified block(s). * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int enqueue_head (ACE_MESSAGE_TYPE *new_item, ACE_Time_Value *tv = 0); /** * Enqueue one or more @c ACE_MESSAGE_TYPE objects at the tail of the queue. * If the @a new_item @c next() pointer is non-zero, it is assumed to be the * start of a series of @c ACE_MESSAGE_TYPE objects connected via their * @c next() pointers. The series of blocks will be added to the queue in * the same order they are passed in as. * * @param new_item Pointer to an @c ACE_MESSAGE_TYPE that will be * added to the queue. If the block's @c next() pointer * is non-zero, all blocks chained from the @c next() * pointer are enqueued as well. * @param tv The absolute time the caller will wait until * for the block to be queued. * * @retval >0 The number of @c ACE_MESSAGE_TYPE objects on the queue after * adding the specified block(s). * @retval -1 On failure. errno holds the reason. Common errno values are: * - EWOULDBLOCK: the timeout elapsed * - ESHUTDOWN: the queue was deactivated or pulsed */ virtual int enqueue_tail (ACE_MESSAGE_TYPE *new_item, ACE_Time_Value *tv = 0); /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: /** * An helper method that wraps the incoming chain messages * with ACE_Message_Blocks. */ ACE_Message_Block *wrap_with_mbs_i (ACE_MESSAGE_TYPE *new_item); }; ACE_END_VERSIONED_NAMESPACE_DECL #include "ace/Message_Queue_T.cpp" #include /**/ "ace/post.h" #endif /* ACE_MESSAGE_QUEUE_T_H */