Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages | Examples

ReplyQueue.h

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////////
00002 /*! \file ReplyQueue.h
00003 *  \brief Declares and defines template classes for synchronization of network comm.
00004 *  \author $Author: rsharo $
00005 *  \version $Revision: 1.1 $
00006 *  \date    $Date: 2004/04/07 13:45:04 $
00007 *///////////////////////////////////////////////////////////////////////////////////
00008 #ifndef REPLY_QUEUE_H
00009 #define REPLY_QUEUE_H
00010 
00011 #include "ace/Log_Msg.h"
00012 #include "ace/Synch_T.h"
00013 
00014 #include <list>
00015 
00016 //
00017 // Forward declaration of the PendingReply class. This forward declaration
00018 // is needed for the declaration of ReplyQueue.
00019 template <class T, ACE_SYNCH_DECL>
00020 class PendingReply;
00021 
00022 //
00023 // This class encapsulates a synchronized queue through which solicited
00024 // data (replies) are passed between threads.
00025 //
00026 // Command threads follow this sequence of execution:
00027 //   (1) Acquire the queue's mutex exactly one time. Mutex acquisition must
00028 //       NOT be recursive. (VERY IMPORTANT).
00029 //   (2) Schedule some sort of input from another thread
00030 //   (3) Call GetReply(), which will block until error or the result is ready
00031 //   (4) Release the queue's mutex
00032 //
00033 // Reply threads follow this sequence of execution:
00034 //   (1) Generate data or read data from the network
00035 //   (2) The thread may or may not acquire the queue's mutex. In this thread
00036 //       acquisition may be recursive if the operating system supports it.
00037 //       In any event, SetReply() will acquire the mutex as part of its
00038 //       operation.
00039 //   (3) Call SetReply() to pass the data to the command thread(s).
00040 //   (4) Release the queue's mutex if the thread had previously acquired it.
00041 //
00042 // Multiple threads can wait in GetReply() and will receive replies
00043 // in FIFO order. This is possible because GetReply() temporarily
00044 // relinquishes the mutex as part of its operation.
00045 //
00046 // If the waiter times out before data is received, it is removed from
00047 // the queue.  Note that this could be problematic if a reply arrives
00048 // after the deadline.  Waiters should set a deadline only if they are
00049 // certain that missing a deadline means no reply will be coming.
00050 //
00051 // Any reply type for which the assignment operator is defined is allowed.
00052 // Reply types that don't support the assignment operator may be used
00053 // by specializing the Assign() method for your type.
00054 //
00055 // Examples of how to instantiate one of these queues:
00056 //
00057 //    A synchronized queue with string reply types:
00058 //       ReplyQueue<std::string, ACE_MT_SYNCH> foo;
00059 //
00060 //    An unsynchronized queue with integer reply types:
00061 //       ReplyQueue<int, ACE_NULL_SYNCH>       foo;
00062 //
00063 //    A queue with system-default synchronization and unspecified reply type:
00064 //       ReplyQueue<void *, ACE_SYNCH>         foo;
00065 template <class T, ACE_SYNCH_DECL>
00066 class ReplyQueue
00067 {
00068 public:
00069         //
00070         // Constructs a reply queue with the specified mutex.
00071         ReplyQueue(ACE_SYNCH_MUTEX_T &myMutex);
00072         
00073         //
00074         // Destroys a reply queue. It calls Close() to ensure all waiters
00075         // are released.
00076         ~ReplyQueue();
00077 
00078         //
00079         // Closes the queue. The queue is cleared and all waiters are freed
00080         // with an error code. Any subsequent calls to GetReply() or SetReply()
00081         // will fail as well.
00082         //
00083         // If acquireMutex is false, then the method will not acquire its own
00084         // mutex. Do this only if the mutex is already externally acquired.
00085         //
00086         // Returns 0 on success or -1 if already closed.
00087         int Close(bool acquireMutex=true);
00088 
00089         //
00090         // Closes the queue. The queue is cleared and all waiters are freed
00091         // with an error code. Any subsequent calls to GetReply() or SetReply()
00092         // will fail as well.
00093         //
00094         // If acquireMutex is false, then the method will not acquire its own
00095         // mutex. Do this only if the mutex is already externally acquired.
00096         //
00097         // Returns 0 on success or -1 if already closed.
00098         inline int Close_i();
00099 
00100         //
00101         // Indicates whether there are any threads currently waiting for a reply.
00102         //
00103         // If acquireMutex is false, then the method will not acquire its own
00104         // mutex. Do this only if the mutex is already externally acquired.
00105         //
00106         // Returns true if there are waiters, false otherwise.
00107         bool IsEmpty(bool acquireMutex=false);
00108 
00109         //
00110         // Indicates whether there are any threads currently waiting for a reply.
00111         //
00112         // This method makes no attempt to acquire its own mutex. The mutex should
00113         // be externally acquired before calling this method.
00114         //
00115         // Returns true if there are waiters, false otherwise.
00116         inline bool IsEmpty_i();
00117         
00118         //
00119         // Blocks the calling thread until the deadline expires or
00120         // until a reply is sent received from the queue.
00121         // If a reply is enqueued before the deadline, its value
00122         // will be assigned to the "theReply" argument.
00123         // Note that the deadline argument is an absolute time -- not a relative
00124         // one. For example, if you want a 10 second timeout, you should compute
00125         // your deadline by calling ACE_OS::gettimeofday() and adding 10 seconds
00126         // to the result.
00127         // Passing a NULL pointer in the deadline argument means "wait forever".
00128         //
00129         // NOTE: You must acquire the queue's mutex exactly once when calling
00130         // this method. Acquiring the mutex more than once (i.e. recursively)
00131         // will result in a deadlock!
00132         //
00133         // Do not acquire the mutex externally before calling this method with
00134         // acquireMutex==true.
00135         //
00136         // If acquireMutex is false, then the method will not acquire its own
00137         // mutex. Do this only if the mutex is already externally acquired once.
00138         //
00139         // Returns 0 if the reply was successfully retrieved, -1 otherwise.
00140         int GetReply(T &theReply, const ACE_Time_Value *deadline, bool acquireMutex=false);
00141         
00142         //
00143         // Blocks the calling thread until the deadline expires or
00144         // until a reply is sent received from the queue.
00145         // If a reply is enqueued before the deadline, its value
00146         // will be assigned to the "theReply" argument.
00147         // Note that the deadline argument is an absolute time -- not a relative
00148         // one. For example, if you want a 10 second timeout, you should compute
00149         // your deadline by calling ACE_OS::gettimeofday() and adding 10 seconds
00150         // to the result.
00151         // Passing a NULL pointer in the deadline argument means "wait forever".
00152         //
00153         // NOTE: You must acquire the queue's mutex exactly once before calling
00154         // this method. Acquiring the mutex more than once (i.e. recursively)
00155         // will result in a deadlock! If you don't acquire the mutex before
00156         // calling, the method will fail.
00157         //
00158         // This method makes no attempt to acquire its own mutex. The mutex should
00159         // be externally acquired once before calling this method.
00160         //
00161         // Returns 0 if the reply was successfully retrieved, -1 otherwise.
00162         inline int GetReply_i(T &theReply, const ACE_Time_Value *deadline);
00163 
00164         //
00165         // Blocks the calling thread until a reply is sent received from the queue.
00166         // The reply is assigned to the "theReply" argument.
00167         //
00168         // NOTE: You must acquire the queue's mutex exactly once before calling
00169         // this method. Acquiring the mutex more than once (i.e. recursively)
00170         // will result in a deadlock! If you don't acquire the mutex before
00171         // calling, the method will fail.
00172         //
00173         // If acquireMutex is false, then the method will not acquire its own
00174         // mutex. Do this only if the mutex is already externally acquired.
00175         //
00176         // Returns 0 if the reply was successfully retrieved, -1 otherwise.
00177         int GetReply(T &theReply, bool acquireMutex=false);
00178 
00179 
00180         //
00181         // Blocks the calling thread until a reply is sent received from the queue.
00182         // The reply is assigned to the "theReply" argument.
00183         //
00184         // NOTE: You must acquire the queue's mutex exactly once before calling
00185         // this method. Acquiring the mutex more than once (i.e. recursively)
00186         // will result in a deadlock! If you don't acquire the mutex before
00187         // calling, the method will fail.
00188         //
00189         // This method makes no attempt to acquire its own mutex. The mutex should
00190         // be externally acquired before calling this method.
00191         //
00192         // Returns 0 if the reply was successfully retrieved, -1 otherwise.
00193         inline int GetReply_i(T &theReply);
00194 
00195 
00196         //
00197         // Sends a reply to the next waiter in GetReply().
00198         // This method should only be called when a GetReply() call is pending.
00199         // It will free the next GetReply() waiter and give them the "theReply"
00200         // argument.
00201         //
00202         // If acquireMutex is false, then the method will not acquire its own
00203         // mutex. Do this only if the mutex is already externally acquired.
00204         //
00205         // Returns 0 on success and -1 on failure.
00206         int SetReply(T &theReply, bool acquireMutex=true);
00207 
00208         //
00209         // Sends a reply to the next waiter in GetReply().
00210         // This method should only be called when a GetReply() call is pending.
00211         // It will free the next GetReply() waiter and give them the "theReply"
00212         // argument.
00213         //
00214         // This method makes no attempt to acquire its own mutex. The mutex should
00215         // be externally acquired before calling this method.
00216         //
00217         // Returns 0 on success and -1 on failure.
00218         inline int SetReply_i(T &theReply);
00219 
00220         //
00221         // Assigns the value of "from" to the object "to".
00222         // Returns a reference to "to".
00223         // This method exists solely to support partial template
00224         // specialization.
00225         inline T & Assign_i(T & from, T & to) { return to = from; }
00226 
00227         //
00228         // Returns a reference to this queue's mutex. Use this method
00229         // if you wish to synchonize other objects with this queue.
00230         inline ACE_SYNCH_MUTEX_T & GetMutex() { return m_replyQueueMutex; }
00231         
00232 protected:
00233         
00234         //
00235         // The PendingReply type corresponding to this template
00236         // instantiation.
00237         typedef PendingReply<T, ACE_SYNCH_USE>  PENDING_REPLY;
00238         //
00239         // The data type of the queue holding PendingReply's.
00240         typedef std::list<PENDING_REPLY *>              QUEUE_TYPE;
00241         
00242         //
00243         // The queue that holds PendingReply's.
00244         QUEUE_TYPE                                                              m_replyQueue;
00245 
00246         //
00247         // The mutex type that synchronizes this queue. If the synch
00248         // type is ACE_NULL_SYNCH, then this mutex is a functionless
00249         // dummy object.
00250         ACE_SYNCH_MUTEX_T &                                             m_replyQueueMutex;
00251 
00252         //
00253         // A flag that indicates whether the queue is closed. 
00254         bool                                                                    m_closed;
00255 };
00256 
00257 
00258 //
00259 // This class encapsulates a reply that is waiting in a ReplyQueue.
00260 template <class T, ACE_SYNCH_DECL>
00261 class PendingReply
00262 {
00263 public:
00264         //
00265         // The ReplyQueue type that holds this PendingReply type.
00266         typedef ReplyQueue<T, ACE_SYNCH_USE> REPLY_QUEUE;
00267 
00268         //
00269         // The ReplyQueue, being a friend of this class, is allowed
00270         // to access this class's protected and private members.
00271         // We don't use the typedef in the friend declaration
00272         // because some (namely MSVC++) compilers can't handle it.
00273         friend class ReplyQueue<T, ACE_SYNCH_USE>;
00274         
00275         //
00276         // Constructs a PendingReply. The "theReply" argument is a reference to
00277         // the object that will be set by PendingQueue::SetReply().  The "myMutex"
00278         // argument is a reference to the PendingQueue's mutex.
00279         PendingReply(T & theReply, ACE_SYNCH_MUTEX_T &myMutex)
00280                 : m_condition(myMutex), m_isEnqueued(false), m_theReply(theReply) {}
00281 
00282         //
00283         // Destroys a PendingReply.
00284         ~PendingReply() {}
00285         
00286 protected:
00287         //
00288         // The condition variable used to signal PendingQueue::GetReply() 
00289         // on success or failure.
00290         ACE_SYNCH_CONDITION_T   m_condition;
00291 
00292         //
00293         // Indicates whether this object is currently enqueued in the PendingQueue.
00294         // This is important when determining the validity of PendingQueue's
00295         // internal iterators.
00296         bool                                    m_isEnqueued;
00297 
00298         //
00299         // A reference to the object that will be set by a successful call to
00300         // PendingQueue::SetReply().  The object is provided by the caller of
00301         // PendingQueue::GetReply().
00302         T &                                             m_theReply;
00303 };
00304 
00305 
00306 
00307 
00308 
00309 template <class T, ACE_SYNCH_DECL>
00310 ReplyQueue<T, ACE_SYNCH_USE>::ReplyQueue(ACE_SYNCH_MUTEX_T &myMutex)
00311                 : m_replyQueueMutex(myMutex),
00312                   m_closed(false)
00313 {
00314 }
00315 
00316 
00317 template <class T, ACE_SYNCH_DECL>
00318 ReplyQueue<T, ACE_SYNCH_USE>::~ReplyQueue()
00319 {
00320         Close_i();
00321 }
00322 
00323 
00324 
00325 template <class T, ACE_SYNCH_DECL>
00326 int ReplyQueue<T, ACE_SYNCH_USE>::Close(bool acquireMutex)
00327 {
00328         if (acquireMutex)
00329         {
00330                 ACE_Guard<ACE_SYNCH_MUTEX_T> g(m_replyQueueMutex);
00331 
00332                 return Close_i();
00333         }
00334 
00335         return Close_i();
00336 }
00337 
00338 
00339         
00340 template <class T, ACE_SYNCH_DECL>
00341 int ReplyQueue<T, ACE_SYNCH_USE>::Close_i()
00342 {
00343         //
00344         // Double-check idiom. Ensure that the queue wasn't closed
00345         // while we were waiting to acquire the mutex.
00346         if (m_closed)
00347                 return -1;
00348                 
00349         //
00350         // Mark the queue as closed.
00351         m_closed = true;
00352                 
00353         //
00354         // Iterate through the queue and release all the
00355         // waiters. They'll see the queue is closed and return an error.
00356         typename QUEUE_TYPE::iterator   i = m_replyQueue.begin(),
00357                 end = m_replyQueue.end();
00358         
00359         //
00360         // A place to hold the results of system calls.
00361         int status = 0;
00362 
00363         //
00364         // Mark all the PendingReplies as no longer enqueued and signal
00365         // all the waiters.  The "status" variable collects any errors.
00366         for (; i != end; ++i)
00367         {
00368                 (*i)->m_isEnqueued = false;
00369                 status |= (*i)->m_condition.broadcast();
00370         }
00371                 
00372         //
00373         // Clear out the queue. Its contents are now invalid.
00374         m_replyQueue.clear();
00375 
00376         //
00377         // Return 0 on success or -1 if signaling any waiters failed.
00378         return status;
00379 }
00380 
00381 
00382 
00383 template <class T, ACE_SYNCH_DECL>
00384 bool ReplyQueue<T, ACE_SYNCH_USE>::IsEmpty(bool acquireMutex)
00385 {
00386         if (acquireMutex)
00387         {
00388                 //
00389                 // Don't bother acquiring the mutex if the queue is already closed. Just 
00390                 // report that it's empty (which it must be).
00391                 if (m_closed)
00392                         return true;
00393 
00394                 ACE_Guard<ACE_SYNCH_MUTEX_T> g(m_replyQueueMutex);
00395 
00396                 return IsEmpty_i();
00397         }
00398 
00399         return this->IsEmpty_i();
00400         return false;
00401 }
00402 
00403 
00404 
00405 template <class T, ACE_SYNCH_DECL>
00406 bool ReplyQueue<T, ACE_SYNCH_USE>::IsEmpty_i()
00407 {
00408         return m_replyQueue.empty();
00409 }
00410 
00411 
00412 
00413 template <class T, ACE_SYNCH_DECL>
00414 int ReplyQueue<T, ACE_SYNCH_USE>::GetReply(T &theReply, const ACE_Time_Value *deadline, bool acquireMutex)
00415 {
00416         if (acquireMutex)
00417         {
00418                 //
00419                 // Don't bother acquiring the mutex if the queue is already closed. Just 
00420                 // report failure.
00421                 if (m_closed)
00422                         return -1;
00423 
00424                 ACE_Guard<ACE_SYNCH_MUTEX_T> g(m_replyQueueMutex);
00425 
00426                 return GetReply_i(theReply, deadline);
00427         }
00428 
00429         return GetReply_i(theReply, deadline);
00430 }
00431 
00432 
00433 
00434 template <class T, ACE_SYNCH_DECL>
00435 int ReplyQueue<T, ACE_SYNCH_USE>::GetReply_i(T &theReply, const ACE_Time_Value *deadline)
00436 {
00437         //
00438         // Check to make sure the queue isn't closed already.
00439         if (m_closed)
00440         {
00441                 ACE_ERROR_RETURN((LM_ERROR,
00442                         "(%N:%l) Attempt to get a reply from a closed queue.\n"),
00443                         -1);
00444         }
00445 
00446         //
00447         // Construct a PendingReply so we can put it in the queue.
00448         // Do this before acquiring the mutex so we don't make other threads
00449         // wait through construction.
00450         PENDING_REPLY replyObj(theReply, m_replyQueueMutex);
00451         
00452         //
00453         // Mark the PendingReply as residing on the queue, and then add it to
00454         // the queue.
00455         replyObj.m_isEnqueued = true;
00456         typename QUEUE_TYPE::iterator it = m_replyQueue.insert(m_replyQueue.end(), &replyObj);
00457         
00458         //
00459         // Wait until signaled by a SetReply() call or until the deadline passes.
00460         // Note that m_replyQueueMutex is relinquished during the time we are 
00461         // waiting.  Its re-acquired on return from wait().
00462         int status = replyObj.m_condition.wait(deadline);
00463         
00464         //
00465         // If m_isEnqueued is still set, then remove the object from the queue
00466         // now. Since the queue is an STL list, the previously-recorded iterator
00467         // is still valid.
00468         if (replyObj.m_isEnqueued)
00469         {
00470                 m_replyQueue.erase(it);
00471         }
00472         
00473         //
00474         // If wait() failed, then this whole call failed.
00475         // Check with the ACE logger to see what the last error was.
00476         // It the failure was something other than a timeout, then log the
00477         // error. Timeout is a failure, but it isn't really an "error".
00478         if (status == -1 && ACE_Log_Msg::last_error_adapter() != ETIME)
00479         {
00480                 ACE_ERROR((LM_ERROR, "(%N:%l) %p\n", "acquire"));
00481         }
00482         //
00483         // If the queue is closed at this point then we didn't get a value. Log a
00484         // warning to aid in debugging and return -1.
00485         else if (m_closed)
00486         {
00487                 status = -1;
00488                 ACE_ERROR((LM_WARNING,
00489                         "(%N:%l) GetReply() failed because reply queue was closed before a response was set.\n"));
00490         }
00491 
00492         return status;
00493 }
00494 
00495 
00496 
00497 template <class T, ACE_SYNCH_DECL>
00498 int ReplyQueue<T, ACE_SYNCH_USE>::GetReply(T &theReply, bool acquireMutex)
00499 {
00500         if (acquireMutex)
00501         {
00502                 //
00503                 // Don't bother acquiring the mutex if the queue is already closed. Just 
00504                 // report failure.
00505                 if (m_closed)
00506                         return -1;
00507 
00508                 ACE_Guard<ACE_SYNCH_MUTEX_T> g(m_replyQueueMutex);
00509 
00510                 return GetReply_i(theReply);
00511         }
00512 
00513         return GetReply_i(theReply);
00514 }
00515 
00516 
00517 
00518 template <class T, ACE_SYNCH_DECL>
00519 int ReplyQueue<T, ACE_SYNCH_USE>::GetReply_i(T &theReply)
00520 {
00521         //
00522         // Check to make sure the queue isn't closed already.
00523         if (m_closed)
00524         {
00525                 ACE_ERROR_RETURN((LM_ERROR,
00526                         "(%N:%l) Attempt to get a reply from a closed queue.\n"),
00527                         -1);
00528         }
00529 
00530         //
00531         // Construct a PendingReply so we can put it in the queue.
00532         // Do this before acquiring the mutex so we don't make other threads
00533         // wait through construction.
00534         PENDING_REPLY replyObj(theReply, m_replyQueueMutex);
00535                         
00536         //
00537         // Mark the PendingReply as residing on the queue, and then add it to
00538         // the queue.
00539         replyObj.m_isEnqueued = true;
00540         typename QUEUE_TYPE::iterator it = m_replyQueue.insert(m_replyQueue.end(), &replyObj);
00541         
00542         //
00543         // Wait until signaled by a SetReply() call or until an error occurs.
00544         // Note that m_replyQueueMutex is relinquished during the time we are 
00545         // waiting.  Its re-acquired on return from wait().
00546         int status = replyObj.m_condition.wait();
00547         
00548         //
00549         // If m_isEnqueued is still set, then remove the object from the queue
00550         // now. Since the queue is an STL list, the previously-recorded iterator
00551         // is still valid.
00552         if (replyObj.m_isEnqueued)
00553         {
00554                 m_replyQueue.erase(it);
00555         }
00556         
00557         //
00558         // If wait() failed, then this whole call failed. Log an error message.
00559         if (status == -1)
00560         {
00561                 ACE_ERROR((LM_ERROR, "(%N:%l) %p\n", "LOCK::acquire"));
00562         }
00563         //
00564         // If the queue is closed at this point then we didn't get a value. Log a
00565         // warning to aid in debugging and return -1.
00566         else if (m_closed)
00567         {
00568                 status = -1;
00569                 ACE_ERROR((LM_WARNING,
00570                         "(%N:%l) GetReply() failed because reply queue was closed before a response was set.\n"));
00571         }
00572         
00573         return status;
00574 }
00575 
00576 
00577 
00578 template <class T, ACE_SYNCH_DECL>
00579 int ReplyQueue<T, ACE_SYNCH_USE>::SetReply(T &theReply, bool acquireMutex)
00580 {
00581         if (acquireMutex)
00582         {
00583                 //
00584                 // Don't bother acquiring the mutex if the queue is already closed. Just 
00585                 // report failure.
00586                 if (m_closed)
00587                         return -1;
00588 
00589                 ACE_Guard<ACE_SYNCH_MUTEX_T> g(m_replyQueueMutex);
00590 
00591                 return SetReply_i(theReply);
00592         }
00593 
00594         return SetReply_i(theReply);
00595 }
00596 
00597 
00598 
00599 template <class T, ACE_SYNCH_DECL>
00600 int ReplyQueue<T, ACE_SYNCH_USE>::SetReply_i(T &theReply)
00601 {
00602         //
00603         // A place to hold the status of system calls.
00604         int status = -1;
00605 
00606         //
00607         // If the queue is already closed the log an error and return -1.
00608         if (m_closed)
00609         {
00610                 ACE_ERROR_RETURN((LM_ERROR,
00611                         "(%N:%l) Attempt to get a reply from a closed queue.\n"),
00612                         -1);
00613         }
00614         
00615         //
00616         // If the queue is empty, then someone called this method in error.
00617         // Log an error and return -1.
00618         if (m_replyQueue.empty())
00619         {
00620                 ACE_ERROR_RETURN((LM_ERROR,
00621                         "(%N:%l) Attempt to set a reply when none are pending.\n"), -1);
00622         }
00623         else
00624         {
00625                 //
00626                 // Get the next PendingReply and mark it as no longer enqueued.
00627                 PENDING_REPLY * replyObj = m_replyQueue.front();
00628                 replyObj->m_isEnqueued = false;
00629                 m_replyQueue.pop_front();
00630 
00631                 //
00632                 // Assigns the value of theReply to replyObj->m_theReply
00633                 Assign_i(theReply, replyObj->m_theReply);
00634                 
00635                 //
00636                 // Notify the waiter that their reply is ready.
00637                 status = replyObj->m_condition.signal();
00638                 
00639                 //
00640                 // If notification failed, then log a message.
00641                 if (status == -1)
00642                 {
00643                         ACE_ERROR((LM_ERROR,
00644                                 "(%N:%l) %p\n", "ACE_Condition<>::signal"));
00645                 }
00646         }
00647         
00648         return status;
00649 }
00650 
00651 #if 0
00652 //
00653 // The following class is used to test compilation. It is not intended to be used.
00654 namespace
00655 {
00656         class ReplyQueueTester
00657         {
00658                 void TestCompilation()
00659                 {
00660                         ReplyQueue<int, ACE_MT_SYNCH>   foo1;
00661                         ReplyQueue<int, ACE_NULL_SYNCH> foo2;
00662                         ReplyQueue<int, ACE_SYNCH>              foo3;
00663                         
00664                         
00665                         ACE_Thread_Mutex        &m1 = foo1.GetMutex();
00666                         ACE_Null_Mutex          &m2 = foo2.GetMutex();
00667                         ACE_SYNCH_MUTEX         &m3 = foo3.GetMutex();
00668                         
00669                         int                                     status,
00670                                                                 arg;
00671                         
00672                         ACE_Time_Value          tv = ACE_OS::gettimeofday()
00673                                                                                 + ACE_Time_Value(10,0);
00674                         
00675                         status = foo1.GetReply(arg, &tv);
00676                         status = foo2.GetReply(arg, &tv);
00677                         status = foo3.GetReply(arg, &tv);
00678                         ;
00679                         status = foo1.GetReply(arg);
00680                         status = foo2.GetReply(arg);
00681                         status = foo3.GetReply(arg);
00682                         
00683                         status = foo1.SetReply(status);
00684                         status = foo2.SetReply(status);
00685                         status = foo3.SetReply(status);
00686                 }
00687         };
00688 }
00689 #endif // 0
00690 
00691 #endif // REPLY_QUEUE_H
00692 

Generated on Wed Sep 5 12:54:24 2007 for DSACSS Operational Code by  doxygen 1.3.9.1