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

Synch_T.h

Go to the documentation of this file.
00001 /* -*- C++ -*- */
00002 
00003 //=============================================================================
00004 /**
00005  *  @file    Synch_T.h
00006  *
00007  *  $Id: Synch_T.h,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $
00008  *
00009  *  @author Douglas C. Schmidt <schmidt@uci.edu>
00010  */
00011 //=============================================================================
00012 
00013 #ifndef ACE_SYNCH_T_H
00014 #define ACE_SYNCH_T_H
00015 #include "ace/pre.h"
00016 #include "ace/Synch.h"
00017 
00018 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00019 # pragma once
00020 #endif /* ACE_LACKS_PRAGMA_ONCE */
00021 
00022 // Forward decl
00023 class ACE_Time_Value;
00024 
00025 /**
00026  * @class ACE_Lock_Adapter
00027  *
00028  * @brief This is an adapter that allows applications to transparently
00029  * combine the <ACE_Lock> abstract base class (which contains
00030  * pure virtual methods) with any of the other concrete ACE
00031  * synchronization classes (e.g., <ACE_Mutex>, <ACE_Semaphore>,
00032  * <ACE_RW_Mutex>, etc.).
00033  *
00034  * This class uses a form of the Adapter pattern.
00035  */
00036 template <class ACE_LOCKING_MECHANISM>
00037 class ACE_Lock_Adapter : public ACE_Lock
00038 {
00039 public:
00040   typedef ACE_LOCKING_MECHANISM ACE_LOCK;
00041 
00042   // = Initialization/Finalization methods.
00043 
00044   /// Constructor. All locking requests will be forwarded to <lock>.
00045   ACE_Lock_Adapter (ACE_LOCKING_MECHANISM &lock);
00046 
00047   /// Constructor. Since no lock is provided by the user, one will be
00048   /// created internally.
00049   ACE_Lock_Adapter (void);
00050 
00051   /// Destructor. If <lock_> was not passed in by the user, it will be
00052   /// deleted.
00053   virtual ~ACE_Lock_Adapter (void);
00054 
00055   // = Lock accessors.
00056   /// Block the thread until the lock is acquired.
00057   virtual int acquire (void);
00058 
00059   /// Conditionally acquire the lock (i.e., won't block).
00060   virtual int tryacquire (void);
00061 
00062   /// Release the lock.
00063   virtual int release (void);
00064 
00065   /**
00066    * Block until the thread acquires a read lock.  If the locking
00067    * mechanism doesn't support read locks then this just calls
00068    * <acquire>.
00069    */
00070   virtual int acquire_read (void);
00071 
00072   /**
00073    * Block until the thread acquires a write lock.  If the locking
00074    * mechanism doesn't support read locks then this just calls
00075    * <acquire>.
00076    */
00077   virtual int acquire_write (void);
00078 
00079   /// Conditionally acquire a read lock.  If the locking mechanism
00080   /// doesn't support read locks then this just calls <acquire>.
00081   virtual int tryacquire_read (void);
00082 
00083   /// Conditionally acquire a write lock.  If the locking mechanism
00084   /// doesn't support read locks then this just calls <acquire>.
00085   virtual int tryacquire_write (void);
00086 
00087   /**
00088    * Conditionally try to upgrade a lock held for read to a write lock.
00089    * If the locking mechanism doesn't support read locks then this just
00090    * calls <acquire>. Returns 0 on success, -1 on failure.
00091    */
00092   virtual int tryacquire_write_upgrade (void);
00093 
00094   /// Explicitly destroy the lock.
00095   virtual int remove (void);
00096 
00097 private:
00098   /// The concrete locking mechanism that all the methods delegate to.
00099   ACE_LOCKING_MECHANISM *lock_;
00100 
00101   /// This flag keep track of whether we are responsible for deleting
00102   /// the lock
00103   int delete_lock_;
00104 };
00105 
00106 /**
00107  * @class ACE_Acquire_Method
00108  *
00109  * @brief An enum class.
00110  *
00111  * These enums should have been inside the reverse lock class, but
00112  * some lame compilers cannot handle enums inside template classes.
00113  *
00114  * The METHOD_TYPE is used to indicate which acquire() method will be
00115  * called on the real lock when the release() method is called on the
00116  * reverse lock. REGULAR indicated the acquire() method, READ
00117  * indicates the acquire_read() method, and WRITE indicates the
00118  * acquire_write() method.  Note that the try_*() methods are not
00119  * represented here because we have to make sure that the release()
00120  * method on the reverse lock acquires a lock on the real lock.
00121  **/
00122 class ACE_Acquire_Method
00123 {
00124 public:
00125   enum METHOD_TYPE
00126   {
00127     ACE_REGULAR,
00128     ACE_READ,
00129     ACE_WRITE
00130   };
00131 };
00132 
00133 /**
00134  * @class ACE_Reverse_Lock
00135  *
00136  * @brief A reverse (or anti) lock.
00137  *
00138  * This is an interesting adapter class that changes a lock into
00139  * a reverse lock, i.e., <acquire> on this class calls <release>
00140  * on the lock, and <release> on this class calls <acquire> on
00141  * the lock.
00142  * One motivation for this class is when we temporarily want to
00143  * release a lock (which we have already acquired) but then
00144  * reacquire it soon after.  An alternative design would be to
00145  * add a Anti_Guard or Reverse_Guard class which would <release>
00146  * on construction and <acquire> destruction.  However, there
00147  * are *many* varieties of the Guard class and this design
00148  * choice would lead to at least 6 new classes.  One new
00149  * ACE_Reverse_Lock class seemed more reasonable.
00150  */
00151 template <class ACE_LOCKING_MECHANISM>
00152 class ACE_Reverse_Lock : public ACE_Lock
00153 {
00154 public:
00155 
00156   typedef ACE_LOCKING_MECHANISM ACE_LOCK;
00157 
00158   // = Initialization/Finalization methods.
00159 
00160   /// Constructor. All locking requests will be forwarded to <lock>.
00161   ACE_Reverse_Lock (ACE_LOCKING_MECHANISM &lock,
00162                     ACE_Acquire_Method::METHOD_TYPE acquire_method = ACE_Acquire_Method::ACE_REGULAR);
00163 
00164   /// Destructor. If <lock_> was not passed in by the user, it will be
00165   /// deleted.
00166   virtual ~ACE_Reverse_Lock (void);
00167 
00168   // = Lock accessors.
00169   /// Release the lock.
00170   virtual int acquire (void);
00171 
00172   /// Release the lock.
00173   virtual int tryacquire (void);
00174 
00175   /// Acquire the lock.
00176   virtual int release (void);
00177 
00178   /// Release the lock.
00179   virtual int acquire_read (void);
00180 
00181   /// Release the lock.
00182   virtual int acquire_write (void);
00183 
00184   /// Release the lock.
00185   virtual int tryacquire_read (void);
00186 
00187   /// Release the lock.
00188   virtual int tryacquire_write (void);
00189 
00190   /// Release the lock.
00191   virtual int tryacquire_write_upgrade (void);
00192 
00193   /// Explicitly destroy the lock.
00194   virtual int remove (void);
00195 
00196 private:
00197   /// The concrete locking mechanism that all the methods delegate to.
00198   ACE_LOCKING_MECHANISM &lock_;
00199 
00200   /// This indicates what kind of acquire method will be called.
00201   ACE_Acquire_Method::METHOD_TYPE acquire_method_;
00202 };
00203 
00204 /**
00205  * @class ACE_TSS
00206  *
00207  * @brief Allows objects that are "physically" in thread specific
00208  * storage (i.e., private to a thread) to be accessed as though
00209  * they were "logically" global to a program.
00210  *
00211  * This class is a wrapper around the OS thread library
00212  * thread-specific functions.  It uses the <C++ operator->> to
00213  * shield applications from the details of accessing
00214  * thread-specific storage.
00215  *
00216  * NOTE: For maximal portability, <TYPE> cannot be a built-in type,
00217  * but instead should be a user-defined class (some compilers will
00218  * allow a built-in type, others won't).  See template class
00219  * ACE_TSS_Type_Adapter, below, for adapting built-in types to work
00220  * with ACE_TSS.
00221  */
00222 template <class TYPE>
00223 class ACE_TSS
00224 {
00225 public:
00226   // = Initialization and termination methods.
00227 
00228   /**
00229    * If caller has passed us a non-NULL ts_obj *, then we'll just use
00230    * this to initialize the thread-specific value (but only for the
00231    * calling thread).  Thus, subsequent calls to <operator->> in this
00232    * thread will return this value.  This is useful since it enables
00233    * us to assign objects to thread-specific data that have
00234    * arbitrarily complex constructors.
00235    */
00236   ACE_TSS (TYPE *ts_obj = 0);
00237 
00238   /// Deregister with thread-key administration.
00239   virtual ~ACE_TSS (void);
00240 
00241   // = Accessors.
00242 
00243   /**
00244    * Get the thread-specific object for the key associated with this
00245    * object.  Returns 0 if the data has never been initialized,
00246    * otherwise returns a pointer to the data.
00247    */
00248   TYPE *ts_object (void) const;
00249 
00250   /// Set the thread-specific object for the key associated with this
00251   /// object.
00252   TYPE *ts_object (TYPE *);
00253 
00254   /// Use a "smart pointer" to get the thread-specific object
00255   /// associated with the <key_>.
00256   TYPE *operator-> () const;
00257 
00258   /// Return or create and return the calling threads TYPE object.
00259   operator TYPE *(void) const;
00260 
00261   /// Hook for construction parameters.
00262   virtual TYPE *make_TSS_TYPE (void) const;
00263 
00264   // = Utility methods.
00265 
00266   /// Dump the state of an object.
00267   void dump (void) const;
00268 
00269   // ACE_ALLOC_HOOK_DECLARE;
00270   // Declare the dynamic allocation hooks.
00271 
00272 protected:
00273   /// Actually implements the code that retrieves the object from
00274   /// thread-specific storage.
00275   TYPE *ts_get (void) const;
00276 
00277   /// Factors out common code for initializing TSS.  This must NOT be
00278   /// called with the lock held...
00279   int ts_init (void) const;
00280 
00281 #if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)))
00282   /// This implementation only works for non-threading systems...
00283   TYPE *type_;
00284 #else
00285   /// Avoid race conditions during initialization.
00286   ACE_Thread_Mutex keylock_;
00287 
00288   /// "First time in" flag.
00289   int once_;
00290 
00291   /// Key for the thread-specific error data.
00292   ACE_thread_key_t key_;
00293 
00294   /// "Destructor" that deletes internal TYPE * when thread exits.
00295   static void cleanup (void *ptr);
00296 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
00297   // = Disallow copying...
00298   ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS<TYPE> &))
00299   ACE_UNIMPLEMENTED_FUNC (ACE_TSS (const ACE_TSS<TYPE> &))
00300 };
00301 
00302 /**
00303  * @class ACE_TSS_Type_Adapter
00304  *
00305  * @brief Adapter that allows built-in types to be used with ACE_TSS.
00306  *
00307  * Wraps a value of a built-in type, providing conversions to
00308  * and from the type.  Example use with ACE_TSS:
00309  * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
00310  * *i = 37;
00311  * ACE_OS::fprintf (stderr, "%d\n", *i);
00312  * Unfortunately, though, some compilers have trouble with the
00313  * implicit type conversions.  This seems to work better:
00314  * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
00315  * i->operator int & () = 37;
00316  * ACE_OS::fprintf (stderr, "%d\n", i->operator int ());
00317  */
00318 template <class TYPE>
00319 class ACE_TSS_Type_Adapter
00320 {
00321 public:
00322   /// Constructor.  Inlined here so that it should _always_ be inlined.
00323   ACE_TSS_Type_Adapter (const TYPE value = 0): value_ (value) {}
00324 
00325   /// TYPE conversion.  Inlined here so that it should _always_ be
00326   /// inlined.
00327   operator TYPE () const { return value_; };
00328 
00329   /// TYPE & conversion.  Inlined here so that it should _always_ be
00330   /// inlined.
00331   operator TYPE &() { return value_; };
00332 
00333 private:
00334   /// The wrapped value.
00335   TYPE value_;
00336 };
00337 
00338 /**
00339  * @class ACE_Guard
00340  *
00341  * @brief This data structure is meant to be used within a method or
00342  * function...  It performs automatic aquisition and release of
00343  * a parameterized synchronization object <ACE_LOCK>.
00344  *
00345  * The <ACE_LOCK> class given as an actual parameter must provide at
00346  * the very least the <acquire>, <tryacquire>, <release>, and
00347  * <remove> methods.
00348  */
00349 template <class ACE_LOCK>
00350 class ACE_Guard
00351 {
00352 public:
00353 
00354   // = Initialization and termination methods.
00355   ACE_Guard (ACE_LOCK &l);
00356 
00357   /// Implicitly and automatically acquire (or try to acquire) the
00358   /// lock.  If <block> is non-0 then <acquire> the <ACE_LOCK>, else
00359   /// <tryacquire> it.
00360   ACE_Guard (ACE_LOCK &l, int block);
00361 
00362   /// Initialise the guard without implicitly acquiring the lock. The
00363   /// <become_owner> parameter indicates whether the guard should release
00364   /// the lock implicitly on destruction. The <block> parameter is
00365   /// ignored and is used here to disambiguate with the preceding
00366   /// constructor.
00367   ACE_Guard (ACE_LOCK &l, int block, int become_owner);
00368 
00369   /// Implicitly release the lock.
00370   ~ACE_Guard (void);
00371 
00372   // = Lock accessors.
00373 
00374   /// Explicitly acquire the lock.
00375   int acquire (void);
00376 
00377   /// Conditionally acquire the lock (i.e., won't block).
00378   int tryacquire (void);
00379 
00380   /// Explicitly release the lock, but only if it is held!
00381   int release (void);
00382 
00383   /// Relinquish ownership of the lock so that it is not released
00384   /// implicitly in the destructor.
00385   void disown (void);
00386 
00387   // = Utility methods.
00388   /// 1 if locked, 0 if couldn't acquire the lock
00389   /// (errno will contain the reason for this).
00390   int locked (void) const;
00391 
00392   /// Explicitly remove the lock.
00393   int remove (void);
00394 
00395   /// Dump the state of an object.
00396   void dump (void) const;
00397 
00398   // ACE_ALLOC_HOOK_DECLARE;
00399   // Declare the dynamic allocation hooks.
00400 
00401 protected:
00402 
00403   /// Helper, meant for subclass only.
00404   ACE_Guard (ACE_LOCK *lock): lock_ (lock) {}
00405 
00406   /// Pointer to the ACE_LOCK we're guarding.
00407   ACE_LOCK *lock_;
00408 
00409   /// Keeps track of whether we acquired the lock or failed.
00410   int owner_;
00411 
00412 private:
00413   // = Prevent assignment and initialization.
00414   ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Guard<ACE_LOCK> &))
00415   ACE_UNIMPLEMENTED_FUNC (ACE_Guard (const ACE_Guard<ACE_LOCK> &))
00416 };
00417 
00418 /**
00419  * @class ACE_Write_Guard
00420  *
00421  * @brief This class is similar to class <ACE_Guard>, though it
00422  * acquires/releases a write lock automatically (naturally, the
00423  * <ACE_LOCK> it is instantiated with must support the appropriate
00424  * API).
00425  */
00426 template <class ACE_LOCK>
00427 class ACE_Write_Guard : public ACE_Guard<ACE_LOCK>
00428 {
00429 public:
00430   // = Initialization method.
00431 
00432   /// Implicitly and automatically acquire a write lock.
00433   ACE_Write_Guard (ACE_LOCK &m);
00434 
00435   /// Implicitly and automatically acquire (or try to acquire) a write
00436   /// lock.
00437   ACE_Write_Guard (ACE_LOCK &m, int block);
00438 
00439   // = Lock accessors.
00440 
00441   /// Explicitly acquire the write lock.
00442   int acquire_write (void);
00443 
00444   /// Explicitly acquire the write lock.
00445   int acquire (void);
00446 
00447   /// Conditionally acquire the write lock (i.e., won't block).
00448   int tryacquire_write (void);
00449 
00450   /// Conditionally acquire the write lock (i.e., won't block).
00451   int tryacquire (void);
00452 
00453   // = Utility methods.
00454 
00455   /// Dump the state of an object.
00456   void dump (void) const;
00457 
00458   // ACE_ALLOC_HOOK_DECLARE;
00459   // Declare the dynamic allocation hooks.
00460 };
00461 
00462 /**
00463  * @class ACE_Read_Guard
00464  *
00465  * @brief This class is similar to class <ACE_Guard>, though it
00466  * acquires/releases a read lock automatically (naturally, the
00467  * <ACE_LOCK> it is instantiated with must support the appropriate
00468  * API).
00469  */
00470 template <class ACE_LOCK>
00471 class ACE_Read_Guard : public ACE_Guard<ACE_LOCK>
00472 {
00473 public:
00474   // = Initialization methods.
00475 
00476   /// Implicitly and automatically acquire a read lock.
00477   ACE_Read_Guard (ACE_LOCK& m);
00478 
00479   /// Implicitly and automatically acquire (or try to acquire) a read
00480   /// lock.
00481   ACE_Read_Guard (ACE_LOCK &m, int block);
00482 
00483   // = Lock accessors.
00484 
00485   /// Explicitly acquire the read lock.
00486   int acquire_read (void);
00487 
00488   /// Explicitly acquire the read lock.
00489   int acquire (void);
00490 
00491   /// Conditionally acquire the read lock (i.e., won't block).
00492   int tryacquire_read (void);
00493 
00494   /// Conditionally acquire the read lock (i.e., won't block).
00495   int tryacquire (void);
00496 
00497   // = Utility methods.
00498 
00499   /// Dump the state of an object.
00500   void dump (void) const;
00501 
00502   // ACE_ALLOC_HOOK_DECLARE;
00503   // Declare the dynamic allocation hooks.
00504 };
00505 
00506 #if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)))
00507 
00508 #define ACE_TSS_Guard ACE_Guard
00509 #define ACE_TSS_Write_GUARD ACE_Write_Guard
00510 #define ACE_TSS_Read_GUARD ACE_Read_Guard
00511 
00512 #else
00513  /* ACE platform supports some form of threading and
00514   thread-specific storage. */
00515 
00516 /**
00517  * @class ACE_TSS_Guard
00518  *
00519  * @brief This data structure is meant to be used within a method or
00520  * function...  It performs automatic aquisition and release of
00521  * a synchronization object.  Moreover, it ensures that the lock
00522  * is released even if a thread exits via <thr_exit>!
00523  */
00524 template <class ACE_LOCK>
00525 class ACE_TSS_Guard
00526 {
00527 public:
00528   // = Initialization and termination methods.
00529 
00530   /// Implicitly and automatically acquire the thread-specific lock.
00531   ACE_TSS_Guard (ACE_LOCK &lock, int block = 1);
00532 
00533   /// Implicitly release the thread-specific lock.
00534   ~ACE_TSS_Guard (void);
00535 
00536   // = Lock accessors.
00537 
00538   /// Explicitly acquire the thread-specific lock.
00539   int acquire (void);
00540 
00541   /// Conditionally acquire the thread-specific lock (i.e., won't
00542   /// block).
00543   int tryacquire (void);
00544 
00545   /// Explicitly release the thread-specific lock.
00546   int release (void);
00547 
00548   // = Utility methods.
00549   /// Explicitly release the thread-specific lock.
00550   int remove (void);
00551 
00552   /// Dump the state of an object.
00553   void dump (void) const;
00554 
00555   // ACE_ALLOC_HOOK_DECLARE;
00556   // Declare the dynamic allocation hooks.
00557 
00558 protected:
00559   /// Helper, meant for subclass only.
00560   ACE_TSS_Guard (void);
00561 
00562   /// Initialize the key.
00563   void init_key (void);
00564 
00565   /// Called when thread exits to clean up the lock.
00566   static void cleanup (void *ptr);
00567 
00568   /// Thread-specific key...
00569   ACE_thread_key_t key_;
00570 
00571 private:
00572   // = Prevent assignment and initialization.
00573   ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS_Guard<ACE_LOCK> &))
00574   ACE_UNIMPLEMENTED_FUNC (ACE_TSS_Guard (const ACE_TSS_Guard<ACE_LOCK> &))
00575 };
00576 
00577 /**
00578  * @class ACE_TSS_Write_Guard
00579  *
00580  * @brief This class is similar to class ACE_TSS_Guard, though it
00581  * acquires/releases a write-lock automatically (naturally, the
00582  * ACE_LOCK it is instantiated with must support the appropriate
00583  * API).
00584  */
00585 template <class ACE_LOCK>
00586 class ACE_TSS_Write_Guard : public ACE_TSS_Guard<ACE_LOCK>
00587 {
00588 public:
00589   // = Initialization method.
00590 
00591   /// Implicitly and automatically acquire the thread-specific write lock.
00592   ACE_TSS_Write_Guard (ACE_LOCK &lock, int block = 1);
00593 
00594   // = Lock accessors.
00595 
00596   /// Explicitly acquire the thread-specific write lock.
00597   int acquire_write (void);
00598 
00599   /// Explicitly acquire the thread-specific write lock.
00600   int acquire (void);
00601 
00602   /// Conditionally acquire the thread-specific write lock (i.e., won't block).
00603   int tryacquire_write (void);
00604 
00605   /// Conditionally acquire the thread-specific write lock (i.e., won't block).
00606   int tryacquire (void);
00607 
00608   // = Utility methods.
00609 
00610   /// Dump the state of an object.
00611   void dump (void) const;
00612 
00613   // ACE_ALLOC_HOOK_DECLARE;
00614   // Declare the dynamic allocation hooks.
00615 };
00616 
00617 /**
00618  * @class ACE_TSS_Read_Guard
00619  *
00620  * @brief This class is similar to class <ACE_TSS_Guard>, though it
00621  * acquires/releases a read lock automatically (naturally, the
00622  * <ACE_LOCK> it is instantiated with must support the
00623  * appropriate API).
00624  */
00625 template <class ACE_LOCK>
00626 class ACE_TSS_Read_Guard : public ACE_TSS_Guard<ACE_LOCK>
00627 {
00628 public:
00629   // = Initialization method.
00630   /// Implicitly and automatically acquire the thread-specific read lock.
00631   ACE_TSS_Read_Guard (ACE_LOCK &lock, int block = 1);
00632 
00633   // = Lock accessors.
00634   /// Explicitly acquire the thread-specific read lock.
00635   int acquire_read (void);
00636 
00637   /// Explicitly acquire the thread-specific read lock.
00638   int acquire (void);
00639 
00640   /// Conditionally acquire the thread-specific read lock (i.e., won't
00641   /// block).
00642   int tryacquire_read (void);
00643 
00644   /// Conditionally acquire the thread-specific read lock (i.e., won't
00645   /// block).
00646   int tryacquire (void);
00647 
00648   // = Utility methods.
00649   /// Dump the state of an object.
00650   void dump (void) const;
00651 
00652   // ACE_ALLOC_HOOK_DECLARE;
00653   // Declare the dynamic allocation hooks.
00654 };
00655 #endif /* !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))) */
00656 
00657 #if defined (ACE_HAS_THREADS) /* ACE platform supports some form of threading. */
00658 
00659 /**
00660  * @class ACE_Condition
00661  *
00662  * @brief ACE_Condition variable wrapper, which allows threads to block
00663  * until shared data changes state.
00664  *
00665  * A condition variable enables threads to atomically block and
00666  * test the condition under the protection of a mutual exclu-
00667  * sion lock (mutex) until the condition is satisfied.  That is,
00668  * the mutex must have been held by the thread before calling
00669  * wait or signal on the condition.  If the condition is false,
00670  * a thread blocks on a condition variable and atomically
00671  * releases the mutex that is waiting for the condition to
00672  * change.  If another thread changes the condition, it may wake
00673  * up waiting threads by signaling the associated condition
00674  * variable.  The waiting threads, upon awakening, reacquire the
00675  * mutex and re-evaluate the condition.
00676  * Note, you can only parameterize <ACE_Condition> with
00677  * @a ACE_Thread_Mutex, @a ACE_Recursive_Thread_Mutex, or @a ACE_Null_Mutex.
00678  */
00679 template <class MUTEX>
00680 class ACE_Condition
00681 {
00682 public:
00683   // = Initialiation and termination methods.
00684   /// Initialize the condition variable.
00685   ACE_Condition (MUTEX &m, int type = USYNC_THREAD,
00686                  const ACE_TCHAR *name = 0, void *arg = 0);
00687 
00688   /// Implicitly destroy the condition variable.
00689   ~ACE_Condition (void);
00690 
00691   // = Lock accessors.
00692   /**
00693    * Block on condition, or until absolute time-of-day has passed.  If
00694    * abstime == 0 use "blocking" <wait> semantics.  Else, if <abstime>
00695    * != 0 and the call times out before the condition is signaled
00696    * <wait> returns -1 and sets errno to ETIME.
00697    */
00698   int wait (const ACE_Time_Value *abstime);
00699 
00700   /// Block on condition.
00701   int wait (void);
00702 
00703   /**
00704    * Block on condition or until absolute time-of-day has passed.  If
00705    * abstime == 0 use "blocking" wait() semantics on the <mutex>
00706    * passed as a parameter (this is useful if you need to store the
00707    * <Condition> in shared memory).  Else, if <abstime> != 0 and the
00708    * call times out before the condition is signaled <wait> returns -1
00709    * and sets errno to ETIME.
00710    */
00711   int wait (MUTEX &mutex, const ACE_Time_Value *abstime = 0);
00712 
00713   /// Signal one waiting thread.
00714   int signal (void);
00715 
00716   /// Signal *all* waiting threads.
00717   int broadcast (void);
00718 
00719   // = Utility methods.
00720   /// Explicitly destroy the condition variable.
00721   int remove (void);
00722 
00723   /// Returns a reference to the underlying mutex_;
00724   MUTEX &mutex (void);
00725 
00726   /// Dump the state of an object.
00727   void dump (void) const;
00728 
00729   // ACE_ALLOC_HOOK_DECLARE;
00730   // Declare the dynamic allocation hooks.
00731 
00732 protected:
00733 #if defined (CHORUS)
00734   /// This condition resides in shared memory.
00735   ACE_cond_t *process_cond_;
00736 
00737   /**
00738    * Remember the name of the condition if we created it so we can
00739    * unlink it when we go away (only the actor that initialized the
00740    * memory can destroy it).
00741    */
00742   const ACE_TCHAR *condname_;
00743 #endif /* CHORUS */
00744 
00745   /// Condition variable.
00746   ACE_cond_t cond_;
00747 
00748   /// Reference to mutex lock.
00749   MUTEX &mutex_;
00750 
00751 private:
00752   // = Prevent assignment and initialization.
00753   ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_Condition<MUTEX> &))
00754   ACE_UNIMPLEMENTED_FUNC (ACE_Condition (const ACE_Condition<MUTEX> &))
00755 };
00756 
00757 /**
00758  * @class ACE_Thread_Condition
00759  *
00760  * @brief ACE_Condition variable wrapper that works within processes.
00761  *
00762  * A condition variable enables threads to atomically block and
00763  * test the condition under the protection of a mutual exclu-
00764  * sion lock (mutex) until the condition is satisfied.  That is,
00765  * the mutex must have been held by the thread before calling
00766  * wait or signal on the condition.  If the condition is false,
00767  * a thread blocks on a condition variable and atomically
00768  * releases the mutex that is waiting for the condition to
00769  * change.  If another thread changes the condition, it may wake
00770  * up waiting threads by signaling the associated condition
00771  * variable.  The waiting threads, upon awakening, reacquire the
00772  * mutex and re-evaluate the condition.
00773  */
00774 template <class MUTEX>
00775 class ACE_Thread_Condition : public ACE_Condition<MUTEX>
00776 {
00777 public:
00778   // = Initialization method.
00779   ACE_Thread_Condition (MUTEX &m, const ACE_TCHAR *name = 0, void *arg = 0);
00780 
00781   /// Dump the state of an object.
00782   void dump (void) const;
00783 
00784   // ACE_ALLOC_HOOK_DECLARE;
00785   // Declare the dynamic allocation hooks.
00786 };
00787 
00788 #endif /* ACE_HAS_THREADS */
00789 
00790 #if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
00791 
00792 /**
00793  * @class ACE_NULL_SYNCH
00794  *
00795  * @brief Implement a do nothing Synchronization wrapper that
00796  * typedefs the <ACE_Condition> and <ACE_Mutex> to the Null* versions.
00797  */
00798 class ACE_Export ACE_NULL_SYNCH
00799 {
00800 public:
00801   typedef ACE_Null_Mutex MUTEX;
00802   typedef ACE_Null_Mutex NULL_MUTEX;
00803   typedef ACE_Null_Mutex PROCESS_MUTEX;
00804   typedef ACE_Null_Mutex RECURSIVE_MUTEX;
00805   typedef ACE_Null_Mutex RW_MUTEX;
00806   typedef ACE_Null_Condition CONDITION;
00807   typedef ACE_Null_Condition RECURSIVE_CONDITION;
00808   typedef ACE_Null_Semaphore SEMAPHORE;
00809   typedef ACE_Null_Mutex NULL_SEMAPHORE;
00810 };
00811 
00812 #if defined (ACE_HAS_THREADS)
00813 
00814 class ACE_Process_Mutex;
00815 class ACE_Condition_Recursive_Thread_Mutex;
00816 
00817 /**
00818  * @class ACE_MT_SYNCH
00819  *
00820  * @brief Implement a default thread safe synchronization wrapper that
00821  * typedefs the <ACE_Condition> and <ACE_Mutex> to the
00822  * <ACE_Condition> and <ACE_Mutex> versions.  Note that this
00823  * should be a template, but SunC++ 4.0.1 complains about
00824  * this...
00825  */
00826 class ACE_Export ACE_MT_SYNCH
00827 {
00828 public:
00829   typedef ACE_Thread_Mutex MUTEX;
00830   typedef ACE_Null_Mutex NULL_MUTEX;
00831   typedef ACE_Process_Mutex PROCESS_MUTEX;
00832   typedef ACE_Recursive_Thread_Mutex RECURSIVE_MUTEX;
00833   typedef ACE_RW_Thread_Mutex RW_MUTEX;
00834   typedef ACE_Condition_Thread_Mutex CONDITION;
00835   typedef ACE_Condition_Recursive_Thread_Mutex RECURSIVE_CONDITION;
00836   typedef ACE_Thread_Semaphore SEMAPHORE;
00837   typedef ACE_Null_Semaphore NULL_SEMAPHORE;
00838 };
00839 
00840 #endif /* ACE_HAS_THREADS */
00841 
00842 #define ACE_SYNCH_MUTEX ACE_SYNCH::MUTEX
00843 #define ACE_SYNCH_NULL_MUTEX ACE_SYNCH::NULL_MUTEX
00844 #define ACE_SYNCH_RECURSIVE_MUTEX ACE_SYNCH::RECURSIVE_MUTEX
00845 #define ACE_SYNCH_RW_MUTEX ACE_SYNCH::RW_MUTEX
00846 #define ACE_SYNCH_CONDITION ACE_SYNCH::CONDITION
00847 #define ACE_SYNCH_RECURSIVE_CONDITION ACE_SYNCH::RECURSIVE_CONDITION
00848 #define ACE_SYNCH_NULL_SEMAPHORE ACE_SYNCH::NULL_SEMAPHORE
00849 #define ACE_SYNCH_SEMAPHORE ACE_SYNCH::SEMAPHORE
00850 
00851 #else /* !ACE_HAS_TEMPLATE_TYPEDEFS */
00852 
00853 #if defined (ACE_HAS_OPTIMIZED_MESSAGE_QUEUE)
00854 #define ACE_NULL_SYNCH ACE_Null_Mutex, ACE_Null_Condition, ACE_Null_Mutex
00855 #define ACE_MT_SYNCH ACE_Thread_Mutex, ACE_Condition_Thread_Mutex, ACE_Thread_Semaphore
00856 #else
00857 #define ACE_NULL_SYNCH ACE_Null_Mutex, ACE_Null_Condition
00858 #define ACE_MT_SYNCH ACE_Thread_Mutex, ACE_Condition_Thread_Mutex
00859 #endif /* ACE_HAS_OPTIMIZED_MESSAGE_QUEUE */
00860 
00861 #if defined (ACE_HAS_THREADS)
00862 
00863 #define ACE_SYNCH_MUTEX ACE_Thread_Mutex
00864 #define ACE_SYNCH_NULL_MUTEX  ACE_Null_Mutex
00865 #define ACE_SYNCH_RECURSIVE_MUTEX ACE_Recursive_Thread_Mutex
00866 #define ACE_SYNCH_RW_MUTEX ACE_RW_Thread_Mutex
00867 #define ACE_SYNCH_CONDITION ACE_Condition_Thread_Mutex
00868 #define ACE_SYNCH_RECURSIVE_CONDITION ACE_Condition_Recursive_Thread_Mutex
00869 #define ACE_SYNCH_SEMAPHORE ACE_Thread_Semaphore
00870 #define ACE_SYNCH_NULL_SEMAPHORE  ACE_Null_Semaphore
00871 
00872 #else /* ACE_HAS_THREADS */
00873 
00874 #define ACE_SYNCH_MUTEX ACE_Null_Mutex
00875 #define ACE_SYNCH_NULL_MUTEX ACE_Null_Mutex
00876 #define ACE_SYNCH_RECURSIVE_MUTEX ACE_Null_Mutex
00877 #define ACE_SYNCH_RW_MUTEX ACE_Null_Mutex
00878 #define ACE_SYNCH_CONDITION ACE_Null_Condition
00879 #define ACE_SYNCH_RECURSIVE_CONDITION ACE_Null_Condition
00880 #define ACE_SYNCH_SEMAPHORE ACE_Null_Semaphore
00881 #define ACE_SYNCH_NULL_SEMAPHORE ACE_Null_Mutex
00882 
00883 #endif /* ACE_HAS_THREADS */
00884 #endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
00885 
00886 // These are available on *all* platforms
00887 #define ACE_SYNCH_PROCESS_SEMAPHORE ACE_Process_Semaphore
00888 #define ACE_SYNCH_PROCESS_MUTEX  ACE_Process_Mutex
00889 
00890 #if defined (ACE_HAS_THREADS)
00891 #define ACE_SYNCH ACE_MT_SYNCH
00892 #else /* ACE_HAS_THREADS */
00893 #define ACE_SYNCH ACE_NULL_SYNCH
00894 #endif /* ACE_HAS_THREADS */
00895 
00896 #if defined (__ACE_INLINE__)
00897 #include "ace/Synch_T.i"
00898 #endif /* __ACE_INLINE__ */
00899 
00900 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
00901 #include "ace/Synch_T.cpp"
00902 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
00903 
00904 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
00905 #pragma implementation ("Synch_T.cpp")
00906 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
00907 
00908 #include "ace/post.h"
00909 #endif /* ACE_SYNCH_T_H */

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