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