summaryrefslogtreecommitdiff
path: root/ACE/ace/Message_Queue_T.h
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/Message_Queue_T.h')
-rw-r--r--ACE/ace/Message_Queue_T.h1411
1 files changed, 1411 insertions, 0 deletions
diff --git a/ACE/ace/Message_Queue_T.h b/ACE/ace/Message_Queue_T.h
new file mode 100644
index 00000000000..329258fabd0
--- /dev/null
+++ b/ACE/ace/Message_Queue_T.h
@@ -0,0 +1,1411 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file Message_Queue_T.h
+ *
+ * $Id$
+ *
+ * @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_MESSAGE_QUEUE_T_H
+#define ACE_MESSAGE_QUEUE_T_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Message_Queue.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Guard_T.h"
+
+#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_WIN32) && (ACE_HAS_WINNT4 != 0)
+class ACE_Message_Queue_NT;
+#endif /* ACE_WIN32 && ACE_HAS_WINNT4 != 0 */
+
+/**
+ * @class ACE_Message_Queue
+ *
+ * @brief A message queueing facility with parameterized synchronization
+ * capability. ACE_Message_Queue is modeled after the queueing facilities
+ * in System V STREAMs.
+ *
+ * ACE_Message_Queue is the primary queueing 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 <ACE_SYNCH_DECL>
+class ACE_Message_Queue : public ACE_Message_Queue_Base
+{
+public:
+ friend class ACE_Message_Queue_Iterator<ACE_SYNCH_USE>;
+ friend class ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>;
+
+ // = Traits
+ typedef ACE_Message_Queue_Iterator<ACE_SYNCH_USE>
+ ITERATOR;
+ typedef ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>
+ REVERSE_ITERATOR;
+
+ // = Initialization and termination 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(void) 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 (void);
+
+ /// Releases all resources from the message queue and marks it deactivated.
+ virtual ~ACE_Message_Queue (void);
+
+ /// Releases all resources from the message queue but does not mark it
+ /// deactivated.
+ /// @sa close().
+ /**
+ * This method holds the queue lock during this operation.
+ *
+ * @return The number of messages flushed; -1 on error.
+ */
+ virtual int flush (void);
+
+ /// 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 (void);
+
+ /** @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);
+ //@}
+
+ // = Check if queue is full/empty.
+ /// True if queue is full, else false.
+ virtual int is_full (void);
+ /// True if queue is empty, else false.
+ virtual int is_empty (void);
+
+ /** @name Queue statistics methods
+ */
+ //@{
+
+ /**
+ * Number of total bytes on the queue, i.e., sum of the message
+ * block sizes.
+ */
+ virtual size_t message_bytes (void);
+
+ /**
+ * Number of total length on the queue, i.e., sum of the message
+ * block lengths.
+ */
+ virtual size_t message_length (void);
+
+ /**
+ * Number of total messages on the queue.
+ */
+ virtual size_t message_count (void);
+
+ // = 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 (void);
+ /**
+ * 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 (void);
+ /**
+ * 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 <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 (void);
+
+ /**
+ * Reactivate the queue so that threads can enqueue and dequeue
+ * messages again. Returns the state of the queue before the call.
+ */
+ virtual int activate (void);
+
+ /**
+ * 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 (void);
+
+ /// Returns the current state of the queue, which can be one of
+ /// ACTIVATED, DEACTIVATED, or PULSED.
+ virtual int state (void);
+
+ /// Returns true if the state of the queue is <DEACTIVATED>,
+ /// but false if the queue's is <ACTIVATED> or <PULSED>.
+ virtual int deactivated (void);
+ //@}
+
+ /** @name Notification strategy methods
+ */
+ //@{
+
+ /**
+ * This hook is automatically invoked by <enqueue_head>,
+ * <enqueue_tail>, and <enqueue_prio> 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
+ * <WFMO_Reactor>, notifying a <Reactor>, 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 (void);
+
+ /// Get the notification strategy for the <Message_Queue>
+ virtual ACE_Notification_Strategy *notification_strategy (void);
+
+ /// Set the notification strategy for the <Message_Queue>
+ 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 (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) 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 <ACE_Message_Block *> in accordance with its priority.
+ virtual int enqueue_i (ACE_Message_Block *new_item);
+
+ /// Enqueue an <ACE_Message_Block *> in accordance with its deadline time.
+ virtual int enqueue_deadline_i (ACE_Message_Block *new_item);
+
+ /// Enqueue an <ACE_Message_Block *> at the end of the queue.
+ virtual int enqueue_tail_i (ACE_Message_Block *new_item);
+
+ /// Enqueue an <ACE_Message_Block *> at the head of the queue.
+ virtual int enqueue_head_i (ACE_Message_Block *new_item);
+
+ /// Dequeue and return the <ACE_Message_Block *> at the head of the
+ /// queue.
+ virtual int dequeue_head_i (ACE_Message_Block *&first_item);
+
+ /// Dequeue and return the <ACE_Message_Block *> with the lowest
+ /// priority.
+ virtual int dequeue_prio_i (ACE_Message_Block *&dequeued);
+
+ /// Dequeue and return the <ACE_Message_Block *> at the tail of the
+ /// queue.
+ virtual int dequeue_tail_i (ACE_Message_Block *&first_item);
+
+ /// Dequeue and return the <ACE_Message_Block *> 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 int is_full_i (void);
+
+ /// True if queue is empty, else false.
+ virtual int is_empty_i (void);
+
+ // = Implementation of the public <activate> and <deactivate> 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 (void);
+
+ // = Helper methods to factor out common #ifdef code.
+
+ /// Wait for the queue to become non-full.
+ virtual int wait_not_full_cond (ACE_Guard<ACE_SYNCH_MUTEX_T> &mon,
+ ACE_Time_Value *timeout);
+
+ /// Wait for the queue to become non-empty.
+ virtual int wait_not_empty_cond (ACE_Guard<ACE_SYNCH_MUTEX_T> &mon,
+ ACE_Time_Value *timeout);
+
+ /// Inform any threads waiting to enqueue that they can procede.
+ virtual int signal_enqueue_waiters (void);
+
+ /// Inform any threads waiting to dequeue that they can procede.
+ virtual int signal_dequeue_waiters (void);
+
+ /// 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_;
+
+ /// 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_;
+
+private:
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Message_Queue<ACE_SYNCH_USE> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Message_Queue (const ACE_Message_Queue<ACE_SYNCH_USE> &))
+};
+
+// This typedef is used to get around a compiler bug in g++/vxworks.
+typedef ACE_Message_Queue<ACE_SYNCH> ACE_DEFAULT_MESSAGE_QUEUE_TYPE;
+
+
+/**
+ * @class ACE_Message_Queue_Iterator
+ *
+ * @brief Iterator for the ACE_Message_Queue.
+ */
+template <ACE_SYNCH_DECL>
+class ACE_Message_Queue_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Message_Queue_Iterator (ACE_Message_Queue <ACE_SYNCH_USE> &queue);
+
+ // = Iteration methods.
+ /// Pass back the <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 (void) 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 (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Message_Queue we are iterating over.
+ ACE_Message_Queue <ACE_SYNCH_USE> &queue_;
+
+ /// 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 <ACE_SYNCH_DECL>
+class ACE_Message_Queue_Reverse_Iterator
+{
+public:
+ // = Initialization method.
+ ACE_Message_Queue_Reverse_Iterator (ACE_Message_Queue <ACE_SYNCH_USE> &queue);
+
+ // = Iteration methods.
+ /// Pass back the <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 (void) 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 (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+ /// Message_Queue we are iterating over.
+ ACE_Message_Queue <ACE_SYNCH_USE> &queue_;
+
+ /// 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
+ * <ACE_Message_Blocks> 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 <ACE_SYNCH_DECL>
+class ACE_Dynamic_Message_Queue : public ACE_Message_Queue<ACE_SYNCH_USE>
+{
+public:
+ // = Initialization and termination methods.
+ 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 (void);
+
+ /**
+ * 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 <ACE_Message_Block *> 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 (void) 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 <ACE_Message_Block *> 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 &current_time,
+ ACE_Message_Block *&sublist_head,
+ ACE_Message_Block *&sublist_tail,
+ ACE_Dynamic_Message_Strategy::Priority_Status status);
+
+ /**
+ * Dequeue and return the <ACE_Message_Block *> 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.
+
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Dynamic_Message_Queue (const ACE_Dynamic_Message_Queue<ACE_SYNCH_USE> &))
+
+ // 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 <ACE_SYNCH_DECL>
+class ACE_Message_Queue_Factory
+{
+public:
+ /// Factory method for a statically prioritized ACE_Message_Queue
+ static ACE_Message_Queue<ACE_SYNCH_USE> *
+ 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<ACE_SYNCH_USE> *
+ 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<ACE_SYNCH_USE> *
+ 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_WIN32) && (ACE_HAS_WINNT4 != 0)
+
+ /// Factory method for a NT message queue.
+ static ACE_Message_Queue_NT *
+ create_NT_message_queue (size_t max_threads);
+
+#endif /* ACE_WIN32 && ACE_HAS_WINNT4 != 0 */
+};
+
+/**
+ * @class ACE_Message_Queue_Ex
+ *
+ * @brief A threaded message queueing facility, modeled after the
+ * queueing facilities in System V STREAMs.
+ *
+ * An <ACE_Message_Queue_Ex> is a strongly-typed version of the
+ * ACE_Message_Queue. If
+ * <ACE_SYNCH_DECL> is <ACE_MT_SYNCH> then all operations are
+ * thread-safe. Otherwise, if it's <ACE_NULL_SYNCH> then there's no
+ * locking overhead.
+ */
+template <class ACE_MESSAGE_TYPE, ACE_SYNCH_DECL>
+class ACE_Message_Queue_Ex
+{
+public:
+
+ // = Default priority value.
+ enum
+ {
+ DEFAULT_PRIORITY = 0
+ };
+
+#if 0
+ // @@ Iterators are not implemented yet...
+
+ friend class ACE_Message_Queue_Iterator<ACE_SYNCH_USE>;
+ friend class ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>;
+
+ // = Traits
+ typedef ACE_Message_Queue_Iterator<ACE_SYNCH_USE>
+ ITERATOR;
+ typedef ACE_Message_Queue_Reverse_Iterator<ACE_SYNCH_USE>
+ REVERSE_ITERATOR;
+#endif /* 0 */
+
+ // = Initialization and termination methods.
+
+ /**
+ * Initialize an ACE_Message_Queue. The <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 <low_water_mark> determines how many
+ * bytes must be in the queue before supplier threads are allowed to
+ * enqueue additional ACE_Message_Blocks. By default, the
+ * <high_water_mark> equals the <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
+ * <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."
+ */
+ 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 * = 0);
+
+ /**
+ * Initialize an ACE_Message_Queue. The <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 <low_water_mark> determines how many
+ * bytes must be in the queue before supplier threads are allowed to
+ * enqueue additional ACE_Message_Blocks. By default, the
+ * <high_water_mark> equals the <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
+ * <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."
+ */
+ 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);
+
+ /// Close down the message queue and release all resources.
+ virtual int close (void);
+
+ /// Close down the message queue and release all resources.
+ virtual ~ACE_Message_Queue_Ex (void);
+
+ /// Release all resources from the message queue but do not mark it as deactivated.
+ /// This method holds the queue lock during this operation. Returns the number of
+ /// messages flushed.
+ virtual int flush (void);
+
+ /// Release all resources from the message queue but do not mark it as
+ /// deactivated. This method does not hold the queue lock during this
+ /// operation, i.e., it assume the lock is held externally.
+ /// Returns the number of messages flushed.
+ virtual int flush_i (void);
+
+ // = Enqueue and dequeue methods.
+
+ // For the following enqueue and dequeue methods if <timeout> == 0,
+ // the caller will block until action is possible, else will wait
+ // until the absolute time specified in *<timeout> elapses). These
+ // calls will return, however, when queue is closed, deactivated,
+ // when a signal occurs, or if the time specified in timeout
+ // elapses, (in which case errno = EWOULDBLOCK).
+
+ /**
+ * Retrieve the first <ACE_MESSAGE_TYPE> without removing it. Note
+ * that <timeout> uses <{absolute}> time rather than <{relative}>
+ * time. If the <timeout> elapses without receiving a message -1 is
+ * returned and <errno> is set to <EWOULDBLOCK>. If the queue is
+ * deactivated -1 is returned and <errno> is set to <ESHUTDOWN>.
+ * Otherwise, returns -1 on failure, else the number of items still
+ * on the queue.
+ */
+ virtual int peek_dequeue_head (ACE_MESSAGE_TYPE *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue an <ACE_MESSAGE_TYPE *> into the <Message_Queue> in
+ * accordance with its <msg_priority> (0 is lowest priority). FIFO
+ * order is maintained when messages of the same priority are
+ * inserted consecutively. Note that <timeout> uses <{absolute}>
+ * time rather than <{relative}> time. If the <timeout> elapses
+ * without receiving a message -1 is returned and <errno> is set to
+ * <EWOULDBLOCK>. If the queue is deactivated -1 is returned and
+ * <errno> is set to <ESHUTDOWN>. Otherwise, returns -1 on failure,
+ * else the number of items still on the queue.
+ */
+ virtual int enqueue_prio (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue an <ACE_MESSAGE_TYPE *> into the <Message_Queue> in
+ * accordance with its <msg_deadline_time>. FIFO
+ * order is maintained when messages of the same deadline time are
+ * inserted consecutively. Note that <timeout> uses <{absolute}>
+ * time rather than <{relative}> time. If the <timeout> elapses
+ * without receiving a message -1 is returned and <errno> is set to
+ * <EWOULDBLOCK>. If the queue is deactivated -1 is returned and
+ * <errno> is set to <ESHUTDOWN>. Otherwise, returns -1 on failure,
+ * else the number of items still on the queue.
+ */
+ virtual int enqueue_deadline (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * 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. Note that <timeout> uses
+ * <{absolute}> time rather than <{relative}> time.
+ */
+ virtual int enqueue (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue an <ACE_MESSAGE_TYPE *> at the end of the queue. Note
+ * that <timeout> uses <{absolute}> time rather than <{relative}>
+ * time. If the <timeout> elapses without receiving a message -1 is
+ * returned and <errno> is set to <EWOULDBLOCK>. If the queue is
+ * deactivated -1 is returned and <errno> is set to <ESHUTDOWN>.
+ * Otherwise, returns -1 on failure, else the number of items still
+ * on the queue.
+ */
+ virtual int enqueue_tail (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Enqueue an <ACE_MESSAGE_TYPE *> at the head of the queue. Note
+ * that <timeout> uses <{absolute}> time rather than <{relative}>
+ * time. If the <timeout> elapses without receiving a message -1 is
+ * returned and <errno> is set to <EWOULDBLOCK>. If the queue is
+ * deactivated -1 is returned and <errno> is set to <ESHUTDOWN>.
+ * Otherwise, returns -1 on failure, else the number of items still
+ * on the queue.
+ */
+ virtual int enqueue_head (ACE_MESSAGE_TYPE *new_item,
+ ACE_Time_Value *timeout = 0);
+
+ /// This method is an alias for the following <dequeue_head> method.
+ virtual int dequeue (ACE_MESSAGE_TYPE *&first_item,
+ ACE_Time_Value *timeout = 0);
+ // This method is an alias for the following <dequeue_head> method.
+
+ /**
+ * Dequeue and return the <ACE_MESSAGE_TYPE *> at the head of the
+ * queue. Note that <timeout> uses <{absolute}> time rather than
+ * <{relative}> time. If the <timeout> elapses without receiving a
+ * message -1 is returned and <errno> is set to <EWOULDBLOCK>. If
+ * the queue is deactivated -1 is returned and <errno> is set to
+ * <ESHUTDOWN>. Otherwise, returns -1 on failure, else the number
+ * of items still on the queue.
+ */
+ virtual int dequeue_head (ACE_MESSAGE_TYPE *&first_item,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue and return the <ACE_MESSAGE_TYPE *> that has the lowest
+ * priority. Note that <timeout> uses <{absolute}> time rather than
+ * <{relative}> time. If the <timeout> elapses without receiving a
+ * message -1 is returned and <errno> is set to <EWOULDBLOCK>. If
+ * the queue is deactivated -1 is returned and <errno> is set to
+ * <ESHUTDOWN>. Otherwise, returns -1 on failure, else the number
+ * of items still on the queue.
+ */
+ virtual int dequeue_prio (ACE_MESSAGE_TYPE *&dequeued,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue and return the <ACE_MESSAGE_TYPE *> at the tail of the
+ * queue. Note that <timeout> uses <{absolute}> time rather than
+ * <{relative}> time. If the <timeout> elapses without receiving a
+ * message -1 is returned and <errno> is set to <EWOULDBLOCK>. If
+ * the queue is deactivated -1 is returned and <errno> is set to
+ * <ESHUTDOWN>. Otherwise, returns -1 on failure, else the number
+ * of items still on the queue.
+ */
+ virtual int dequeue_tail (ACE_MESSAGE_TYPE *&dequeued,
+ ACE_Time_Value *timeout = 0);
+
+ /**
+ * Dequeue and return the <ACE_MESSAGE_TYPE *> with the lowest
+ * deadline time. Note that <timeout> uses <{absolute}> time rather than
+ * <{relative}> time. If the <timeout> elapses without receiving a
+ * message -1 is returned and <errno> is set to <EWOULDBLOCK>. If
+ * the queue is deactivated -1 is returned and <errno> is set to
+ * <ESHUTDOWN>. Otherwise, returns -1 on failure, else the number
+ * of items still on the queue.
+ */
+ virtual int dequeue_deadline (ACE_MESSAGE_TYPE *&dequeued,
+ ACE_Time_Value *timeout = 0);
+
+ // = Check if queue is full/empty.
+ /// True if queue is full, else false.
+ virtual int is_full (void);
+ /// True if queue is empty, else false.
+ virtual int is_empty (void);
+
+
+ // = Queue statistic methods.
+ /**
+ * Number of total bytes on the queue, i.e., sum of the message
+ * block sizes.
+ */
+ virtual size_t message_bytes (void);
+ /**
+ * Number of total length on the queue, i.e., sum of the message
+ * block lengths.
+ */
+ virtual size_t message_length (void);
+ /**
+ * Number of total messages on the queue.
+ */
+ virtual size_t message_count (void);
+
+ // = 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);
+
+ // = Flow control methods.
+ /**
+ * Get high watermark.
+ */
+ virtual size_t high_water_mark (void);
+ /**
+ * 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 (void);
+ /**
+ * Set the low watermark, which determines how many bytes must be in
+ * the queue before supplier threads are allowed to enqueue
+ * additional <ACE_MESSAGE_TYPE>s.
+ */
+ virtual void low_water_mark (size_t lwm);
+
+ // = Activation control methods.
+
+ /**
+ * 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 <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 (void);
+
+ /**
+ * Reactivate the queue so that threads can enqueue and dequeue
+ * messages again. Returns the state of the queue before the call.
+ */
+ virtual int activate (void);
+
+ /**
+ * 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 (void);
+
+ /// Returns the current state of the queue, which can be one of
+ /// ACTIVATED, DEACTIVATED, or PULSED.
+ virtual int state (void);
+
+ /// Returns true if the state of the queue is DEACTIVATED,
+ /// but false if the queue's state is ACTIVATED or PULSED.
+ virtual int deactivated (void);
+
+ // = Notification hook.
+
+ /**
+ * This hook is automatically invoked by <enqueue_head>,
+ * <enqueue_tail>, and <enqueue_prio> 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
+ * <WFMO_Reactor>, notifying a <Reactor>, 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 (void);
+
+ /// Get the notification strategy for the <Message_Queue>
+ virtual ACE_Notification_Strategy *notification_strategy (void);
+
+ /// Set the notification strategy for the <Message_Queue>
+ 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 (void);
+
+ /// Dump the state of an object.
+ virtual void dump (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+protected:
+ /// Implement this via an ACE_Message_Queue.
+ ACE_Message_Queue<ACE_SYNCH_USE> queue_;
+};
+
+/**
+ * @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_TYPE, ACE_SYNCH_DECL>
+class ACE_Message_Queue_Ex_N : public ACE_Message_Queue_Ex<ACE_MESSAGE_TYPE, ACE_SYNCH_USE>
+{
+public:
+ // = Initialization and termination methods.
+
+ /**
+ * 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 (void);
+
+ /**
+ * 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
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Message_Queue_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Message_Queue_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#include /**/ "ace/post.h"
+#endif /* ACE_MESSAGE_QUEUE_T_H */