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 */
1.2.14 written by Dimitri van Heesch,
© 1997-2002