Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Synch.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //==========================================================================
00004 /**
00005  *  @file    Synch.h
00006  *
00007  *  $Id: Synch.h,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $
00008  *
00009  *   Wrapper Facades for various synchronization mechanisms.
00010  *
00011  *  @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
00012  */
00013 //==========================================================================
00014 
00015 #ifndef ACE_SYNCH_H
00016 #define ACE_SYNCH_H
00017 #include "ace/pre.h"
00018 
00019 #include "ace/ACE_export.h"
00020 
00021 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00022 # pragma once
00023 #endif /* ACE_LACKS_PRAGMA_ONCE */
00024 
00025 #include "ace/OS.h"
00026 
00027 
00028 /**
00029  * @class ACE_Lock
00030  *
00031  * @brief This is the abstract base class that contains the uniform
00032  * locking API that is supported by all the ACE synchronization
00033  * mechanisms.
00034  *
00035  * This class is typically used in conjunction with the
00036  * <ACE_Lock_Adapter> in order to provide a polymorphic
00037  * interface to the ACE synchronization mechanisms (e.g.,
00038  * <ACE_Mutex>, <ACE_Semaphore>, <ACE_RW_Mutex>, etc).  Note that
00039  * the reason that all of ACE doesn't use polymorphic locks is
00040  * that (1) they add ~20% extra overhead for virtual function
00041  * calls and (2) objects with virtual functions can't be placed
00042  * into shared memory.
00043  */
00044 class ACE_Export ACE_Lock
00045 {
00046 public:
00047   /// CE needs a default ctor here.
00048   ACE_Lock (void);
00049 
00050   /// Noop virtual destructor
00051   virtual ~ACE_Lock (void);
00052 
00053   /**
00054    * Explicitly destroy the lock.  Note that only one thread should
00055    * call this method since it doesn't protect against race
00056    * conditions.
00057    */
00058   virtual int remove (void) = 0;
00059 
00060   /// Block the thread until the lock is acquired.  Returns -1 on
00061   /// failure.
00062   virtual int acquire (void) = 0;
00063 
00064   /**
00065    * Conditionally acquire the lock (i.e., won't block).  Returns -1
00066    * on failure.  If we "failed" because someone else already had the
00067    * lock, <errno> is set to <EBUSY>.
00068    */
00069   virtual int tryacquire (void) = 0;
00070 
00071   /// Release the lock.  Returns -1 on failure.
00072   virtual int release (void) = 0;
00073 
00074   /**
00075    * Block until the thread acquires a read lock.  If the locking
00076    * mechanism doesn't support read locks then this just calls
00077    * <acquire>.  Returns -1 on failure.
00078    */
00079   virtual int acquire_read (void) = 0;
00080 
00081   /**
00082    * Block until the thread acquires a write lock.  If the locking
00083    * mechanism doesn't support read locks then this just calls
00084    * <acquire>.  Returns -1 on failure.
00085    */
00086   virtual int acquire_write (void) = 0;
00087 
00088   /**
00089    * Conditionally acquire a read lock.  If the locking mechanism
00090    * doesn't support read locks then this just calls <acquire>.
00091    * Returns -1 on failure.  If we "failed" because someone else
00092    * already had the lock, <errno> is set to <EBUSY>.
00093    */
00094   virtual int tryacquire_read (void) = 0;
00095 
00096   /**
00097    * Conditionally acquire a write lock.  If the locking mechanism
00098    * doesn't support read locks then this just calls <acquire>.
00099    * Returns -1 on failure.  If we "failed" because someone else
00100    * already had the lock, <errno> is set to <EBUSY>.
00101    */
00102   virtual int tryacquire_write (void) = 0;
00103 
00104   /**
00105    * Conditionally try to upgrade a lock held for read to a write lock.
00106    * If the locking mechanism doesn't support read locks then this just
00107    * calls <acquire>. Returns 0 on success, -1 on failure.
00108    */
00109   virtual int tryacquire_write_upgrade (void) = 0;
00110 };
00111 
00112 /**
00113  * @class ACE_Adaptive_Lock
00114  *
00115  * @brief An adaptive general locking class that defers the decision of
00116  * lock type to run time.
00117  *
00118  * This class, as ACE_Lock, provide a set of general locking APIs.
00119  * However, it defers our decision of what kind of lock to use
00120  * to the run time and delegates all locking operations to the actual
00121  * lock.  Users must define a constructor in their subclass to
00122  * initialize <lock_>.
00123  */
00124 class ACE_Export ACE_Adaptive_Lock : public ACE_Lock
00125 {
00126 public:
00127   /// You must also override the destructor function to match with how
00128   /// you construct the underneath <lock_>.
00129   virtual ~ACE_Adaptive_Lock (void);
00130 
00131   // = Lock/unlock operations.
00132 
00133   virtual int remove (void);
00134   virtual int acquire (void);
00135   virtual int tryacquire (void);
00136   virtual int release (void);
00137   virtual int acquire_read (void);
00138   virtual int acquire_write (void);
00139   virtual int tryacquire_read (void);
00140   virtual int tryacquire_write (void);
00141   virtual int tryacquire_write_upgrade (void);
00142   void dump (void) const;
00143 
00144 protected:
00145   /**
00146    * Create and initialize create the actual lcok used in the class.
00147    * The default constructor simply set the <lock_> to 0 (null).  You
00148    * must overwrite this method for this class to work.
00149    */
00150   ACE_Adaptive_Lock (void);
00151 
00152   ACE_Lock *lock_;
00153 };
00154 
00155 /**
00156  * @class ACE_Semaphore
00157  *
00158  * @brief Wrapper for Dijkstra style general semaphores.
00159  */
00160 class ACE_Export ACE_Semaphore
00161 {
00162 public:
00163   // = Initialization and termination.
00164   /// Initialize the semaphore, with initial value of "count".
00165   ACE_Semaphore (u_int count = 1, // By default make this unlocked.
00166                  int type = USYNC_THREAD,
00167                  const ACE_TCHAR *name = 0,
00168                  void * = 0,
00169                  int max = 0x7fffffff);
00170 
00171   /// Implicitly destroy the semaphore.
00172   ~ACE_Semaphore (void);
00173 
00174   /**
00175    * Explicitly destroy the semaphore.  Note that only one thread
00176    * should call this method since it doesn't protect against race
00177    * conditions.
00178    */
00179   int remove (void);
00180 
00181   /// Block the thread until the semaphore count becomes
00182   /// greater than 0, then decrement it.
00183   int acquire (void);
00184 
00185   /**
00186    * Block the thread until the semaphore count becomes greater than 0
00187    * (at which point it is decremented) or until <tv> times out (in
00188    * which case -1 is returned and <errno> == <ETIME>).  Note that <tv>
00189    * is assumed to be in "absolute" rather than "relative" time.  The
00190    * value of <tv> is updated upon return to show the actual
00191    * (absolute) acquisition time.
00192    *
00193    * NOTE: Solaris threads do not support timed semaphores.
00194    * Therefore, if you're running on Solaris you might want to
00195    * consider using the ACE POSIX pthreads implementation instead,
00196    * which can be enabled by compiling ACE with
00197    * -DACE_HAS_PTHREADS, rather than -DACE_HAS_STHREADS or
00198    * -DACE_HAS_POSIX_SEM. */
00199   int acquire (ACE_Time_Value &tv);
00200 
00201   /**
00202    * If <tv> == 0 then call <acquire()> directly.  Otherwise, Block
00203    * the thread until the semaphore count becomes greater than 0
00204    * (at which point it is decremented) or until <tv> times out (in
00205    * which case -1 is returned and <errno> == <ETIME>).  Note that
00206    * <*tv> is assumed to be in "absolute" rather than "relative" time.
00207    * The value of <*tv> is updated upon return to show the actual
00208    * (absolute) acquisition time.
00209    *
00210    * NOTE: Solaris threads do not support timed semaphores.
00211    * Therefore, if you're running on Solaris you might want to
00212    * consider using the ACE POSIX pthreads implementation instead,
00213    * which can be enabled by compiling ACE with
00214    * -DACE_HAS_PTHREADS, rather than -DACE_HAS_STHREADS or
00215    * -DACE_HAS_POSIX_SEM.  */
00216   int acquire (ACE_Time_Value *tv);
00217 
00218   /**
00219    * Conditionally decrement the semaphore if count is greater than 0
00220    * (i.e., won't block).  Returns -1 on failure.  If we "failed"
00221    * because someone else already had the lock, <errno> is set to
00222    * <EBUSY>.
00223    */
00224   int tryacquire (void);
00225 
00226   /// Increment the semaphore by 1, potentially unblocking a waiting
00227   /// thread.
00228   int release (void);
00229 
00230   /// Increment the semaphore by <release_count>, potentially
00231   /// unblocking waiting threads.
00232   int release (u_int release_count);
00233 
00234   /**
00235    * Acquire semaphore ownership.  This calls <acquire> and is only
00236    * here to make the <ACE_Semaphore> interface consistent with the
00237    * other synchronization APIs.
00238    */
00239   int acquire_read (void);
00240 
00241   /**
00242    * Acquire semaphore ownership.  This calls <acquire> and is only
00243    * here to make the <ACE_Semaphore> interface consistent with the
00244    * other synchronization APIs.
00245    */
00246   int acquire_write (void);
00247 
00248   /**
00249    * Conditionally acquire semaphore (i.e., won't block).  This calls
00250    * <tryacquire> and is only here to make the <ACE_Semaphore>
00251    * interface consistent with the other synchronization APIs.
00252    * Returns -1 on failure.  If we "failed" because someone else
00253    * already had the lock, <errno> is set to <EBUSY>.
00254    */
00255   int tryacquire_read (void);
00256 
00257   /**
00258    * Conditionally acquire semaphore (i.e., won't block).  This calls
00259    * <tryacquire> and is only here to make the <ACE_Semaphore>
00260    * interface consistent with the other synchronization APIs.
00261    * Returns -1 on failure.  If we "failed" because someone else
00262    * already had the lock, <errno> is set to <EBUSY>.
00263    */
00264   int tryacquire_write (void);
00265 
00266   /**
00267    * This is only here to make the <ACE_Semaphore>
00268    * interface consistent with the other synchronization APIs.
00269    * Assumes the caller has already acquired the semaphore using one of
00270    * the above calls, and returns 0 (success) always.
00271    */
00272   int tryacquire_write_upgrade (void);
00273 
00274   /// Dump the state of an object.
00275   void dump (void) const;
00276 
00277   /// Declare the dynamic allocation hooks.
00278   ACE_ALLOC_HOOK_DECLARE;
00279 
00280   /// Return the underlying lock.
00281   const ACE_sema_t &lock (void) const;
00282 
00283 protected:
00284   ACE_sema_t semaphore_;
00285 
00286   /// Keeps track of whether <remove> has been called yet to avoid
00287   /// multiple <remove> calls, e.g., explicitly and implicitly in the
00288   /// destructor.  This flag isn't protected by a lock, so make sure
00289   /// that you don't have multiple threads simultaneously calling
00290   /// <remove> on the same object, which is a bad idea anyway...
00291   int removed_;
00292 
00293 private:
00294   // = Prevent assignment and initialization.
00295   void operator= (const ACE_Semaphore &);
00296   ACE_Semaphore (const ACE_Semaphore &);
00297 };
00298 
00299 /**
00300  * @class ACE_Null_Semaphore
00301  *
00302  * @brief Implement a do nothing <ACE_Semaphore>, i.e., all the methods are
00303  * no ops.
00304  *
00305  * Although the methods are no-ops, the return values are different for
00306  * the blocking as opposed to timed acquires.  The blocking version of
00307  * acquire() is often used to serialize access to a critical section,
00308  * whereas the timed version is often used to wait for another thread
00309  * to update some condition or change some shared state.  When using an
00310  * ACE_Null_Semaphore, however, there's no other thread involved to
00311  * change a state or condition (otherwise, a null semaphore would be
00312  * inappropriate).  Returning an error value signifies that the
00313  * state or condition has not been (and can't be) changed, which is
00314  * consistent with the behavior of the threaded case where a timeout
00315  * occurs before the state or condition is changed.
00316  */
00317 class ACE_Export ACE_Null_Semaphore
00318 {
00319 public:
00320   ACE_Null_Semaphore (u_int count = 1, // By default make this unlocked.
00321                        int type = USYNC_THREAD,
00322                        const ACE_TCHAR *name = 0,
00323                        void * = 0,
00324                        int max = 0x7fffffff);
00325   ~ACE_Null_Semaphore (void);
00326   /// Return 0.
00327   int remove (void);
00328 
00329   /// Return 0.
00330   int acquire (void);
00331 
00332   /// Return -1 with <errno> == <ETIME>.
00333   int acquire (ACE_Time_Value &);
00334 
00335   /// Return -1 with <errno> == <ETIME>.
00336   int acquire (ACE_Time_Value *);
00337 
00338   /// Return 0.
00339   int tryacquire (void);
00340 
00341   /// Return 0.
00342   int release (void);
00343 
00344   /// Return 0.
00345   int release (size_t);
00346 
00347   /// Return 0.
00348   int acquire_write (void);
00349 
00350   /// Return 0.
00351   int tryacquire_write (void);
00352 
00353   /// Return 0.
00354   int tryacquire_write_upgrade (void);
00355 
00356   /// Return 0.
00357   int acquire_read (void);
00358 
00359   /// Return 0.
00360   int tryacquire_read (void);
00361 
00362   /// Dump the state of an object.
00363   void dump (void) const;
00364 
00365   /// Declare the dynamic allocation hooks.
00366   ACE_ALLOC_HOOK_DECLARE;
00367 };
00368 
00369 /**
00370  * @class ACE_RW_Mutex
00371  *
00372  * @brief Wrapper for readers/writer locks.
00373  *
00374  * These are most useful for applications that have many more
00375  * parallel readers than writers...
00376  */
00377 class ACE_Export ACE_RW_Mutex
00378 {
00379 public:
00380   /// Initialize a readers/writer lock.
00381   ACE_RW_Mutex (int type = USYNC_THREAD,
00382                 const ACE_TCHAR *name = 0,
00383                 void *arg = 0);
00384 
00385   /// Implicitly destroy a readers/writer lock
00386   ~ACE_RW_Mutex (void);
00387 
00388   /**
00389    * Explicitly destroy a readers/writer lock.  Note that only one
00390    * thread should call this method since it doesn't protect against
00391    * race conditions.
00392    */
00393   int remove (void);
00394 
00395   /// Acquire a read lock, but block if a writer hold the lock.
00396   int acquire_read (void);
00397 
00398   /// Acquire a write lock, but block if any readers or a
00399   /// writer hold the lock.
00400   int acquire_write (void);
00401 
00402   /**
00403    * Conditionally acquire a read lock (i.e., won't block).  Returns
00404    * -1 on failure.  If we "failed" because someone else already had
00405    * the lock, <errno> is set to <EBUSY>.
00406    */
00407   int tryacquire_read (void);
00408 
00409   /// Conditionally acquire a write lock (i.e., won't block).
00410   int tryacquire_write (void);
00411 
00412   /**
00413    * Conditionally upgrade a read lock to a write lock.  This only
00414    * works if there are no other readers present, in which case the
00415    * method returns 0.  Otherwise, the method returns -1 and sets
00416    * <errno> to <EBUSY>.  Note that the caller of this method *must*
00417    * already possess this lock as a read lock (but this condition is
00418    * not checked by the current implementation).
00419    */
00420   int tryacquire_write_upgrade (void);
00421 
00422   /**
00423    * Note, for interface uniformity with other synchronization
00424    * wrappers we include the <acquire> method.  This is implemented as
00425    * a write-lock to safe...
00426    */
00427   int acquire (void);
00428 
00429   /**
00430    * Note, for interface uniformity with other synchronization
00431    * wrappers we include the <tryacquire> method.  This is implemented
00432    * as a write-lock to be safe...  Returns -1 on failure.  If we
00433    * "failed" because someone else already had the lock, <errno> is
00434    * set to <EBUSY>.
00435    */
00436   int tryacquire (void);
00437 
00438   /// Unlock a readers/writer lock.
00439   int release (void);
00440 
00441   /// Return the underlying lock.
00442   const ACE_rwlock_t &lock (void) const;
00443 
00444   /// Dump the state of an object.
00445   void dump (void) const;
00446 
00447   /// Declare the dynamic allocation hooks.
00448   ACE_ALLOC_HOOK_DECLARE;
00449 
00450 protected:
00451   /// Readers/writer lock.
00452   ACE_rwlock_t lock_;
00453 
00454   /// Keeps track of whether <remove> has been called yet to avoid
00455   /// multiple <remove> calls, e.g., explicitly and implicitly in the
00456   /// destructor.  This flag isn't protected by a lock, so make sure
00457   /// that you don't have multiple threads simultaneously calling
00458   /// <remove> on the same object, which is a bad idea anyway...
00459   int removed_;
00460 
00461 private:
00462   // = Prevent assignment and initialization.
00463   void operator= (const ACE_RW_Mutex &);
00464   ACE_RW_Mutex (const ACE_RW_Mutex &);
00465 };
00466 
00467 /**
00468  * @class ACE_Mutex
00469  *
00470  * @brief <ACE_Mutex> wrapper (valid in same process or across
00471  * processes (depending on TYPE flag)).
00472  */
00473 class ACE_Export ACE_Mutex
00474 {
00475 public:
00476   /// Initialize the mutex.
00477   ACE_Mutex (int type = USYNC_THREAD,
00478              const ACE_TCHAR *name = 0,
00479              ACE_mutexattr_t *arg = 0,
00480              mode_t mode = ACE_DEFAULT_FILE_PERMS);
00481 
00482   /// Implicitly destroy the mutex.
00483   ~ACE_Mutex (void);
00484 
00485   /**
00486    * Explicitly destroy the mutex.  Note that only one thread should
00487    * call this method since it doesn't protect against race
00488    * conditions.
00489    */
00490   int remove (void);
00491 
00492   /// Acquire lock ownership (wait on queue if necessary).
00493   int acquire (void);
00494 
00495   /**
00496    * Block the thread until the mutex is acquired or <tv> times out,
00497    * in which case -1 is returned and <errno> == <ETIME>.  Note that
00498    * <tv> is assumed  to be in "absolute" rather than "relative" time.
00499    * The value of <tv> is updated upon return to show the actual
00500    * (absolute) acquisition time.
00501    */
00502   int acquire (ACE_Time_Value &tv);
00503 
00504   /**
00505    * If <tv> == 0 then call <acquire()> directly.  Otherwise, block
00506    * the thread until the mutex is acquired or <tv> times out, in
00507    * which case -1 is returned and <errno> == <ETIME>.  Note that
00508    * <*tv> is assumed to be in "absolute" rather than "relative" time.
00509    * The value of <*tv> is updated upon return to show the actual
00510    * (absolute) acquisition time.  */
00511   int acquire (ACE_Time_Value *tv);
00512 
00513   /**
00514    * Conditionally acquire lock (i.e., don't wait on queue).  Returns
00515    * -1 on failure.  If we "failed" because someone else already had
00516    * the lock, <errno> is set to <EBUSY>.
00517    */
00518   int tryacquire (void);
00519 
00520   /// Release lock and unblock a thread at head of queue.
00521   int release (void);
00522 
00523   /**
00524    * Acquire mutex ownership.  This calls <acquire> and is only
00525    * here to make the <ACE_Mutex> interface consistent with the
00526    * other synchronization APIs.
00527    */
00528   int acquire_read (void);
00529 
00530   /**
00531    * Acquire mutex ownership.  This calls <acquire> and is only
00532    * here to make the <ACE_Mutex> interface consistent with the
00533    * other synchronization APIs.
00534    */
00535   int acquire_write (void);
00536 
00537   /**
00538    * Conditionally acquire mutex (i.e., won't block).  This calls
00539    * <tryacquire> and is only here to make the <ACE_Mutex> interface
00540    * consistent with the other synchronization APIs.  Returns -1 on
00541    * failure.  If we "failed" because someone else already had the
00542    * lock, <errno> is set to <EBUSY>.
00543    */
00544   int tryacquire_read (void);
00545 
00546   /**
00547    * Conditionally acquire mutex (i.e., won't block).  This calls
00548    * <tryacquire> and is only here to make the <ACE_Mutex> interface
00549    * consistent with the other synchronization APIs.  Returns -1 on
00550    * failure.  If we "failed" because someone else already had the
00551    * lock, <errno> is set to <EBUSY>.
00552    */
00553   int tryacquire_write (void);
00554 
00555   /**
00556    * This is only here for consistency with the other synchronization
00557    * APIs and usability with Lock adapters. Assumes the caller already has
00558    * acquired the mutex and returns 0 in all cases.
00559    */
00560   int tryacquire_write_upgrade (void);
00561 
00562   /// Return the underlying mutex.
00563   const ACE_mutex_t &lock (void) const;
00564 
00565   /// Dump the state of an object.
00566   void dump (void) const;
00567 
00568   /// Declare the dynamic allocation hooks.
00569   ACE_ALLOC_HOOK_DECLARE;
00570 
00571   // = This should be protected but some C++ compilers complain...
00572 public:
00573 #if defined (CHORUS) || defined(ACE_HAS_PTHREADS) || defined(ACE_HAS_STHREADS)
00574   /// This lock resides in shared memory.
00575   ACE_mutex_t *process_lock_;
00576 
00577   /**
00578    * Remember the name of the mutex if we created it so we can unlink
00579    * it when we go away (only the actor that initialized the memory
00580    * can destroy it).
00581    */
00582   const ACE_TCHAR *lockname_;
00583 #endif /* CHORUS || ACE_HAS_PTHREADS */
00584 
00585   /// Mutex type supported by the OS.
00586   ACE_mutex_t lock_;
00587 
00588   /// Keeps track of whether <remove> has been called yet to avoid
00589   /// multiple <remove> calls, e.g., explicitly and implicitly in the
00590   /// destructor.  This flag isn't protected by a lock, so make sure
00591   /// that you don't have multiple threads simultaneously calling
00592   /// <remove> on the same object, which is a bad idea anyway...
00593   int removed_;
00594 
00595 private:
00596   // = Prevent assignment and initialization.
00597   void operator= (const ACE_Mutex &);
00598   ACE_Mutex (const ACE_Mutex &);
00599 };
00600 
00601 /**
00602  * @class ACE_Null_Barrier
00603  *
00604  * @brief Implements "NULL barrier synchronization".
00605  */
00606 class ACE_Export ACE_Null_Barrier
00607 {
00608 public:
00609   /// Initialize the barrier to synchronize <count> threads.
00610   ACE_Null_Barrier (u_int,
00611                     const char * = 0,
00612                     void * = 0);
00613 
00614   /// Default dtor.
00615   ~ACE_Null_Barrier (void);
00616 
00617   /// Block the caller until all <count> threads have called <wait> and
00618   /// then allow all the caller threads to continue in parallel.
00619   int wait (void);
00620 
00621   /// Dump the state of an object.
00622   void dump (void) const;
00623 
00624   /// Declare the dynamic allocation hooks.
00625   ACE_ALLOC_HOOK_DECLARE;
00626 
00627 private:
00628   // = Prevent assignment and initialization.
00629   void operator= (const ACE_Null_Barrier &);
00630   ACE_Null_Barrier (const ACE_Null_Barrier &);
00631 };
00632 
00633 /**
00634  * @class ACE_Null_Mutex
00635  *
00636  * @brief Implement a do nothing <ACE_Mutex>, i.e., all the methods are
00637  * no ops.
00638  */
00639 class ACE_Export ACE_Null_Mutex
00640 {
00641 public:
00642   ACE_Null_Mutex (const ACE_TCHAR * = 0);
00643   ~ACE_Null_Mutex (void);
00644   /// Return 0.
00645   int remove (void);
00646 
00647   /// Return 0.
00648   int acquire (void);
00649 
00650   /// Return -1 with <errno> == <ETIME>.
00651   int acquire (ACE_Time_Value &timeout);
00652 
00653   /// Return -1 with <errno> == <ETIME>.
00654   int acquire (ACE_Time_Value *timeout);
00655 
00656   /// Return 0.
00657   int tryacquire (void);
00658 
00659   /// Return 0.
00660   int release (void);
00661 
00662   /// Return 0.
00663   int acquire_write (void);
00664 
00665   /// Return 0.
00666   int tryacquire_write (void);
00667 
00668   /// Return 0.
00669   int tryacquire_write_upgrade (void);
00670 
00671   /// Return 0.
00672   int acquire_read (void);
00673 
00674   /// Return 0.
00675   int tryacquire_read (void);
00676 
00677   /// Dump the state of an object.
00678   void dump (void) const;
00679 
00680   /// Declare the dynamic allocation hooks.
00681   ACE_ALLOC_HOOK_DECLARE;
00682 
00683   int lock_; // A dummy lock.
00684 };
00685 
00686 class ACE_Export ACE_Noop_Token : public ACE_Null_Mutex
00687 {
00688 public:
00689   /// Queueing strategy
00690   enum QUEUEING_STRATEGY
00691   {
00692     FIFO = -1,
00693     LIFO = 0
00694   };
00695 
00696   /// Get queueing strategy.
00697   int queueing_strategy (void);
00698 
00699   /// Set queueing strategy.
00700   void queueing_strategy (int queueing_strategy);
00701 
00702   int renew (int = 0, ACE_Time_Value * =0);
00703 
00704   /// Dump the state of an object.
00705   void dump (void) const;
00706 
00707   /// Declare the dynamic allocation hooks.
00708   ACE_ALLOC_HOOK_DECLARE;
00709 };
00710 
00711 /**
00712  * @class ACE_Null_Condition
00713  *
00714  * @brief Implement a do nothing <ACE_Condition> variable wrapper,
00715  * i.e., all methods are no ops.  This class is necessary since
00716  * some C++ compilers are *very* lame...
00717  */
00718 class ACE_Export ACE_Null_Condition
00719 {
00720 public:
00721   ACE_Null_Condition (const ACE_Null_Mutex &m,
00722                       const ACE_TCHAR * = 0,
00723                       void * = 0);
00724   ~ACE_Null_Condition (void);
00725 
00726   /// Returns 0.
00727   int remove (void);
00728 
00729   /// Returns -1 with <errno> == <ETIME>.
00730   int wait (const ACE_Time_Value * = 0);
00731 
00732   /// Returns 0.
00733   int signal (void);
00734 
00735   /// Returns 0.
00736   int broadcast (void);
00737   ACE_Null_Mutex &mutex (void);
00738 
00739   /// Dump the state of an object.
00740   void dump (void) const;
00741 
00742   // ACE_ALLOC_HOOK_DECLARE;
00743   // Declare the dynamic allocation hooks.
00744 
00745 protected:
00746   ACE_Null_Mutex &mutex_; // Reference to mutex lock.
00747 
00748 private:
00749   // = Prevent assignment and initialization.
00750   void operator= (const ACE_Null_Condition &);
00751   ACE_Null_Condition (const ACE_Null_Condition &);
00752 };
00753 
00754 #if defined (ACE_USES_OBSOLETE_GUARD_CLASSES)
00755 /**
00756  * @class ACE_Null_Mutex_Guard
00757  *
00758  * @brief This data structure is meant to be used within a method or
00759  * function...  It performs automatic aquisition and release of
00760  * an ACE_Null_Mutex.
00761  *
00762  * This class is obsolete and should be replaced by
00763  * ACE_Guard<ACE_Null_Mutex>.
00764  */
00765 class ACE_Export ACE_Null_Mutex_Guard
00766 {
00767 public:
00768   ACE_Null_Mutex_Guard (ACE_Null_Mutex &);
00769   ~ACE_Null_Mutex_Guard (void);
00770   int remove (void);
00771   int locked (void);
00772   int acquire (void);
00773   int tryacquire (void);
00774   int release (void);
00775   void dump (void) const;
00776 
00777 private:
00778   // = Prevent assignment and initialization.
00779   void operator= (const ACE_Null_Mutex_Guard &);
00780   ACE_Null_Mutex_Guard (const ACE_Null_Mutex_Guard &);
00781 };
00782 #endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */
00783 
00784 /**
00785  * @class ACE_TSS_Adapter
00786  *
00787  * @brief This class encapsulates a TSS object and its associated
00788  * C++ destructor function.  It is used by the ACE_TSS...
00789  * methods (in Synch_T.cpp) in order to allow an extern
00790  * "C" cleanup routine to be used.  Needed by the "frigging"
00791  * MVS C++ compiler.
00792  *
00793  * Objects of this class are stored in thread specific
00794  * storage. ts_obj_ points to the "real" object and
00795  * func_ is a pointer to the C++ cleanup function for ts_obj_.
00796  */
00797 class ACE_Export ACE_TSS_Adapter
00798 {
00799 public:
00800   /// Initialize the adapter.
00801   ACE_TSS_Adapter (void *object, ACE_THR_DEST f);
00802 
00803   /// Default dtor.
00804   ~ACE_TSS_Adapter (void);
00805 
00806   /// Perform the cleanup operation.
00807   void cleanup (void);
00808 
00809 //private:
00810 
00811   /// The real TS object.
00812   void *ts_obj_;
00813 
00814   /// The real cleanup routine for ts_obj;
00815   ACE_THR_DEST func_;
00816 };
00817 
00818 /**
00819  * @class ACE_Event
00820  *
00821  * @brief A wrapper around the Win32 event locking mechanism.
00822  *
00823  * Portable implementation of an Event mechanism, which is native to
00824  * Win32, but must be emulated on UNIX.  All platforms support
00825  * process-scope locking support.  However, only Win32 platforms
00826  * support global naming and system-scope locking support.
00827  */
00828 class ACE_Export ACE_Event
00829 {
00830 public:
00831   /// Constructor that creates event.
00832   ACE_Event (int manual_reset = 0,
00833              int initial_state = 0,
00834              int type = USYNC_THREAD,
00835              const ACE_TCHAR *name = 0,
00836              void *arg = 0);
00837 
00838   /// Implicitly destroy the event variable.
00839   ~ACE_Event (void);
00840 
00841   /**
00842    * Explicitly destroy the event variable.  Note that only one thread
00843    * should call this method since it doesn't protect against race
00844    * conditions.
00845    */
00846   int remove (void);
00847 
00848   /// Underlying handle to event.
00849   ACE_event_t handle (void) const;
00850 
00851   /**
00852    * Set the underlying handle to event. Note that this method assumes
00853    * ownership of the <handle> and will close it down in <remove>.  If
00854    * you want the <handle> to stay open when <remove> is called make
00855    * sure to call <dup> on the <handle> before closing it.  You are
00856    * responsible for the closing the existing <handle> before
00857    * overwriting it.
00858    */
00859   void handle (ACE_event_t new_handle);
00860 
00861   /**
00862    * if MANUAL reset
00863    *    sleep till the event becomes signaled
00864    *    event remains signaled after wait() completes.
00865    * else AUTO reset
00866    *    sleep till the event becomes signaled
00867    *    event resets wait() completes.
00868    */
00869   int wait (void);
00870 
00871   /// Same as wait() above, but this one can be timed
00872   /// <abstime> is absolute time-of-day if if <use_absolute_time>
00873   /// is non-0, else it is relative time.
00874   int wait (const ACE_Time_Value *abstime,
00875             int use_absolute_time = 1);
00876 
00877   /**
00878    * if MANUAL reset
00879    *    wake up all waiting threads
00880    *    set to signaled state
00881    * else AUTO reset
00882    *    if no thread is waiting, set to signaled state
00883    *    if thread(s) are waiting, wake up one waiting thread and
00884    *    reset event
00885    */
00886   int signal (void);
00887 
00888   /**
00889    * if MANUAL reset
00890    *    wakeup all waiting threads and
00891    *    reset event
00892    * else AUTO reset
00893    *    wakeup one waiting thread (if present) and
00894    *    reset event
00895    */
00896   int pulse (void);
00897 
00898   /// Set to nonsignaled state.
00899   int reset (void);
00900 
00901   /// Dump the state of an object.
00902   void dump (void) const;
00903 
00904   /// Declare the dynamic allocation hooks
00905   ACE_ALLOC_HOOK_DECLARE;
00906 
00907 protected:
00908   /// The underlying handle.
00909   ACE_event_t handle_;
00910 
00911   /// Keeps track of whether <remove> has been called yet to avoid
00912   /// multiple <remove> calls, e.g., explicitly and implicitly in the
00913   /// destructor.  This flag isn't protected by a lock, so make sure
00914   /// that you don't have multiple threads simultaneously calling
00915   /// <remove> on the same object, which is a bad idea anyway...
00916   int removed_;
00917 
00918 private:
00919   // = Prevent copying.
00920   ACE_Event (const ACE_Event& event);
00921   const ACE_Event &operator= (const ACE_Event &rhs);
00922 };
00923 
00924 /**
00925  * @class ACE_Manual_Event
00926  *
00927  * @brief Manual Events.
00928  *
00929  * Specialization of Event mechanism which wakes up all waiting
00930  * thread on <signal>.  All platforms support process-scope locking
00931  * support.  However, only Win32 platforms support global naming and
00932  * system-scope locking support.
00933  */
00934 class ACE_Export ACE_Manual_Event : public ACE_Event
00935 {
00936 public:
00937   /// constructor which will create manual event
00938   ACE_Manual_Event (int initial_state = 0,
00939                     int type = USYNC_THREAD,
00940                     const char *name = 0,
00941                     void *arg = 0);
00942 
00943 #if defined (ACE_HAS_WCHAR)
00944   /// constructor which will create manual event (wchar_t version)
00945   ACE_Manual_Event (int initial_state,
00946                     int type,
00947                     const wchar_t *name,
00948                     void *arg = 0);
00949 #endif /* ACE_HAS_WCHAR */
00950 
00951   /// Default dtor.
00952   ~ACE_Manual_Event (void);
00953 
00954   /// Dump the state of an object.
00955   void dump (void) const;
00956 
00957   /// Declare the dynamic allocation hooks
00958   ACE_ALLOC_HOOK_DECLARE;
00959 };
00960 
00961 /**
00962  * @class ACE_Auto_Event
00963  *
00964  * @brief Auto Events.
00965  *
00966  * Specialization of Event mechanism which wakes up one waiting
00967  * thread on <signal>.  All platforms support process-scope locking
00968  * support.  However, only Win32 platforms support global naming and
00969  * system-scope locking support.
00970  */
00971 class ACE_Export ACE_Auto_Event : public ACE_Event
00972 {
00973 public:
00974   /// constructor which will create auto event
00975   ACE_Auto_Event (int initial_state = 0,
00976                   int type = USYNC_THREAD,
00977                   const char *name = 0,
00978                   void *arg = 0);
00979 
00980 #if defined (ACE_HAS_WCHAR)
00981   /// constructor which will create auto event (wchar_t version)
00982   ACE_Auto_Event (int initial_state,
00983                   int type,
00984                   const wchar_t *name,
00985                   void *arg = 0);
00986 #endif /* ACE_HAS_WCHAR */
00987 
00988   /// Default dtor.
00989   ~ACE_Auto_Event (void);
00990 
00991   /// Dump the state of an object.
00992   void dump (void) const;
00993 
00994   /// Declare the dynamic allocation hooks
00995   ACE_ALLOC_HOOK_DECLARE;
00996 };
00997 
00998 // ACE platform supports some form of threading.
00999 #if !defined (ACE_HAS_THREADS)
01000 /**
01001  * @class ACE_Barrier
01002  *
01003  * @brief This is a no-op to make ACE "syntactically consistent."
01004  */
01005 class ACE_Barrier
01006 {
01007 public:
01008   ACE_Barrier (u_int, const ACE_TCHAR * = 0, void * = 0) {}
01009   ~ACE_Barrier (void) {}
01010   int wait (void) { ACE_NOTSUP_RETURN (-1); }
01011   void dump (void) const {}
01012 };
01013 #else
01014   /**
01015    * @class ACE_Thread_Mutex
01016    *
01017    * @brief ACE_Thread_Mutex wrapper (only valid for threads in the same
01018    * process).
01019    *
01020    * This implementation is optimized for locking threads that are
01021    * in the same process.  It maps to <CRITICAL_SECTION>s on NT
01022    * and <ACE_mutex_t> with <type> set to <USYNC_THREAD> on UNIX.
01023    * ACE_Thread_Mutex is recursive on some platforms (like
01024    * Win32). However, on most platforms (like Solaris) it is not
01025    * recursive.  To be totally safe and portable, developers
01026    * should use <ACE_Recursive_Thread_Mutex> when they need a
01027    * recursive mutex.
01028    */
01029 class ACE_Export ACE_Thread_Mutex
01030 {
01031   friend class ACE_Condition_Thread_Mutex;
01032 public:
01033   /// Constructor.
01034   ACE_Thread_Mutex (const ACE_TCHAR *name = 0,
01035                     ACE_mutexattr_t *attributes = 0);
01036 
01037   /// Implicitly destroy the mutex.
01038   ~ACE_Thread_Mutex (void);
01039 
01040   /**
01041    * Explicitly destroy the mutex.  Note that only one thread should
01042    * call this method since it doesn't protect against race
01043    * conditions.
01044    */
01045   int remove (void);
01046 
01047   /// Acquire lock ownership (wait on queue if necessary).
01048   int acquire (void);
01049 
01050   /**
01051    * Block the thread until we acquire the mutex or until <tv> times
01052    * out, in which case -1 is returned with <errno> == <ETIME>.  Note
01053    * that <tv> is assumed to be in "absolute" rather than "relative"
01054    * time.  The value of <tv> is updated upon return to show the
01055    * actual (absolute) acquisition time.
01056    */
01057   int acquire (ACE_Time_Value &tv);
01058 
01059   /**
01060    * If <tv> == 0 the call <acquire()> directly.  Otherwise, Block the
01061    * thread until we acquire the mutex or until <tv> times out, in
01062    * which case -1 is returned with <errno> == <ETIME>.  Note that
01063    * <*tv> is assumed to be in "absolute" rather than "relative" time.
01064    * The value of <*tv> is updated upon return to show the actual
01065    * (absolute) acquisition time.
01066    */
01067   int acquire (ACE_Time_Value *tv);
01068 
01069   /**
01070    * Conditionally acquire lock (i.e., don't wait on queue).  Returns
01071    * -1 on failure.  If we "failed" because someone else already had
01072    * the lock, <errno> is set to <EBUSY>.
01073    */
01074   int tryacquire (void);
01075 
01076   /// Release lock and unblock a thread at head of queue.
01077   int release (void);
01078 
01079   /**
01080    * Acquire mutex ownership.  This calls <acquire> and is only here
01081    * to make the <ACE_Thread_Mutex> interface consistent with the
01082    * other synchronization APIs.
01083    */
01084   int acquire_read (void);
01085 
01086   /**
01087    * Acquire mutex ownership.  This calls <acquire> and is only here
01088    * to make the <ACE_Thread_Mutex> interface consistent with the
01089    * other synchronization APIs.
01090    */
01091   int acquire_write (void);
01092 
01093   /**
01094    * Conditionally acquire mutex (i.e., won't block).  This calls
01095    * <tryacquire> and is only here to make the <ACE_Thread_Mutex>
01096    * interface consistent with the other synchronization APIs.
01097    * Returns -1 on failure.  If we "failed" because someone else
01098    * already had the lock, <errno> is set to <EBUSY>.
01099    */
01100   int tryacquire_read (void);
01101 
01102   /**
01103    * Conditionally acquire mutex (i.e., won't block).  This calls
01104    * <tryacquire> and is only here to make the <ACE_Thread_Mutex>
01105    * interface consistent with the other synchronization APIs.
01106    * Returns -1 on failure.  If we "failed" because someone else
01107    * already had the lock, <errno> is set to <EBUSY>.
01108    */
01109   int tryacquire_write (void);
01110 
01111   /**
01112    * This is only here to make the <ACE_Thread_Mutex>
01113    * interface consistent with the other synchronization APIs.
01114    * Assumes the caller has already acquired the mutex using one of
01115    * the above calls, and returns 0 (success) always.
01116    */
01117   int tryacquire_write_upgrade (void);
01118 
01119   /// Return the underlying mutex.
01120   const ACE_thread_mutex_t &lock (void) const;
01121 
01122   /// Dump the state of an object.
01123   void dump (void) const;
01124 
01125   /// Declare the dynamic allocation hooks.
01126   ACE_ALLOC_HOOK_DECLARE;
01127 
01128   // protected:
01129   /// Mutex type that supports single-process locking efficiently.
01130   ACE_thread_mutex_t lock_;
01131 
01132   /// Keeps track of whether <remove> has been called yet to avoid
01133   /// multiple <remove> calls, e.g., explicitly and implicitly in the
01134   /// destructor.  This flag isn't protected by a lock, so make sure
01135   /// that you don't have multiple threads simultaneously calling
01136   /// <remove> on the same object, which is a bad idea anyway...
01137   int removed_;
01138 
01139 private:
01140   // = Prevent assignment and initialization.
01141   void operator= (const ACE_Thread_Mutex &);
01142   ACE_Thread_Mutex (const ACE_Thread_Mutex &);
01143 };
01144 
01145 #if defined (ACE_USES_OBSOLETE_GUARD_CLASSES)
01146 /**
01147  * @class ACE_Thread_Mutex_Guard
01148  *
01149  * @brief This data structure is meant to be used within a method or
01150  * function...  It performs automatic aquisition and release of
01151  * an <ACE_Thread_Mutex>.
01152  *
01153  * This class is obsolete and should be replaced by
01154  * ACE_Guard<ACE_Thread_Mutex>.
01155  */
01156 class ACE_Export ACE_Thread_Mutex_Guard
01157 {
01158 public:
01159   /// Implicitly and automatically acquire the lock.
01160   ACE_Thread_Mutex_Guard (ACE_Thread_Mutex &m, int block = 1);
01161 
01162   /// Implicitly release the lock.
01163   ~ACE_Thread_Mutex_Guard (void);
01164 
01165   /// 1 if locked, 0 if couldn't acquire the lock (errno will contain
01166   /// the reason for this).
01167   int locked (void);
01168 
01169   /**
01170    * Explicitly release the lock.  Note that only one thread should
01171    * call this method since it doesn't protect against race
01172    * conditions.
01173    */
01174   int remove (void);
01175 
01176   /// Explicitly acquire the lock.
01177   int acquire (void);
01178 
01179   /**
01180    * Conditionally acquire the lock (i.e., won't block).  Returns -1
01181    * on failure.  If we "failed" because someone else already had the
01182    * lock, <errno> is set to <EBUSY>.
01183    */
01184   int tryacquire (void);
01185 
01186   /// Explicitly release the lock.
01187   int release (void);
01188 
01189   /// Dump the state of an object.
01190   void dump (void) const;
01191 
01192   /// Declare the dynamic allocation hooks.
01193   ACE_ALLOC_HOOK_DECLARE;
01194 
01195 protected:
01196   /// Reference to the mutex.
01197   ACE_Thread_Mutex &lock_;
01198 
01199   /// Keeps track of whether we acquired the lock or failed.
01200   int owner_;
01201 
01202 private:
01203   // = Prevent assignment and initialization.
01204   void operator= (const ACE_Thread_Mutex_Guard &);
01205   ACE_Thread_Mutex_Guard (const ACE_Thread_Mutex_Guard &);
01206 };
01207 #endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */
01208 
01209 class ACE_Export ACE_Condition_Attributes
01210 {
01211 public:
01212   /// Constructor
01213   ACE_Condition_Attributes (int type = ACE_DEFAULT_SYNCH_TYPE);
01214 
01215   /// Destructor
01216   ~ACE_Condition_Attributes (void);
01217 
01218 private:
01219   friend class ACE_Condition_Thread_Mutex;
01220 
01221   /// The attributes
01222   ACE_condattr_t attributes_;
01223 
01224 private:
01225   // = Prevent assignment and initialization.
01226   void operator= (const ACE_Condition_Attributes &);
01227   ACE_Condition_Attributes (const ACE_Condition_Attributes &);
01228 };
01229 
01230 /**
01231  * @class ACE_Condition_Thread_Mutex
01232  *
01233  * @brief ACE_Condition variable wrapper written using ACE_Mutexes This
01234  * allows threads to block until shared data changes state.
01235  * A condition variable enables threads to atomically block and
01236  * test the condition under the protection of a mutual exclu-
01237  * sion lock (mutex) until the condition is satisfied.  That is,
01238  * the mutex must have been held by the thread before calling
01239  * wait or signal on the condition.  If the condition is false,
01240  * a thread blocks on a condition variable and atomically
01241  * releases the mutex that is waiting for the condition to
01242  * change.  If another thread changes the condition, it may wake
01243  * up waiting threads by signaling the associated condition
01244  * variable.  The waiting threads, upon awakening, reacquire the
01245  * mutex and re-evaluate the condition.
01246  *
01247  * This should be an instantiation of ACE_Condition but problems
01248  * with compilers precludes this...
01249  */
01250 class ACE_Export ACE_Condition_Thread_Mutex
01251 {
01252 public:
01253   /// Initialize the condition variable.
01254   ACE_Condition_Thread_Mutex (const ACE_Thread_Mutex &m,
01255                               const ACE_TCHAR *name = 0,
01256                               void *arg = 0);
01257 
01258   /// Initialize the condition variable.
01259   ACE_Condition_Thread_Mutex (const ACE_Thread_Mutex &m,
01260                               ACE_Condition_Attributes &attributes,
01261                               const ACE_TCHAR *name = 0,
01262                               void *arg = 0);
01263 
01264   /// Implicitly destroy the condition variable.
01265   ~ACE_Condition_Thread_Mutex (void);
01266 
01267   /**
01268    * Explicitly destroy the condition variable.  Note that only one
01269    * thread should call this method since it doesn't protect against
01270    * race conditions.
01271    */
01272   int remove (void);
01273 
01274   /**
01275    * Block on condition, or until absolute time-of-day has passed.  If
01276    * abstime == 0 use "blocking" <wait> semantics.  Else, if <abstime>
01277    * != 0 and the call times out before the condition is signaled
01278    * <wait> returns -1 and sets errno to ETIME.
01279    */
01280   int wait (const ACE_Time_Value *abstime);
01281 
01282   /// Block on condition.
01283   int wait (void);
01284 
01285   /**
01286    * Block on condition or until absolute time-of-day has passed.  If
01287    * abstime == 0 use "blocking" wait() semantics on the <mutex>
01288    * passed as a parameter (this is useful if you need to store the
01289    * <Condition> in shared memory).  Else, if <abstime> != 0 and the
01290    * call times out before the condition is signaled <wait> returns -1
01291    * and sets errno to ETIME.
01292    */
01293   int wait (ACE_Thread_Mutex &mutex, const ACE_Time_Value *abstime = 0);
01294 
01295   /// Signal one waiting thread.
01296   int signal (void);
01297 
01298   /// Signal *all* waiting threads.
01299   int broadcast (void);
01300 
01301   /// Returns a reference to the underlying mutex;
01302   ACE_Thread_Mutex &mutex (void);
01303 
01304   /// Dump the state of an object.
01305   void dump (void) const;
01306 
01307   /// Declare the dynamic allocation hooks.
01308   ACE_ALLOC_HOOK_DECLARE;
01309 
01310 protected:
01311   /// Condition variable.
01312   ACE_cond_t cond_;
01313 
01314   /// Reference to mutex lock.
01315   ACE_Thread_Mutex &mutex_;
01316 
01317   /// Keeps track of whether <remove> has been called yet to avoid
01318   /// multiple <remove> calls, e.g., explicitly and implicitly in the
01319   /// destructor.  This flag isn't protected by a lock, so make sure
01320   /// that you don't have multiple threads simultaneously calling
01321   /// <remove> on the same object, which is a bad idea anyway...
01322   int removed_;
01323 
01324 private:
01325   // = Prevent assignment and initialization.
01326   void operator= (const ACE_Condition_Thread_Mutex &);
01327   ACE_Condition_Thread_Mutex (const ACE_Condition_Thread_Mutex &);
01328 };
01329 
01330 /**
01331  * @class ACE_Recursive_Thread_Mutex
01332  *
01333  * @brief Implement a C++ wrapper that allows nested acquisition and
01334  * release of a mutex that occurs in the same thread.
01335  */
01336 class ACE_Export ACE_Recursive_Thread_Mutex
01337 {
01338 public:
01339   /// Initialize a recursive mutex.
01340   ACE_Recursive_Thread_Mutex (const ACE_TCHAR *name = 0,
01341                               ACE_mutexattr_t *arg = 0);
01342 
01343   /// Implicitly release a recursive mutex.
01344   ~ACE_Recursive_Thread_Mutex (void);
01345 
01346   /**
01347    * Implicitly release a recursive mutex.  Note that only one thread
01348    * should call this method since it doesn't protect against race
01349    * conditions.
01350    */
01351   int remove (void);
01352 
01353   /**
01354    * Acquire a recursive mutex (will increment the nesting level and
01355    * not deadmutex if the owner of the mutex calls this method more
01356    * than once).
01357    */
01358   int acquire (void);
01359 
01360   /**
01361    * Conditionally acquire a recursive mutex (i.e., won't block).
01362    * Returns -1 on failure.  If we "failed" because someone else
01363    * already had the lock, <errno> is set to <EBUSY>.
01364    */
01365   int tryacquire (void);
01366 
01367   /**
01368    * Acquire mutex ownership.  This calls <acquire> and is only
01369    * here to make the <ACE_Recusive_Thread_Mutex> interface consistent
01370    * with the other synchronization APIs.
01371    */
01372   int acquire_read (void);
01373 
01374   /**
01375    * Acquire mutex ownership.  This calls <acquire> and is only
01376    * here to make the <ACE_Recusive_Thread_Mutex> interface consistent
01377    * with the other synchronization APIs.
01378    */
01379   int acquire_write (void);
01380 
01381   /**
01382    * Conditionally acquire mutex (i.e., won't block).  This calls
01383    * <tryacquire> and is only here to make the
01384    * <ACE_Recusive_Thread_Mutex> interface consistent with the other
01385    * synchronization APIs.  Returns -1 on failure.  If we "failed"
01386    * because someone else already had the lock, <errno> is set to
01387    * <EBUSY>.
01388    */
01389   int tryacquire_read (void);
01390 
01391   /**
01392    * Conditionally acquire mutex (i.e., won't block).  This calls
01393    * <tryacquire> and is only here to make the
01394    * <ACE_Recusive_Thread_Mutex> interface consistent with the other
01395    * synchronization APIs.  Returns -1 on failure.  If we "failed"
01396    * because someone else already had the lock, <errno> is set to
01397    * <EBUSY>.
01398    */
01399   int tryacquire_write (void);
01400 
01401   /**
01402    * This is only here to make the <ACE_Recursive_Thread_Mutex>
01403    * interface consistent with the other synchronization APIs.
01404    * Assumes the caller has already acquired the mutex using one of
01405    * the above calls, and returns 0 (success) always.
01406    */
01407   int tryacquire_write_upgrade (void);
01408 
01409   /**
01410    * Releases a recursive mutex (will not release mutex until all the
01411    * nesting level drops to 0, which means the mutex is no longer
01412    * held).
01413    */
01414   int release (void);
01415 
01416   /// Return the id of the thread that currently owns the mutex.
01417   ACE_thread_t get_thread_id (void);
01418 
01419   /**
01420    * Return the nesting level of the recursion.  When a thread has
01421    * acquired the mutex for the first time, the nesting level == 1.
01422    * The nesting level is incremented every time the thread acquires
01423    * the mutex recursively.
01424    */
01425   int get_nesting_level (void);
01426 
01427   /// Returns a reference to the recursive mutex;
01428   ACE_recursive_thread_mutex_t &mutex (void);
01429 
01430   /// Returns a reference to the recursive mutex's internal mutex;
01431   ACE_thread_mutex_t &get_nesting_mutex (void);
01432 
01433   /// Dump the state of an object.
01434   void dump (void) const;
01435 
01436   /// Declare the dynamic allocation hooks.
01437   ACE_ALLOC_HOOK_DECLARE;
01438 
01439 protected:
01440   // = This method should *not* be public (they hold no locks...)
01441   void set_thread_id (ACE_thread_t t);
01442 
01443   /// Recursive mutex.
01444   ACE_recursive_thread_mutex_t recursive_mutex_;
01445 
01446   /// Keeps track of whether <remove> has been called yet to avoid
01447   /// multiple <remove> calls, e.g., explicitly and implicitly in the
01448   /// destructor.  This flag isn't protected by a lock, so make sure
01449   /// that you don't have multiple threads simultaneously calling
01450   /// <remove> on the same object, which is a bad idea anyway...
01451   int removed_;
01452 
01453 private:
01454   // = Prevent assignment and initialization.
01455   void operator= (const ACE_Recursive_Thread_Mutex &);
01456   ACE_Recursive_Thread_Mutex (const ACE_Recursive_Thread_Mutex &);
01457 };
01458 
01459 /**
01460  * @class ACE_RW_Thread_Mutex
01461  *
01462  * @brief Wrapper for readers/writer locks that exist within a process.
01463  */
01464 class ACE_Export ACE_RW_Thread_Mutex : public ACE_RW_Mutex
01465 {
01466 public:
01467   ACE_RW_Thread_Mutex (const ACE_TCHAR *name = 0,
01468                        void *arg = 0);
01469 
01470   /// Default dtor.
01471   ~ACE_RW_Thread_Mutex (void);
01472 
01473   /**
01474    * Conditionally upgrade a read lock to a write lock.  This only
01475    * works if there are no other readers present, in which case the
01476    * method returns 0.  Otherwise, the method returns -1 and sets
01477    * <errno> to <EBUSY>.  Note that the caller of this method *must*
01478    * already possess this lock as a read lock (but this condition is
01479    * not checked by the current implementation).
01480    */
01481   int tryacquire_write_upgrade (void);
01482 
01483   /// Dump the state of an object.
01484   void dump (void) const;
01485 
01486   /// Declare the dynamic allocation hooks.
01487   ACE_ALLOC_HOOK_DECLARE;
01488 };
01489 
01490 /**
01491  * @class ACE_Thread_Semaphore
01492  *
01493  * @brief Wrapper for Dijkstra style general semaphores that work
01494  * only within one process.
01495  */
01496 class ACE_Export ACE_Thread_Semaphore : public ACE_Semaphore
01497 {
01498 public:
01499   /// Initialize the semaphore, with an initial value of <count>,
01500   /// maximum value of <max>, and unlocked by default.
01501   ACE_Thread_Semaphore (u_int count = 1, // By default make this unlocked.
01502                         const ACE_TCHAR *name = 0,
01503                         void * = 0,
01504                         int max = 0x7FFFFFFF);
01505 
01506   /// Default dtor.
01507   ~ACE_Thread_Semaphore (void);
01508 
01509   /// Dump the state of an object.
01510   void dump (void) const;
01511 
01512   /// Declare the dynamic allocation hooks.
01513   ACE_ALLOC_HOOK_DECLARE;
01514 };
01515 
01516 struct ACE_Export ACE_Sub_Barrier
01517 {
01518   // = Initialization.
01519   ACE_Sub_Barrier (u_int count,
01520                    ACE_Thread_Mutex &lock,
01521                    const ACE_TCHAR *name = 0,
01522                    void *arg = 0);
01523 
01524   ~ACE_Sub_Barrier (void);
01525 
01526   /// True if this generation of the barrier is done.
01527   ACE_Condition_Thread_Mutex barrier_finished_;
01528 
01529   /// Number of threads that are still running.
01530   int running_threads_;
01531 
01532   /// Dump the state of an object.
01533   void dump (void) const;
01534 
01535   /// Declare the dynamic allocation hooks.
01536   ACE_ALLOC_HOOK_DECLARE;
01537 };
01538 
01539 /**
01540  * @class ACE_Barrier
01541  *
01542  * @brief Implements "barrier synchronization".
01543  *
01544  * This class allows <count> number of threads to synchronize
01545  * their completion of (one round of) a task, which is known as
01546  * "barrier synchronization".   After all the threads call <wait()>
01547  * on the barrier they are all atomically released and can begin a new
01548  * round.
01549  * 
01550  * This implementation uses a "sub-barrier generation numbering"
01551  * scheme to avoid overhead and to ensure that all threads wait to
01552  * leave the barrier correct.  This code is based on an article from
01553  * SunOpsis Vol. 4, No. 1 by Richard Marejka
01554  * (Richard.Marejka@canada.sun.com). 
01555  */
01556 class ACE_Export ACE_Barrier
01557 {
01558 public:
01559   /// Initialize the barrier to synchronize <count> threads.
01560   ACE_Barrier (u_int count,
01561                const ACE_TCHAR *name = 0,
01562                void *arg = 0);
01563 
01564   /// Default dtor.
01565   ~ACE_Barrier (void);
01566 
01567   /// Block the caller until all <count> threads have called <wait> and
01568   /// then allow all the caller threads to continue in parallel.
01569   int wait (void);
01570 
01571   /// Dump the state of an object.
01572   void dump (void) const;
01573 
01574   /// Declare the dynamic allocation hooks.
01575   ACE_ALLOC_HOOK_DECLARE;
01576 
01577 protected:
01578   /// Serialize access to the barrier state.
01579   ACE_Thread_Mutex lock_;
01580 
01581   /// Either 0 or 1, depending on whether we are the first generation
01582   /// of waiters or the next generation of waiters.
01583   int current_generation_;
01584 
01585   /// Total number of threads that can be waiting at any one time.
01586   int count_;
01587 
01588   /**
01589    * We keep two <sub_barriers>, one for the first "generation" of
01590    * waiters, and one for the next "generation" of waiters.  This
01591    * efficiently solves the problem of what to do if all the first
01592    * generation waiters don't leave the barrier before one of the
01593    * threads calls wait() again (i.e., starts up the next generation
01594    * barrier).
01595    */
01596   ACE_Sub_Barrier sub_barrier_1_;
01597   ACE_Sub_Barrier sub_barrier_2_;
01598   ACE_Sub_Barrier *sub_barrier_[2];
01599 
01600 private:
01601   // = Prevent assignment and initialization.
01602   void operator= (const ACE_Barrier &);
01603   ACE_Barrier (const ACE_Barrier &);
01604 };
01605 
01606 #if 0
01607 // The following two classes are commented out since there doesn't
01608 // appear to be a portable and robust means of implementing this
01609 // functionality across platforms.  If you know of a portable and
01610 // robust way to implement this functionality please let us know.
01611 
01612 /**
01613  * @class ACE_Process_Condition
01614  *
01615  * @brief ACE_Condition variable wrapper that works across processes.
01616  */
01617 class ACE_Export ACE_Process_Condition
01618 {
01619 public:
01620   ACE_Process_Condition (MUTEX &m, const ACE_TCHAR *name = 0, void *arg = 0);
01621 
01622   /// Dump the state of an object.
01623   void dump (void) const;
01624 
01625   // ACE_ALLOC_HOOK_DECLARE;
01626   // Declare the dynamic allocation hooks.
01627 };
01628 #endif /* 0 */
01629 
01630 #if 0
01631 /**
01632  * @class ACE_Process_Barrier
01633  *
01634  * @brief Implements "barrier synchronization" using ACE_Process_Mutexes!
01635  *
01636  * This class is just a simple wrapper for ACE_Barrier that
01637  * selects the USYNC_PROCESS variant for the locks.
01638  */
01639 class ACE_Export ACE_Process_Barrier : public ACE_Barrier
01640 {
01641 public:
01642   /// Create a Process_Barrier, passing in the optional <name>.
01643   ACE_Process_Barrier (u_int count, const ACE_TCHAR *name = 0);
01644 
01645   /// Dump the state of an object.
01646   void dump (void) const;
01647 
01648   /// Declare the dynamic allocation hooks.
01649   ACE_ALLOC_HOOK_DECLARE;
01650 };
01651 #endif /* 0 */
01652 
01653 /**
01654  * @class ACE_Thread_Barrier
01655  *
01656  * @brief Implements "barrier synchronization" using ACE_Thread_Mutexes!
01657  *
01658  * This class is just a simple wrapper for ACE_Barrier that
01659  * selects the USYNC_THREAD variant for the locks.
01660  */
01661 class ACE_Export ACE_Thread_Barrier : public ACE_Barrier
01662 {
01663 public:
01664   /// Create a Thread_Barrier, passing in the optional <name>.
01665   ACE_Thread_Barrier (u_int count, const ACE_TCHAR *name = 0);
01666 
01667   /// Default dtor.
01668   ~ACE_Thread_Barrier (void);
01669 
01670   /// Dump the state of an object.
01671   void dump (void) const;
01672 
01673   /// Declare the dynamic allocation hooks.
01674   ACE_ALLOC_HOOK_DECLARE;
01675 };
01676 #endif /* ACE_HAS_THREADS */
01677 
01678 #if defined (__ACE_INLINE__)
01679 #include "ace/Synch.i"
01680 #endif /* __ACE_INLINE__ */
01681 
01682 // Include the templates here.
01683 #include "ace/Synch_T.h"
01684 
01685 template <class ACE_LOCK>
01686 class ACE_Guard;
01687 
01688 ACE_TEMPLATE_SPECIALIZATION
01689 /**
01690  * @class ACE_Guard<ACE_Null_Mutex>
01691  *
01692  * @brief Template specialization of <ACE_Guard> for the
01693  * <ACE_Null_Mutex>.
01694  *
01695  * This specialization is useful since it helps to speedup
01696  * performance of the "Null_Mutex" considerably.
01697  */
01698 class ACE_Export ACE_Guard<ACE_Null_Mutex>
01699 {
01700 public:
01701   // = Initialization and termination methods.
01702   ACE_Guard (ACE_Null_Mutex &) {}
01703   ACE_Guard (ACE_Null_Mutex &, int) {}
01704 #if defined (ACE_WIN32)
01705   ~ACE_Guard (void) {}
01706 #endif /* ACE_WIN32 */
01707 
01708   int acquire (void) { return 0; }
01709   int tryacquire (void) { return 0; }
01710   int release (void) { return 0; }
01711   int locked (void) { return 1; }
01712   int remove (void) { return 0; }
01713   void dump (void) const {}
01714 
01715 private:
01716   // = Prevent assignment and initialization.
01717   ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Guard<ACE_Null_Mutex> &))
01718   ACE_UNIMPLEMENTED_FUNC (ACE_Guard (const ACE_Guard<ACE_Null_Mutex> &))
01719 };
01720 
01721 template <class ACE_LOCK>
01722 class ACE_Write_Guard;
01723 
01724 ACE_TEMPLATE_SPECIALIZATION
01725 /**
01726  * @class ACE_Write_Guard<ACE_Null_Mutex>
01727  *
01728  */
01729 class ACE_Export ACE_Write_Guard<ACE_Null_Mutex> : public ACE_Guard<ACE_Null_Mutex>
01730 {
01731 public:
01732   ACE_Write_Guard (ACE_Null_Mutex &m)
01733     : ACE_Guard<ACE_Null_Mutex> (m) {}
01734   ACE_Write_Guard (ACE_Null_Mutex &m, int blocked)
01735     : ACE_Guard<ACE_Null_Mutex> (m, blocked) {}
01736 
01737   int acquire_write (void) { return 0; }
01738   int acquire (void) { return 0; }
01739   int tryacquire_write (void) { return 0; }
01740   int tryacquire (void) { return 0; }
01741   void dump (void) const {}
01742 };
01743 
01744 template <class ACE_LOCK>
01745 class ACE_Read_Guard;
01746 
01747 ACE_TEMPLATE_SPECIALIZATION
01748 /**
01749  * @class ACE_Read_Guard<ACE_Null_Mutex>
01750  *
01751  */
01752 class ACE_Export ACE_Read_Guard<ACE_Null_Mutex> : public ACE_Guard<ACE_Null_Mutex>
01753 {
01754 public:
01755   ACE_Read_Guard (ACE_Null_Mutex &m)
01756     : ACE_Guard<ACE_Null_Mutex> (m) {}
01757   ACE_Read_Guard (ACE_Null_Mutex &m, int blocked)
01758     : ACE_Guard<ACE_Null_Mutex> (m, blocked) {}
01759 
01760   int acquire_read (void) { return 0; }
01761   int acquire (void) { return 0; }
01762   int tryacquire_read (void) { return 0; }
01763   int tryacquire (void) { return 0; }
01764   void dump (void) const {}
01765 };
01766 
01767 #if defined (ACE_HAS_THREADS)
01768 
01769 template <class ACE_LOCK>
01770 class ACE_Condition;
01771 
01772 ACE_TEMPLATE_SPECIALIZATION
01773 /**
01774  * @class ACE_Condition<ACE_Recursive_Thread_Mutex>
01775  * 
01776  * @brief ACE_Condition template specialization written using
01777  *  @a ACE_Recursive_Thread_Mutex.  This allows threads to block until
01778  *  shared data changes state using recursive mutexes. 
01779  */
01780 class ACE_Export ACE_Condition<ACE_Recursive_Thread_Mutex>
01781 {
01782 public:
01783   /// Initialize the condition variable with a recursive mutex.
01784   ACE_Condition (ACE_Recursive_Thread_Mutex &m);
01785 
01786   /// Implicitly destroy the condition variable.
01787   ~ACE_Condition (void);
01788 
01789   /**
01790    * Explicitly destroy the condition variable.  Note that only one
01791    * thread should call this method since it doesn't protect against
01792    * race conditions.
01793    */
01794   int remove (void);
01795 
01796   /**
01797    * Block on condition, or until absolute time-of-day has passed.  If
01798    * abstime == 0 use "blocking" <wait> semantics.  Else, if <abstime>
01799    * != 0 and the call times out before the condition is signaled
01800    * <wait> returns -1 and sets errno to ETIME.
01801    */
01802   int wait (const ACE_Time_Value *abstime = 0);
01803 
01804   /**
01805    * Block on condition or until absolute time-of-day has passed.  If
01806    * abstime == 0 use "blocking" wait() semantics on the recursive @a mutex
01807    * passed as a parameter (this is useful if you need to store the
01808    * <Condition> in shared memory).  Else, if <abstime> != 0 and the
01809    * call times out before the condition is signaled <wait> returns -1
01810    * and sets errno to ETIME.
01811    */
01812   int wait (ACE_Recursive_Thread_Mutex &mutex,
01813             const ACE_Time_Value *abstime = 0); 
01814 
01815   /// Signal one waiting thread.
01816   int signal (void);
01817 
01818   /// Signal *all* waiting threads.
01819   int broadcast (void);
01820 
01821   /// Returns a reference to the underlying mutex;
01822   ACE_Recursive_Thread_Mutex &mutex (void);
01823 
01824   /// Dump the state of an object.
01825   void dump (void) const;
01826 
01827 private:
01828   /// A normal (i.e., non-recursive) condition variable.
01829   ACE_cond_t cond_;
01830 
01831   /// Reference to the recursive mutex.
01832   ACE_Recursive_Thread_Mutex &mutex_;
01833 
01834   // = Prevent assignment and initialization.
01835   ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Condition<ACE_Recursive_Thread_Mutex> &))
01836   ACE_UNIMPLEMENTED_FUNC (ACE_Condition (const ACE_Condition<ACE_Recursive_Thread_Mutex> &))
01837 };
01838 
01839 class ACE_Export ACE_Condition_Recursive_Thread_Mutex 
01840   : public ACE_Condition<ACE_Recursive_Thread_Mutex>
01841 {        
01842 public:
01843   /// Initialize the condition variable with a recursive mutex.
01844   ACE_Condition_Recursive_Thread_Mutex (ACE_Recursive_Thread_Mutex &m):
01845     ACE_Condition<ACE_Recursive_Thread_Mutex> (m) {}
01846 };
01847 #endif /* ACE_HAS_THREADS */
01848 
01849 #if defined (ACE_LEGACY_MODE)
01850 # include "ace/File_Lock.h"
01851 # include "ace/Process_Semaphore.h"
01852 # include "ace/Process_Mutex.h"
01853 # include "ace/RW_Process_Mutex.h"
01854 # include "ace/Test_and_Set.h"
01855 #endif  /* ACE_LEGACY_MODE */
01856 
01857 #include "ace/post.h"
01858 #endif /* ACE_SYNCH_H */

Generated on Mon Jun 16 11:21:39 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002