00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file Local_Tokens.h 00006 * 00007 * $Id: Local_Tokens.h 74005 2006-08-14 11:30:00Z johnnyw $ 00008 * 00009 * @author Karl-Heinz Dorn <kdorn@erlh.siemens.de> 00010 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> 00011 * @author Tim Harrison <harrison@cs.wustl.edu> 00012 * 00013 * This file contains definitions for the following classes: 00014 * 00015 * public: 00016 * 7. ACE_Token_Proxy 00017 * 8. ACE_Null_Token : public ACE_Token_Proxy 00018 * 9. ACE_Local_Mutex : public ACE_Token_Proxy 00019 * *. ACE_Local_RLock : public ACE_Local_Mutex 00020 * &. ACE_Local_WLock : public ACE_Local_Mutex 00021 * private: 00022 * 1. ACE_TOKEN_CONST 00023 * 3. ACE_TPQ_Entry 00024 * b. ACE_TSS_TPQ_Entry 00025 * c. ACE_TPQ_Iterator 00026 * 4. ACE_Token_Proxy_Queue 00027 * 5. ACE_Tokens 00028 * 6. ACE_Mutex_Token : public ACE_Tokens 00029 * 12. ACE_RW_Token : public ACE_Tokens 00030 * a. ACE_Token_Name 00031 * 00032 * Note that the locking classes defined in this file are *not* 00033 * intended to be used as general-purpose synchronization 00034 * mechanisms, such as mutexes or semaphores. Instead, you should 00035 * use the ACE_Recursive_Thread_Mutex, ACE_Thread_Mutex, 00036 * ACE_Thread_Semaphore, etc., that are defined in 00037 * $ACE_ROOT/ace/Synch.h and $ACE_ROOT/ace/Synch_T.h or the 00038 * ACE_Token that's defined in $ACE_ROOT/ace/Token.h. 00039 * 00040 * 00041 */ 00042 //============================================================================= 00043 00044 #ifndef ACE_LOCAL_MUTEX_H 00045 #define ACE_LOCAL_MUTEX_H 00046 #include /**/ "ace/pre.h" 00047 00048 #include /**/ "ace/config-all.h" 00049 00050 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00051 # pragma once 00052 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00053 00054 #if defined (ACE_HAS_TOKENS_LIBRARY) 00055 00056 #include "ace/Synch_Traits.h" 00057 #include "ace/Condition_Thread_Mutex.h" 00058 #include "ace/TSS_T.h" 00059 #include "ace/Containers.h" 00060 #include "ace/Synch_Options.h" 00061 #include "ace/Map_Manager.h" 00062 #include "ace/Log_Msg.h" 00063 #include "ace/OS_NS_string.h" 00064 #include "ace/os_include/os_netdb.h" 00065 00066 #if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) 00067 # define ACE_NO_TSS_TOKENS 1 00068 #endif /* !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) */ 00069 00070 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00071 00072 // 1. 00073 /** 00074 * @class ACE_TOKEN_CONST 00075 * 00076 * @brief Not a public interface. 00077 * 00078 * Constant definitions and typedefs for Token library. Mostly, 00079 * this class is necessary to fight the compiler with order of 00080 * declaration errors. 00081 */ 00082 namespace ACE_TOKEN_CONST 00083 { 00084 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) 00085 // ACE platform supports some form of threading. 00086 typedef ACE_Condition_Thread_Mutex COND_VAR; 00087 typedef ACE_Thread_Mutex MUTEX; 00088 typedef ACE_Guard<ACE_Thread_Mutex> GUARD; 00089 #else 00090 typedef ACE_Null_Condition COND_VAR; 00091 typedef ACE_Null_Mutex MUTEX; 00092 typedef ACE_Guard<ACE_Null_Mutex> GUARD; 00093 #endif /* ACE_HAS_THREADS */ 00094 } 00095 00096 // Forward decl. 00097 class ACE_Token_Proxy; 00098 00099 // 3.. 00100 /** 00101 * @class ACE_TPQ_Entry 00102 * 00103 * @brief Token Proxy Queue entry. Used in the ACE_Token_Proxy_Queue 00104 * 00105 * Not a public interface. 00106 */ 00107 class ACE_Export ACE_TPQ_Entry 00108 { 00109 friend class ACE_Token_Manager; 00110 public: 00111 typedef void (*PTVF) (void *); 00112 00113 /// Null constructor. 00114 ACE_TPQ_Entry (void); 00115 00116 /// Constructor. 00117 ACE_TPQ_Entry (const ACE_Token_Proxy *proxy, 00118 const ACE_TCHAR *client_id); 00119 00120 /// Copy constructor. 00121 ACE_TPQ_Entry (const ACE_TPQ_Entry &rhs); 00122 00123 /// Destructor. 00124 ~ACE_TPQ_Entry (void); 00125 00126 /// Copy operator use by the queue. 00127 void operator= (const ACE_TPQ_Entry &rhs); 00128 00129 /// Get top of the queue. 00130 ACE_Token_Proxy *proxy (void) const; 00131 00132 /// Set top of the queue. 00133 void proxy (ACE_Token_Proxy *); 00134 00135 /// Get nesting level of the entry. 00136 int nesting_level (void) const; 00137 00138 /// Delta nesting level of the entry. 00139 void nesting_level (int delta); 00140 00141 /// Get client_id of the entry. 00142 const ACE_TCHAR *client_id (void) const; 00143 00144 /// Set client_id of the entry. 00145 void client_id (const ACE_TCHAR *); 00146 00147 /// Returns 1 if @a id == client id. Does not check for @a id == 0. 00148 int equal_client_id (const ACE_TCHAR *id); 00149 00150 /// One method for arg and sleep_hook. 00151 void set (void (*sleep_hook)(void *)); 00152 00153 /// Set sleep hook of the entry. 00154 void sleep_hook (void (*sh)(void *)); 00155 00156 /// Get sleep hook of the entry. 00157 PTVF sleep_hook (void) const; 00158 00159 /// Call the sleep hook function or method passing arg. 00160 void call_sleep_hook (void); 00161 00162 /// Dump the state of the class. 00163 void dump (void) const; 00164 00165 // = Used to block the thread if an acquire fails with EWOULDBLOCK. 00166 ACE_TOKEN_CONST::COND_VAR cond_var_; 00167 ACE_TOKEN_CONST::MUTEX lock_; 00168 00169 /// Pointer to next in list. 00170 ACE_TPQ_Entry *next_; 00171 00172 /// Get whether this client is blocked waiting for a token. 00173 int waiting (void) const; 00174 00175 /// Set whether this client is blocked waiting for a token. 00176 void waiting (int w); 00177 00178 private: 00179 /// This client is waiting for a token. 00180 int waiting_; 00181 00182 /// Proxy. 00183 ACE_Token_Proxy *proxy_; 00184 00185 /// Nesting level. 00186 int nesting_level_; 00187 00188 /// Arg. 00189 void *arg_; 00190 00191 /// Client id. 00192 ACE_TCHAR client_id_[ACE_MAXCLIENTIDLEN]; 00193 00194 /// Sleep hook. 00195 void (*sleep_hook_)(void *); 00196 }; 00197 00198 // b.. 00199 #if defined (ACE_NO_TSS_TOKENS) 00200 typedef ACE_TPQ_Entry ACE_TPQ_ENTRY; 00201 #else 00202 typedef ACE_TSS<ACE_TPQ_Entry> ACE_TPQ_ENTRY; 00203 #endif /* ACE_NO_TSS_TOKENS */ 00204 00205 /** 00206 * @class ACE_TSS_TPQ_Entry 00207 * 00208 * @brief ACE_TSS_TPQ_Entry 00209 * 00210 * Not a public interface. 00211 */ 00212 class ACE_Export ACE_TSS_TPQ_Entry : public ACE_TPQ_ENTRY 00213 { 00214 public: 00215 /// These are passed to the constructor of ACE_TPQ_Entry in 00216 /// make_TSS_TYPE 00217 ACE_TSS_TPQ_Entry (const ACE_Token_Proxy *proxy, 00218 const ACE_TCHAR *client_id); 00219 00220 /// Destructor. 00221 virtual ~ACE_TSS_TPQ_Entry (void); 00222 00223 /// Allows us to pass args to the construction of the TSS object. 00224 virtual ACE_TPQ_Entry *make_TSS_TYPE (void) const; 00225 00226 /// Operator overloading and inheritence don't mix. 00227 operator ACE_TPQ_Entry *(void); 00228 00229 /// Dump the state of the class. 00230 void dump (void) const; 00231 00232 #if defined (ACE_NO_TSS_TOKENS) 00233 ACE_TPQ_Entry *operator-> (void) 00234 { 00235 return (ACE_TPQ_Entry *) this; 00236 } 00237 #endif /* ACE_NO_TSS_TOKENS */ 00238 00239 private: 00240 /// Private: should not be used 00241 ACE_TSS_TPQ_Entry (const ACE_TSS_TPQ_Entry &); 00242 void operator= (const ACE_TSS_TPQ_Entry &); 00243 00244 // = These are passed to the constructor of ACE_TPQ_Entry in 00245 // make_TSS_TYPE 00246 00247 /// Proxy. 00248 const ACE_Token_Proxy *proxy_; 00249 00250 /// Client_id. 00251 const ACE_TCHAR *client_id_; 00252 }; 00253 00254 class ACE_Token_Proxy_Queue; 00255 00256 // c.. 00257 /** 00258 * @class ACE_TPQ_Iterator 00259 * 00260 * @brief Iterates through ACE_Token_Proxy_Queues. 00261 * 00262 * Not a public interface. 00263 */ 00264 class ACE_Export ACE_TPQ_Iterator 00265 { 00266 public: 00267 /// Constructor. 00268 ACE_TPQ_Iterator (ACE_Token_Proxy_Queue &q); 00269 00270 /// Destructor. 00271 ~ACE_TPQ_Iterator (void); 00272 00273 /// Pass back the <next_item>. 00274 int next (ACE_TPQ_Entry *&next_item); 00275 00276 /// Returns 1 when all items have been seen, else 0. 00277 int done (void) const; 00278 00279 /// Move forward by one element in the queue. 00280 void advance (void); 00281 00282 /// Dump the state of an object. 00283 void dump (void) const; 00284 00285 private: 00286 ACE_TPQ_Entry *current_; 00287 }; 00288 00289 // 4.. 00290 /** 00291 * @class ACE_Token_Proxy_Queue 00292 * 00293 * @brief Token waiter list. 00294 * 00295 * Not a public interface. 00296 * This queue holds all the token proxies waiting for ownership 00297 * of a token. Along with the proxy reference, it also stores 00298 * the nesting level, client id, and a magic cookie from the 00299 * proxy. This queue stores the ACE_TPQ_Entries by pointer 00300 * values. It DOES NOT make copies. Thus, the user is 00301 * responsible to ensure that the TPQ's stick around. This is 00302 * motivated by the need to reduce dynamic memory allocation. 00303 */ 00304 class ACE_Export ACE_Token_Proxy_Queue 00305 { 00306 public: 00307 friend class ACE_TPQ_Iterator; 00308 00309 /// Constructor. 00310 ACE_Token_Proxy_Queue (void); 00311 00312 /// Destructor. 00313 ~ACE_Token_Proxy_Queue (void); 00314 00315 /** 00316 * Enqueue a proxy, nesting level, client_id, and a magic cookie at 00317 * the given position in the list. If the position is -1, we 00318 * enqueue at the end of the list (I think). 00319 */ 00320 void enqueue (ACE_TPQ_Entry* new_entry, 00321 int position); 00322 00323 /// Top of the queue. 00324 const ACE_TPQ_Entry* head (void); 00325 00326 // int member (const ACE_TCHAR *id); 00327 // Is this id in the waiter list? 00328 00329 /// Remove the top waiter. 00330 void dequeue (void); 00331 00332 /// Remove the waiter whose proxy ref matches @a remove_me. 00333 void remove (const ACE_TPQ_Entry *remove_me); 00334 00335 /// The number of waiters. 00336 int size (void); 00337 00338 /// Dump the state of the class. 00339 void dump (void) const; 00340 00341 protected: 00342 /// Head. 00343 ACE_TPQ_Entry *head_; 00344 00345 /// Tail. 00346 ACE_TPQ_Entry *tail_; 00347 00348 /// Size. 00349 int size_; 00350 }; 00351 00352 // 5.. 00353 /** 00354 * @class ACE_Tokens 00355 * 00356 * @brief Abstract representation of ACE tokens. 00357 * 00358 * Not a public interface. 00359 * Currently, I don't see a reason for providing an abstract 00360 * interface at this level of the library. As of yet, no one 00361 * uses ACE_Tokens derivatives through this abstract interface 00362 * except for ACE_Token_Manager. It only uses the statistical 00363 * methods which are shared by all Tokens. For that reason, it 00364 * still makes since to have a common base class. However, 00365 * acquire, renew, and release do not need to have matching 00366 * interfaces throughout all Tokens. 00367 * To add a new type of token (e.g. semaphore), this class must 00368 * be subtyped to define the new semantics. See 00369 * ACE_Token_Manager for details. 00370 */ 00371 class ACE_Export ACE_Tokens 00372 { 00373 public: 00374 00375 /// Null constructor. 00376 ACE_Tokens (void); 00377 00378 /// Destructor 00379 virtual ~ACE_Tokens (void); 00380 00381 /// No implementation. 00382 virtual int acquire (ACE_TPQ_Entry *caller, 00383 int ignore_deadlock, 00384 int notify) = 0; 00385 00386 /// No implementation. 00387 virtual int tryacquire (ACE_TPQ_Entry *caller) = 0; 00388 00389 /// No implementation. 00390 virtual int renew (ACE_TPQ_Entry *caller, 00391 int requeue_position) = 0; 00392 00393 /// No implementation. 00394 virtual int release (ACE_TPQ_Entry *caller) = 0; 00395 00396 /// Move the caller to the front of the waiter list. This is for use 00397 /// with remote mutexes and shadow mutexes. 00398 void make_owner (ACE_TPQ_Entry *caller); 00399 00400 /// Remove the caller from the waiter list. 00401 void remove (ACE_TPQ_Entry *caller); 00402 00403 // = Accessor methods. 00404 00405 /// Stack of owners. 00406 typedef ACE_Unbounded_Stack<ACE_TPQ_Entry *> OWNER_STACK; 00407 00408 /// Returns a stack of the current owners. Returns -1 on error, 0 on 00409 /// success. If <id> is non-zero, returns 1 if id is an owner. 00410 virtual int owners (OWNER_STACK &o, const ACE_TCHAR *id) = 0; 00411 00412 /// Returns 1 if <id> is waiting for this token. 0 otherwise. 00413 virtual int is_waiting_for (const ACE_TCHAR *id) = 0; 00414 00415 /// Returns 1 if <id> is an owner of this token. 0 otherwise. 00416 virtual int is_owner (const ACE_TCHAR *id) = 0; 00417 00418 /// Return the queue of waiters. 00419 virtual ACE_Token_Proxy_Queue *waiters (void); 00420 00421 /// Return the number of proxies that are currently waiting to get 00422 /// the token. 00423 virtual int no_of_waiters (void); 00424 00425 /// The current owner. 00426 const ACE_TCHAR *owner_id (void); 00427 00428 /// Token name. 00429 const ACE_TCHAR* name (void); 00430 00431 // = Reference counting. These are only called by the 00432 // Token_Manager. 00433 void inc_reference (void); 00434 int dec_reference (void); 00435 00436 /// Dump the state of the class. 00437 void dump (void) const; 00438 00439 /** 00440 * These are the Token types supported by the library at ship time. 00441 * There is no restriction on the number of Token types added by 00442 * "3rd parties." These are only necessary for the Token Server. 00443 */ 00444 enum TOKEN_TYPES { MUTEX, RWLOCK }; 00445 00446 /** 00447 * Provides a manual RTTI mechanism. This method is used only by 00448 * ACE_Token_Request so that the type of a token can be sent to a 00449 * remote Token Server. 00450 */ 00451 virtual int type (void) const = 0; 00452 00453 // = The following methods allow the deadlock detection algorithm to 00454 // check if this token has been visited. 00455 00456 /// Mark or unmark the token as visited. 00457 void visit (int v); 00458 00459 /// Check if the token has been visited. 00460 int visited (void); 00461 00462 /// All the data of the current owner. 00463 ACE_TPQ_Entry *owner (void); 00464 00465 protected: 00466 00467 /// For the deadlock detection algorithm. 00468 int visited_; 00469 00470 /// Reference count. 00471 int reference_count_; 00472 00473 /// List of client's owning and waiting the token. 00474 ACE_Token_Proxy_Queue waiters_; 00475 00476 /// Name of token. 00477 ACE_TCHAR token_name_[ACE_MAXTOKENNAMELEN]; 00478 }; 00479 00480 class ACE_Local_Mutex; 00481 00482 // 6.. 00483 /** 00484 * @class ACE_Mutex_Token 00485 * 00486 * @brief Class that acquires, renews, and releases a process-local 00487 * synchronization token. 00488 * 00489 * Not a public interface. 00490 * This class is a more general-purpose synchronization mechanism 00491 * than SunOS 5.x mutexes. For example, it implements "recursive 00492 * mutex" semantics, where a thread that owns the token can 00493 * reacquire it without deadlocking. In addition, threads that 00494 * are blocked awaiting the token are serviced in strict FIFO 00495 * order as other threads release the token (SunOS 5.x mutexes 00496 * don't strictly enforce an acquisition order). 00497 */ 00498 class ACE_Export ACE_Mutex_Token : public ACE_Tokens 00499 { 00500 public: 00501 /// Constructor 00502 explicit ACE_Mutex_Token (const ACE_TCHAR* name); 00503 00504 /// Destructor 00505 virtual ~ACE_Mutex_Token (void); 00506 00507 // = Synchronization operations. 00508 // With acquire, renew, and release, the caller must be specified so 00509 // that multiple proxies (e.g. ACE_Local_Mutex) can use the same 00510 // token. 00511 00512 /** 00513 * Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as 00514 * the reason. If errnum == EWOULDBLOCK, and notify == 1, 00515 * <ACE_Token_Proxy::sleep_hook> has been called on the current 00516 * owner of the token. If ignore_deadlock is passed as 1 and errnum 00517 * == EDEADLK, then deadlock was detected via ace_token_manager. 00518 */ 00519 virtual int acquire (ACE_TPQ_Entry *caller, 00520 int ignore_deadlock, 00521 int notify); 00522 00523 /// Same as acquire, but fails if would block 00524 virtual int tryacquire (ACE_TPQ_Entry *caller); 00525 00526 /** 00527 * An optimized method that efficiently reacquires the token if no 00528 * other threads are waiting. This is useful for situations where 00529 * you don't want to degrade the quality of service if there are 00530 * other threads waiting to get the token. If <requeue_position> == 00531 * -1 and there are other threads waiting to obtain the token we are 00532 * queued at the end of the list of waiters. If <requeue_position> 00533 * > -1 then it indicates how many entries to skip over before 00534 * inserting our thread into the list of waiters (e.g., 00535 * <requeue_position> == 0 means "insert at front of the queue"). 00536 * Renew has the rather odd semantics such that if there are other 00537 * waiting threads it will give up the token even if the 00538 * nesting_level_ > 1. I'm not sure if this is really the right 00539 * thing to do (since it makes it possible for shared data to be 00540 * changed unexpectedly) so use with caution... Returns 0 on 00541 * success, -1 on failure with <ACE_Log_Msg::errnum> as the reason. 00542 * If errnum == EWOULDBLOCK, and notify == 1, 00543 * <ACE_Token_Proxy::sleep_hook> has been called on the current 00544 * owner of the token. 00545 */ 00546 virtual int renew (ACE_TPQ_Entry *caller, 00547 int requeue_position); 00548 00549 /** 00550 * Relinquish the token. If there are any waiters then the next one 00551 * in line gets it. If the caller is not the owner, caller is 00552 * removed from the waiter list. 00553 */ 00554 virtual int release (ACE_TPQ_Entry *caller); 00555 00556 /// Dump the state of the class. 00557 void dump (void) const; 00558 00559 /// Returns ACE_Tokens::MUTEX. 00560 virtual int type (void) const; 00561 00562 /// Returns a stack of the current owners. Returns -1 on error, 0 on 00563 /// success. If <id> is non-zero, returns 1 if id is an owner. 00564 virtual int owners (OWNER_STACK &o, const ACE_TCHAR *id); 00565 00566 /// Returns 1 if <id> is waiting for this token. 0 otherwise. 00567 virtual int is_waiting_for (const ACE_TCHAR *id); 00568 00569 /// Returns 1 if <id> is an owner of this token. 0 otherwise. 00570 virtual int is_owner (const ACE_TCHAR *id); 00571 00572 private: 00573 /// ACE_Mutex_Token used to lock internal data structures. 00574 ACE_TOKEN_CONST::MUTEX lock_; 00575 }; 00576 00577 // 12.. 00578 /** 00579 * @class ACE_RW_Token 00580 * 00581 * @brief Class that acquires, renews, and releases a process-local 00582 * synchronization token. 00583 * 00584 * Not a public interface. 00585 * This class is a more general-purpose synchronization mechanism 00586 * than SunOS 5.x mutexes. For example, it implements "recursive 00587 * mutex" semantics, where a thread that owns the token can 00588 * reacquire it without deadlocking. In addition, threads that are 00589 * blocked awaiting the token are serviced in strict FIFO order as 00590 * other threads release the token (SunOS 5.x mutexes don't strictly 00591 * enforce an acquisition order). 00592 */ 00593 class ACE_Export ACE_RW_Token : public ACE_Tokens 00594 { 00595 public: 00596 /// Constructor. 00597 explicit ACE_RW_Token (const ACE_TCHAR* name); 00598 00599 /// Destructor. 00600 virtual ~ACE_RW_Token (void); 00601 00602 // = Synchronization operations. 00603 // With acquire, renew, and release, the caller must be specified so 00604 // that multiple proxies (e.g. ACE_Local_Mutex) can use the same 00605 // token. 00606 00607 /** 00608 * Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as 00609 * the reason. If errnum == EWOULDBLOCK, and notify == 1, 00610 * <ACE_Token_Proxy::sleep_hook> has been called on the current 00611 * owner of the token. If @a ignore_deadlock is passed as 1 and errnum 00612 * == EDEADLK, then deadlock was detected via ACE_Token_Manager. 00613 */ 00614 virtual int acquire (ACE_TPQ_Entry *caller, 00615 int ignore_deadlock, 00616 int notify); 00617 00618 /// Same as acquire except fails on would block 00619 virtual int tryacquire (ACE_TPQ_Entry *caller); 00620 00621 /** 00622 * An optimized method that efficiently reacquires the token if no 00623 * other threads are waiting. This is useful for situations where 00624 * you don't want to degrade the quality of service if there are 00625 * other threads waiting to get the token. If <requeue_position> == 00626 * -1 and there are other threads waiting to obtain the token we are 00627 * queued at the end of the list of waiters. If <requeue_position> 00628 * > -1 then it indicates how many entries to skip over before 00629 * inserting our thread into the list of waiters (e.g., 00630 * <requeue_position> == 0 means "insert at front of the queue"). 00631 * Renew has the rather odd semantics such that if there are other 00632 * waiting threads it will give up the token even if the 00633 * nesting_level_ > 1. I'm not sure if this is really the right 00634 * thing to do (since it makes it possible for shared data to be 00635 * changed unexpectedly) so use with caution... Returns 0 on 00636 * success, -1 on failure with <ACE_Log_Msg::errnum> as the reason. 00637 * If errnum == EWOULDBLOCK, and notify == 1, 00638 * <ACE_Token_Proxy::sleep_hook> has been called on the current 00639 * owner of the token. 00640 */ 00641 virtual int renew (ACE_TPQ_Entry *caller, 00642 int requeue_position); 00643 00644 /** 00645 * Relinquish the token. If there are any waiters then the next one 00646 * in line gets it. If the caller is not the owner, caller is 00647 * removed from the waiter list. 00648 */ 00649 virtual int release (ACE_TPQ_Entry *caller); 00650 00651 /// Dump the state of the class. 00652 void dump (void) const; 00653 00654 /// These are the types that proxies can be. 00655 enum PROXY_TYPE { READER, WRITER }; 00656 00657 /// Returns READER or WRITER. 00658 virtual int type (void) const; 00659 00660 /// Returns a stack of the current owners. Returns -1 on error, 0 on 00661 /// success. If <id> is non-zero, returns 1 if id is an owner. 00662 virtual int owners (OWNER_STACK &o, const ACE_TCHAR *id); 00663 00664 /// Returns 1 if <id> is waiting for this token. 0 otherwise. 00665 virtual int is_waiting_for (const ACE_TCHAR *id); 00666 00667 /// Returns 1 if <id> is an owner of this token. 0 otherwise. 00668 virtual int is_owner (const ACE_TCHAR *id); 00669 00670 protected: 00671 /// The number of waiting writers. 00672 int num_writers_; 00673 00674 /// ACE_Mutex_Token used to lock internal data structures. 00675 ACE_TOKEN_CONST::MUTEX lock_; 00676 00677 /// Sets the new owner. 00678 void notify_new_owner (ACE_TPQ_Entry *caller); 00679 }; 00680 00681 // a.. 00682 /** 00683 * @class ACE_Token_Name 00684 * 00685 * @brief Allows Token_Manger to identify tokens. 00686 * 00687 * For now, this is just a string. We need a string class 00688 * anyway to use in ACE_Map_Manager. Having this class 00689 * (instead of <ACE_SString>) allows us to easily change if 00690 * needed. For instance, we may choose to identify tokens by 00691 * name and *type* in the future. 00692 */ 00693 class ACE_Export ACE_Token_Name 00694 { 00695 public: 00696 /// Construction. 00697 ACE_Token_Name (const ACE_TCHAR *token_name = 0); 00698 00699 /// Copy construction. 00700 ACE_Token_Name (const ACE_Token_Name &rhs); 00701 00702 /// Destructor. 00703 virtual ~ACE_Token_Name (void); 00704 00705 /// Copy. 00706 void operator= (const ACE_Token_Name &rhs); 00707 00708 /// Comparison. 00709 bool operator== (const ACE_Token_Name &rhs) const; 00710 00711 /// Get the token name. 00712 const ACE_TCHAR *name (void) const; 00713 00714 /// Set the token name. 00715 void name (const ACE_TCHAR *new_name); 00716 00717 /// Dump the state of the class. 00718 void dump (void) const; 00719 00720 private: 00721 /// Name of the token. 00722 ACE_TCHAR token_name_[ACE_MAXTOKENNAMELEN]; 00723 }; 00724 00725 // 7.. 00726 /** 00727 * @class ACE_Token_Proxy 00728 * 00729 * @brief Abstract representation of ACE tokens. 00730 * 00731 * Interface for all Tokens in ACE. This class implements the 00732 * synchronization needed for tokens (condition variables etc.) 00733 * The algorithms for the operations (acquire, release, etc.) 00734 * operate on the generic ACE_Tokens interface. Thus, the _type_ 00735 * of token (mutex, rwlock) can be set at construction of 00736 * ACE_Token_Proxy. You can use all Tokens in ACE through the 00737 * ACE_Token_Proxy by passing the proper values at construction. 00738 * Alternatively, there are class definitions which "know" how to 00739 * do this (ACE_Local_Mutex, ACE_Local_RLock, ACE_Local_WLock). 00740 * To add a new type of token (e.g. semaphore), this class is not 00741 * changed. See ACE_Token_Manager for details. 00742 * Tokens (e.g. ACE_Mutex_Token) assume that it can always call 00743 * <ACE_Token_Proxy::token_acquired> on a new token owner. This 00744 * is not a problem for synchronous use of token proxies (that is, 00745 * when acquires block until successful.) However, for 00746 * implementations of the Token Server, which may use asynch 00747 * operations, the proxy can not go away after an acquire until 00748 * the token is acquired. This is not really a problem, but 00749 * should be understood. 00750 */ 00751 class ACE_Export ACE_Token_Proxy 00752 { 00753 public: 00754 friend class ACE_Token_Manager; 00755 friend class ACE_Token_Invariant_Manager; // For testing. 00756 00757 // Initialization and termination methods. 00758 /// Construction. 00759 ACE_Token_Proxy (void); 00760 00761 /// Destructor. 00762 virtual ~ACE_Token_Proxy (void); 00763 00764 /** 00765 * Open the <ACE_Token>. 00766 * @param name The string uniquely identifying the token. 00767 * @param ignore_deadlock Can be 1 to disable deadlock notifications. 00768 * @param debug Prints debug messages. 00769 */ 00770 virtual int open (const ACE_TCHAR *name, 00771 int ignore_deadlock = 0, 00772 int debug = 0); 00773 00774 // = The following methods have implementations which are 00775 // independent of the token semantics (mutex, rwlock, etc.) They 00776 // forward operations to the underlying token and perform the 00777 // necessary blocking semantics for operations (condition variables 00778 // etc.) This allows reuse of the blocking code as well as having 00779 // multiple proxies to the same token. 00780 00781 /// Calls acquire on the token. Blocks the calling thread if would 00782 /// block. 00783 virtual int acquire (int notify = 0, 00784 void (*sleep_hook)(void *) = 0, 00785 ACE_Synch_Options &options = 00786 ACE_Synch_Options::defaults); 00787 00788 /// Calls renew on the token. Blocks the calling thread if would block. 00789 virtual int renew (int requeue_position = -1, 00790 ACE_Synch_Options &options = 00791 ACE_Synch_Options::defaults); 00792 00793 /// Calls renew on the token. 00794 virtual int tryacquire (void (*sleep_hook)(void *) = 0); 00795 00796 /// Calls release on the token. 00797 virtual int release (ACE_Synch_Options &options = 00798 ACE_Synch_Options::defaults); 00799 00800 /// Calls remove on the token. 00801 virtual int remove (ACE_Synch_Options &options = 00802 ACE_Synch_Options::defaults); 00803 00804 /// Since the locking mechanism doesn't support read locks then this 00805 /// just calls <acquire>. 00806 virtual int acquire_read (int notify = 0, 00807 void (*sleep_hook)(void *) = 0, 00808 ACE_Synch_Options &options = 00809 ACE_Synch_Options::defaults); 00810 00811 /// Since the locking mechanism doesn't support write locks then this 00812 /// just calls <acquire>. 00813 virtual int acquire_write (int notify = 0, 00814 void (*sleep_hook)(void *) = 0, 00815 ACE_Synch_Options &options = 00816 ACE_Synch_Options::defaults); 00817 00818 /// Since the locking mechanism doesn't support read locks then this 00819 /// just calls <tryacquire>. 00820 virtual int tryacquire_read (void (*sleep_hook)(void *) = 0); 00821 00822 /// Since the locking mechanism doesn't support write locks then this 00823 /// just calls <tryacquire>. 00824 virtual int tryacquire_write (void (*sleep_hook)(void *) = 0); 00825 00826 // = Utility methods. 00827 00828 /// Get the client id of the proxy. This is implemented as 00829 /// thread-specific data. 00830 virtual const ACE_TCHAR *client_id (void) const; 00831 00832 /** 00833 * Set the client_id for the calling thread. I strongly recommend 00834 * that this not be used unless you really know what you're doing. 00835 * I use this in the Token Server, and it caused many headaches. 00836 */ 00837 virtual void client_id (const ACE_TCHAR *client_id); 00838 00839 /** 00840 * Return the name of the token. This is important for use within 00841 * the token servers (local and remote) as well as with token 00842 * collections. So, all derivations of ACE_Token_Proxy must be able to 00843 * stringify some name. The name must uniquely identify a token. 00844 * So, for instance, the token within the reactor should probably be 00845 * called "Reactor Token." 00846 */ 00847 virtual const ACE_TCHAR *name (void) const; 00848 00849 /** 00850 * This should really be called <someone_waiting>. This is called 00851 * by ACE_Token_xx's when another proxy enters the waiting list and 00852 * requests that the current token holder be notified. 00853 */ 00854 virtual void sleep_hook (void); 00855 00856 /// This is called when a queued (waiting) proxy is removed from the 00857 /// waiters list and given the token. 00858 virtual void token_acquired (ACE_TPQ_Entry *); 00859 00860 /// The client id of the current token holder 00861 virtual const ACE_TCHAR *owner_id (void); 00862 00863 /// Return a dynamically allocated clone of the derived class. 00864 virtual ACE_Token_Proxy *clone (void) const = 0; 00865 00866 /// Dump the state of the class. 00867 void dump (void) const; 00868 00869 /** 00870 * This method can be used be Tokens (e.g. Readers/Writer Tokens) to 00871 * distinguish between Proxy types. For instance a Reader proxy 00872 * should return a different type value than a Writer proxy. The 00873 * default implementation returns 0. 00874 */ 00875 virtual int type (void) const; 00876 00877 protected: 00878 /// Duplication. 00879 ACE_Token_Proxy (const ACE_Token_Proxy &); 00880 00881 /// If this is set, we ignore deadlock. 00882 int ignore_deadlock_; 00883 00884 /// Print a bunch of debug messages. 00885 int debug_; 00886 00887 /// Reference to the actual logical token. Many ACE_Local_Mutex 00888 /// proxies can reference the same ACE_Mutex_Token. 00889 ACE_Tokens *token_; 00890 00891 /// Handles cond_var waits. 00892 int handle_options (ACE_Synch_Options &options, 00893 ACE_TOKEN_CONST::COND_VAR &cv); 00894 00895 /// Waiter info used for asynchronous transactions. 00896 ACE_TSS_TPQ_Entry waiter_; 00897 00898 /// Make the correct type of ACE_Tokens. This is called by the Token 00899 /// Manager. 00900 virtual ACE_Tokens *create_token (const ACE_TCHAR *name) = 0; 00901 }; 00902 00903 // 8.. 00904 /** 00905 * @class ACE_Null_Token 00906 * 00907 * @brief No op class for nonthreaded platform protocols. 00908 */ 00909 class ACE_Export ACE_Null_Token : public ACE_Token_Proxy 00910 { 00911 public: 00912 #if defined (ACE_LACKS_INLINE_FUNCTIONS) 00913 // @@ Hopefully, we can remove this ridicules ifdef when CE's compiler becomes more normal. 00914 /// Construction. 00915 ACE_Null_Token (void); 00916 00917 /// Destructor. 00918 ~ACE_Null_Token (void); 00919 #endif /* ACE_LACKS_INLINE_FUNCTION */ 00920 00921 /// Acquire. 00922 virtual int acquire (int /* notify */ = 0, 00923 void (* /* sleep_hook */ )(void *) = 0, 00924 ACE_Synch_Options & /* options */ = 00925 ACE_Synch_Options::defaults) { return 0; } 00926 00927 /// Renew. 00928 virtual int renew (int /* requeue_position */ = -1, 00929 ACE_Synch_Options & /* options */ = 00930 ACE_Synch_Options::defaults) { return 0; } 00931 00932 /// Try acquire. 00933 virtual int tryacquire (void (* /* sleep_hook */)(void *) = 0) { return 0; } 00934 00935 /// Release. 00936 virtual int release (ACE_Synch_Options & /* options */ = 00937 ACE_Synch_Options::defaults) { return 0; } 00938 00939 /// Remove. 00940 virtual int remove (ACE_Synch_Options & /* options */ = 00941 ACE_Synch_Options::defaults) { return 0; } 00942 00943 /// Return a dynamically allocated clone of the derived class. 00944 virtual ACE_Token_Proxy *clone (void) const { return new ACE_Null_Token; } 00945 00946 /// Dump the state of the class. 00947 void dump (void) const; 00948 00949 /// Do not allow the Token Manager to create us. 00950 virtual ACE_Tokens *create_token (const ACE_TCHAR *) { return 0; } 00951 }; 00952 00953 // 9.. 00954 /** 00955 * @class ACE_Local_Mutex 00956 * 00957 * @brief Class that acquires, renews, and releases a synchronization 00958 * token local to the process. 00959 * 00960 * This class is a more general-purpose synchronization mechanism 00961 * than SunOS 5.x mutexes. For example, it implements "recursive 00962 * mutex" semantics, where a thread that owns the token can 00963 * reacquire it without deadlocking. In addition, threads that 00964 * are blocked awaiting the token are serviced in strict FIFO 00965 * order as other threads release the token (SunOS 5.x mutexes 00966 * don't strictly enforce an acquisition order). Lastly, 00967 * ACE_Local_Mutex performs deadlock detection on acquire calls. 00968 * The interfaces for acquire, tryacquire, renew, release, 00969 * etc. are defined in ACE_Token_Proxy. The semantics for 00970 * ACE_Local_Mutex are that of a mutex. 00971 */ 00972 class ACE_Export ACE_Local_Mutex : public ACE_Token_Proxy 00973 { 00974 public: 00975 /** 00976 * Constructor. 00977 * @param token_name Uniquely id's the token. 00978 * @param ignore_deadlock Will allow deadlock to occur (useful for testing). 00979 * @param debug Prints a bunch of messages. 00980 */ 00981 ACE_Local_Mutex (const ACE_TCHAR *token_name = 0, 00982 int ignore_deadlock = 0, 00983 int debug = 0); 00984 00985 /// Destructor 00986 ~ACE_Local_Mutex (void); 00987 00988 /// Dump the state of the class. 00989 void dump (void) const; 00990 00991 /// Return deep copy. 00992 virtual ACE_Token_Proxy *clone (void) const; 00993 00994 protected: 00995 /// Return a new ACE_Local_Mutex. 00996 virtual ACE_Tokens *create_token (const ACE_TCHAR *name); 00997 }; 00998 00999 // *. 01000 /** 01001 * @class ACE_Local_RLock 01002 * 01003 * @brief Class that acquires, renews, and releases a readers lock that 01004 * is local to the process. 01005 * 01006 * This class implements the reader interface to canonical 01007 * readers/writer locks. Multiple readers can hold the lock 01008 * simultaneously when no writers have the lock. Alternatively, 01009 * when a writer holds the lock, no other participants (readers 01010 * or writers) may hold the lock. This class is a more 01011 * general-purpose synchronization mechanism than SunOS 5.x 01012 * RLocks. For example, it implements "recursive RLock" 01013 * semantics, where a thread that owns the token can reacquire it 01014 * without deadlocking. In addition, threads that are blocked 01015 * awaiting the token are serviced in strict FIFO order as other 01016 * threads release the token (SunOS 5.x RLockes don't strictly 01017 * enforce an acquisition order). 01018 * The interfaces for acquire, tryacquire, renew, release, 01019 * etc. are defined in ACE_Token_Proxy. The semantics for 01020 * ACE_Local_RLock are that of a readers/writers lock. Acquire 01021 * for this class implies a reader acquisition. That is, 01022 * multiple clients may acquire a lock for read only. 01023 */ 01024 class ACE_Export ACE_Local_RLock : public ACE_Token_Proxy 01025 { 01026 public: 01027 // = Initialization and termination. 01028 01029 /** 01030 * Constructor. 01031 * @param token_name Uniquely id's the token. 01032 * @param ignore_deadlock Will allow deadlock to occur (useful for testing). 01033 * @param debug Prints a bunch of messages. 01034 */ 01035 ACE_Local_RLock (const ACE_TCHAR *token_name = 0, 01036 int ignore_deadlock = 0, 01037 int debug = 0); 01038 01039 /// Destructor 01040 ~ACE_Local_RLock (void); 01041 01042 /// Dump the state of the class. 01043 void dump (void) const; 01044 01045 /// Returns ACE_RW_Token::RLOCK. 01046 virtual int type (void) const; 01047 01048 /// Return deep copy. 01049 virtual ACE_Token_Proxy *clone (void) const; 01050 01051 protected: 01052 /// Return a new ACE_Local_Mutex. 01053 virtual ACE_Tokens *create_token (const ACE_TCHAR *name); 01054 }; 01055 01056 // *. 01057 /** 01058 * @class ACE_Local_WLock 01059 * 01060 * @brief Class that acquires, renews, and releases a writer lock that 01061 * is local to the process. 01062 * 01063 * This class implements the writer interface to canonical 01064 * readers/writer locks. Multiple readers can hold the lock 01065 * simultaneously when no writers have the lock. Alternatively, 01066 * when a writer holds the lock, no other participants (readers 01067 * or writers) may hold the lock. This class is a more 01068 * general-purpose synchronization mechanism than SunOS 5.x 01069 * WLock. For example, it implements "recursive WLock" 01070 * semantics, where a thread that owns the token can reacquire it 01071 * without deadlocking. In addition, threads that are blocked 01072 * awaiting the token are serviced in strict FIFO order as other 01073 * threads release the token (SunOS 5.x WLocks don't strictly 01074 * enforce an acquisition order). 01075 * The interfaces for acquire, tryacquire, renew, release, 01076 * etc. are defined in ACE_Token_Proxy. The semantics for 01077 * ACE_Local_WLock are that of a readers/writers lock. Acquire 01078 * for this class implies a writer acquisition. That is, only 01079 * one client may hold the lock for writing. 01080 */ 01081 class ACE_Export ACE_Local_WLock : public ACE_Token_Proxy 01082 { 01083 public: 01084 // = Initialization and termination. 01085 01086 /** 01087 * Constructor. 01088 * @param token_name Uniquely id's the token. 01089 * @param ignore_deadlock Will allow deadlock to occur (useful for testing). 01090 * @param debug Prints a bunch of messages. 01091 */ 01092 ACE_Local_WLock (const ACE_TCHAR *token_name = 0, 01093 int ignore_deadlock = 0, 01094 int debug = 0); 01095 01096 /// Destructor 01097 ~ACE_Local_WLock (void); 01098 01099 /// Dump the state of the class. 01100 void dump (void) const; 01101 01102 /// Returns ACE_RW_Token::WLOCK. 01103 virtual int type (void) const; 01104 01105 /// Return deep copy. 01106 virtual ACE_Token_Proxy *clone (void) const; 01107 01108 protected: 01109 /// Return a new ACE_Local_Mutex. 01110 ACE_Tokens *create_token (const ACE_TCHAR *name); 01111 }; 01112 01113 ACE_END_VERSIONED_NAMESPACE_DECL 01114 01115 #endif /* ACE_HAS_TOKENS_LIBRARY */ 01116 01117 #if defined (__ACE_INLINE__) 01118 #include "ace/Local_Tokens.inl" 01119 #endif /* __ACE_INLINE__ */ 01120 #include /**/ "ace/post.h" 01121 #endif /* ACE_LOCAL_MUTEX_H */