3 //=============================================================================
7 * @author Karl-Heinz Dorn <kdorn@erlh.siemens.de>
8 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
9 * @author Tim Harrison <harrison@cs.wustl.edu>
11 * This file contains definitions for the following classes:
15 * 8. ACE_Null_Token : public ACE_Token_Proxy
16 * 9. ACE_Local_Mutex : public ACE_Token_Proxy
17 * *. ACE_Local_RLock : public ACE_Local_Mutex
18 * &. ACE_Local_WLock : public ACE_Local_Mutex
22 * b. ACE_TSS_TPQ_Entry
24 * 4. ACE_Token_Proxy_Queue
26 * 6. ACE_Mutex_Token : public ACE_Tokens
27 * 12. ACE_RW_Token : public ACE_Tokens
30 * Note that the locking classes defined in this file are *not*
31 * intended to be used as general-purpose synchronization
32 * mechanisms, such as mutexes or semaphores. Instead, you should
33 * use the ACE_Recursive_Thread_Mutex, ACE_Thread_Mutex,
34 * ACE_Thread_Semaphore, etc., that are defined in
35 * $ACE_ROOT/ace/Synch.h or the
36 * ACE_Token that's defined in $ACE_ROOT/ace/Token.h.
38 //=============================================================================
40 #ifndef ACE_LOCAL_MUTEX_H
41 #define ACE_LOCAL_MUTEX_H
42 #include /**/ "ace/pre.h"
44 #include /**/ "ace/config-all.h"
46 #if !defined (ACE_LACKS_PRAGMA_ONCE)
48 #endif /* ACE_LACKS_PRAGMA_ONCE */
50 #if defined (ACE_HAS_TOKENS_LIBRARY)
52 #include "ace/Synch_Traits.h"
53 #include "ace/Condition_Thread_Mutex.h"
54 #include "ace/TSS_T.h"
55 #include "ace/Containers.h"
56 #include "ace/Synch_Options.h"
57 #include "ace/Map_Manager.h"
58 #include "ace/Log_Category.h"
59 #include "ace/OS_NS_string.h"
60 #include "ace/os_include/os_netdb.h"
62 #if !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE))
63 # define ACE_NO_TSS_TOKENS 1
64 #endif /* !(defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)) */
66 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
70 * @class ACE_TOKEN_CONST
72 * @brief Not a public interface.
74 * Constant definitions and typedefs for Token library. Mostly,
75 * this class is necessary to fight the compiler with order of
78 // FUZZ: disable check_for_ACE_Guard
79 namespace ACE_TOKEN_CONST
81 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
82 // ACE platform supports some form of threading.
83 typedef ACE_Condition_Thread_Mutex COND_VAR
;
84 typedef ACE_Thread_Mutex MUTEX
;
85 typedef ACE_Guard
<ACE_Thread_Mutex
> GUARD
;
87 typedef ACE_Null_Condition COND_VAR
;
88 typedef ACE_Null_Mutex MUTEX
;
89 typedef ACE_Guard
<ACE_Null_Mutex
> GUARD
;
90 #endif /* ACE_HAS_THREADS */
92 // FUZZ: enable check_for_ACE_Guard
95 class ACE_Token_Proxy
;
99 * @class ACE_TPQ_Entry
101 * @brief Token Proxy Queue entry. Used in the ACE_Token_Proxy_Queue
103 * Not a public interface.
105 class ACE_Export ACE_TPQ_Entry
107 friend class ACE_Token_Manager
;
109 typedef void (*PTVF
) (void *);
111 /// Null constructor.
115 ACE_TPQ_Entry (const ACE_Token_Proxy
*proxy
,
116 const ACE_TCHAR
*client_id
);
118 /// Copy constructor.
119 ACE_TPQ_Entry (const ACE_TPQ_Entry
&rhs
);
124 /// Copy operator use by the queue.
125 void operator= (const ACE_TPQ_Entry
&rhs
);
127 /// Get top of the queue.
128 ACE_Token_Proxy
*proxy () const;
130 /// Set top of the queue.
131 void proxy (ACE_Token_Proxy
*);
133 /// Get nesting level of the entry.
134 int nesting_level () const;
136 /// Delta nesting level of the entry.
137 void nesting_level (int delta
);
139 /// Get client_id of the entry.
140 const ACE_TCHAR
*client_id () const;
142 /// Set client_id of the entry.
143 void client_id (const ACE_TCHAR
*);
145 /// Returns 1 if @a id == client id. Does not check for @a id == 0.
146 int equal_client_id (const ACE_TCHAR
*id
);
148 /// One method for arg and sleep_hook.
149 void set (void (*sleep_hook
)(void *));
151 /// Set sleep hook of the entry.
152 void sleep_hook (void (*sh
)(void *));
154 /// Get sleep hook of the entry.
155 PTVF
sleep_hook () const;
157 /// Call the sleep hook function or method passing arg.
158 void call_sleep_hook ();
160 /// Dump the state of the class.
163 // = Used to block the thread if an acquire fails with EWOULDBLOCK.
164 ACE_TOKEN_CONST::COND_VAR cond_var_
;
165 ACE_TOKEN_CONST::MUTEX lock_
;
167 /// Pointer to next in list.
168 ACE_TPQ_Entry
*next_
;
170 /// Get whether this client is blocked waiting for a token.
171 int waiting () const;
173 /// Set whether this client is blocked waiting for a token.
174 void waiting (int w
);
177 /// This client is waiting for a token.
181 ACE_Token_Proxy
*proxy_
;
190 ACE_TCHAR client_id_
[ACE_MAXCLIENTIDLEN
];
193 void (*sleep_hook_
)(void *);
197 #if defined (ACE_NO_TSS_TOKENS)
198 typedef ACE_TPQ_Entry ACE_TPQ_ENTRY
;
200 typedef ACE_TSS
<ACE_TPQ_Entry
> ACE_TPQ_ENTRY
;
201 #endif /* ACE_NO_TSS_TOKENS */
204 * @class ACE_TSS_TPQ_Entry
206 * @brief ACE_TSS_TPQ_Entry
208 * Not a public interface.
210 class ACE_Export ACE_TSS_TPQ_Entry
: public ACE_TPQ_ENTRY
213 /// These are passed to the constructor of ACE_TPQ_Entry in
215 ACE_TSS_TPQ_Entry (const ACE_Token_Proxy
*proxy
,
216 const ACE_TCHAR
*client_id
);
219 virtual ~ACE_TSS_TPQ_Entry () = default;
221 /// Allows us to pass args to the construction of the TSS object.
222 virtual ACE_TPQ_Entry
*make_TSS_TYPE () const;
224 /// Operator overloading and inheritance don't mix.
225 operator ACE_TPQ_Entry
*();
227 /// Dump the state of the class.
230 #if defined (ACE_NO_TSS_TOKENS)
231 ACE_TPQ_Entry
*operator-> ()
233 return (ACE_TPQ_Entry
*) this;
235 #endif /* ACE_NO_TSS_TOKENS */
238 ACE_TSS_TPQ_Entry (const ACE_TSS_TPQ_Entry
&) = delete;
239 void operator= (const ACE_TSS_TPQ_Entry
&) = delete;
241 // = These are passed to the constructor of ACE_TPQ_Entry in
245 const ACE_Token_Proxy
*proxy_
;
248 const ACE_TCHAR
*client_id_
;
251 class ACE_Token_Proxy_Queue
;
255 * @class ACE_TPQ_Iterator
257 * @brief Iterates through ACE_Token_Proxy_Queues.
259 * Not a public interface.
261 class ACE_Export ACE_TPQ_Iterator
265 ACE_TPQ_Iterator (ACE_Token_Proxy_Queue
&q
);
268 ~ACE_TPQ_Iterator () = default;
270 /// Pass back the @a next_item.
271 int next (ACE_TPQ_Entry
*&next_item
);
273 /// Returns 1 when all items have been seen, else 0.
276 /// Move forward by one element in the queue.
279 /// Dump the state of an object.
283 ACE_TPQ_Entry
*current_
;
288 * @class ACE_Token_Proxy_Queue
290 * @brief Token waiter list.
292 * Not a public interface.
293 * This queue holds all the token proxies waiting for ownership
294 * of a token. Along with the proxy reference, it also stores
295 * the nesting level, client id, and a magic cookie from the
296 * proxy. This queue stores the ACE_TPQ_Entries by pointer
297 * values. It DOES NOT make copies. Thus, the user is
298 * responsible to ensure that the TPQ's stick around. This is
299 * motivated by the need to reduce dynamic memory allocation.
301 class ACE_Export ACE_Token_Proxy_Queue
304 friend class ACE_TPQ_Iterator
;
307 ACE_Token_Proxy_Queue ();
310 ~ACE_Token_Proxy_Queue () = default;
313 * Enqueue a proxy, nesting level, client_id, and a magic cookie at
314 * the given position in the list. If the position is -1, we
315 * enqueue at the end of the list (I think).
317 void enqueue (ACE_TPQ_Entry
* new_entry
,
320 /// Top of the queue.
321 const ACE_TPQ_Entry
* head ();
323 // int member (const ACE_TCHAR *id);
324 // Is this id in the waiter list?
326 /// Remove the top waiter.
329 /// Remove the waiter whose proxy ref matches @a remove_me.
330 void remove (const ACE_TPQ_Entry
*remove_me
);
332 /// The number of waiters.
335 /// Dump the state of the class.
340 ACE_TPQ_Entry
*head_
;
343 ACE_TPQ_Entry
*tail_
;
353 * @brief Abstract representation of ACE tokens.
355 * Not a public interface.
356 * Currently, I don't see a reason for providing an abstract
357 * interface at this level of the library. As of yet, no one
358 * uses ACE_Tokens derivatives through this abstract interface
359 * except for ACE_Token_Manager. It only uses the statistical
360 * methods which are shared by all Tokens. For that reason, it
361 * still makes since to have a common base class. However,
362 * acquire, renew, and release do not need to have matching
363 * interfaces throughout all Tokens.
364 * To add a new type of token (e.g. semaphore), this class must
365 * be subtyped to define the new semantics. See
366 * ACE_Token_Manager for details.
368 class ACE_Export ACE_Tokens
371 /// Null constructor.
375 virtual ~ACE_Tokens () = default;
377 /// No implementation.
378 virtual int acquire (ACE_TPQ_Entry
*caller
,
382 /// No implementation.
383 virtual int tryacquire (ACE_TPQ_Entry
*caller
) = 0;
385 /// No implementation.
386 virtual int renew (ACE_TPQ_Entry
*caller
,
387 int requeue_position
) = 0;
389 /// No implementation.
390 virtual int release (ACE_TPQ_Entry
*caller
) = 0;
392 /// Move the caller to the front of the waiter list. This is for use
393 /// with remote mutexes and shadow mutexes.
394 void make_owner (ACE_TPQ_Entry
*caller
);
396 /// Remove the caller from the waiter list.
397 void remove (ACE_TPQ_Entry
*caller
);
399 // = Accessor methods.
402 typedef ACE_Unbounded_Stack
<ACE_TPQ_Entry
*> OWNER_STACK
;
404 /// Returns a stack of the current owners. Returns -1 on error, 0 on
405 /// success. If @a id is non-zero, returns 1 if id is an owner.
406 virtual int owners (OWNER_STACK
&o
, const ACE_TCHAR
*id
) = 0;
408 /// Returns 1 if @a id is waiting for this token. 0 otherwise.
409 virtual int is_waiting_for (const ACE_TCHAR
*id
) = 0;
411 /// Returns 1 if @a id is an owner of this token. 0 otherwise.
412 virtual int is_owner (const ACE_TCHAR
*id
) = 0;
414 /// Return the queue of waiters.
415 virtual ACE_Token_Proxy_Queue
*waiters ();
417 /// Return the number of proxies that are currently waiting to get
419 virtual int no_of_waiters ();
421 /// The current owner.
422 const ACE_TCHAR
*owner_id ();
425 const ACE_TCHAR
* name ();
427 // = Reference counting. These are only called by the
429 void inc_reference ();
430 int dec_reference ();
432 /// Dump the state of the class.
436 * These are the Token types supported by the library at ship time.
437 * There is no restriction on the number of Token types added by
438 * "3rd parties." These are only necessary for the Token Server.
440 enum TOKEN_TYPES
{ MUTEX
, RWLOCK
};
443 * Provides a manual RTTI mechanism. This method is used only by
444 * ACE_Token_Request so that the type of a token can be sent to a
445 * remote Token Server.
447 virtual int type () const = 0;
449 // = The following methods allow the deadlock detection algorithm to
450 // check if this token has been visited.
452 /// Mark or unmark the token as visited.
455 /// Check if the token has been visited.
458 /// All the data of the current owner.
459 ACE_TPQ_Entry
*owner ();
462 /// For the deadlock detection algorithm.
466 int reference_count_
;
468 /// List of client's owning and waiting the token.
469 ACE_Token_Proxy_Queue waiters_
;
472 ACE_TCHAR token_name_
[ACE_MAXTOKENNAMELEN
];
475 class ACE_Local_Mutex
;
479 * @class ACE_Mutex_Token
481 * @brief Class that acquires, renews, and releases a process-local
482 * synchronization token.
484 * Not a public interface.
485 * This class is a more general-purpose synchronization mechanism
486 * than SunOS 5.x mutexes. For example, it implements "recursive
487 * mutex" semantics, where a thread that owns the token can
488 * reacquire it without deadlocking. In addition, threads that
489 * are blocked awaiting the token are serviced in strict FIFO
490 * order as other threads release the token (SunOS 5.x mutexes
491 * don't strictly enforce an acquisition order).
493 class ACE_Export ACE_Mutex_Token
: public ACE_Tokens
497 explicit ACE_Mutex_Token (const ACE_TCHAR
* name
);
500 virtual ~ACE_Mutex_Token ();
502 // = Synchronization operations.
503 // With acquire, renew, and release, the caller must be specified so
504 // that multiple proxies (e.g. ACE_Local_Mutex) can use the same
508 * Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as
509 * the reason. If errnum == EWOULDBLOCK, and notify == 1,
510 * <ACE_Token_Proxy::sleep_hook> has been called on the current
511 * owner of the token. If ignore_deadlock is passed as 1 and errnum
512 * == EDEADLK, then deadlock was detected via ace_token_manager.
514 virtual int acquire (ACE_TPQ_Entry
*caller
,
518 /// Same as acquire, but fails if would block
519 virtual int tryacquire (ACE_TPQ_Entry
*caller
);
522 * An optimized method that efficiently reacquires the token if no
523 * other threads are waiting. This is useful for situations where
524 * you don't want to degrade the quality of service if there are
525 * other threads waiting to get the token. If <requeue_position> ==
526 * -1 and there are other threads waiting to obtain the token we are
527 * queued at the end of the list of waiters. If <requeue_position>
528 * > -1 then it indicates how many entries to skip over before
529 * inserting our thread into the list of waiters (e.g.,
530 * <requeue_position> == 0 means "insert at front of the queue").
531 * Renew has the rather odd semantics such that if there are other
532 * waiting threads it will give up the token even if the
533 * nesting_level_ > 1. I'm not sure if this is really the right
534 * thing to do (since it makes it possible for shared data to be
535 * changed unexpectedly) so use with caution... Returns 0 on
536 * success, -1 on failure with <ACE_Log_Msg::errnum> as the reason.
537 * If errnum == EWOULDBLOCK, and notify == 1,
538 * <ACE_Token_Proxy::sleep_hook> has been called on the current
539 * owner of the token.
541 virtual int renew (ACE_TPQ_Entry
*caller
,
542 int requeue_position
);
545 * Relinquish the token. If there are any waiters then the next one
546 * in line gets it. If the caller is not the owner, caller is
547 * removed from the waiter list.
549 virtual int release (ACE_TPQ_Entry
*caller
);
551 /// Dump the state of the class.
554 /// Returns ACE_Tokens::MUTEX.
555 virtual int type () const;
557 /// Returns a stack of the current owners. Returns -1 on error, 0 on
558 /// success. If @a id is non-zero, returns 1 if id is an owner.
559 virtual int owners (OWNER_STACK
&o
, const ACE_TCHAR
*id
);
561 /// Returns 1 if @a id is waiting for this token. 0 otherwise.
562 virtual int is_waiting_for (const ACE_TCHAR
*id
);
564 /// Returns 1 if @a id is an owner of this token. 0 otherwise.
565 virtual int is_owner (const ACE_TCHAR
*id
);
568 /// ACE_Mutex_Token used to lock internal data structures.
569 ACE_TOKEN_CONST::MUTEX lock_
;
574 * @class ACE_RW_Token
576 * @brief Class that acquires, renews, and releases a process-local
577 * synchronization token.
579 * Not a public interface.
580 * This class is a more general-purpose synchronization mechanism
581 * than SunOS 5.x mutexes. For example, it implements "recursive
582 * mutex" semantics, where a thread that owns the token can
583 * reacquire it without deadlocking. In addition, threads that are
584 * blocked awaiting the token are serviced in strict FIFO order as
585 * other threads release the token (SunOS 5.x mutexes don't strictly
586 * enforce an acquisition order).
588 class ACE_Export ACE_RW_Token
: public ACE_Tokens
592 explicit ACE_RW_Token (const ACE_TCHAR
* name
);
595 virtual ~ACE_RW_Token ();
597 // = Synchronization operations.
598 // With acquire, renew, and release, the caller must be specified so
599 // that multiple proxies (e.g. ACE_Local_Mutex) can use the same
603 * Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as
604 * the reason. If errnum == EWOULDBLOCK, and notify == 1,
605 * <ACE_Token_Proxy::sleep_hook> has been called on the current
606 * owner of the token. If @a ignore_deadlock is passed as 1 and errnum
607 * == EDEADLK, then deadlock was detected via ACE_Token_Manager.
609 virtual int acquire (ACE_TPQ_Entry
*caller
,
613 /// Same as acquire except fails on would block
614 virtual int tryacquire (ACE_TPQ_Entry
*caller
);
617 * An optimized method that efficiently reacquires the token if no
618 * other threads are waiting. This is useful for situations where
619 * you don't want to degrade the quality of service if there are
620 * other threads waiting to get the token. If <requeue_position> ==
621 * -1 and there are other threads waiting to obtain the token we are
622 * queued at the end of the list of waiters. If <requeue_position>
623 * > -1 then it indicates how many entries to skip over before
624 * inserting our thread into the list of waiters (e.g.,
625 * <requeue_position> == 0 means "insert at front of the queue").
626 * Renew has the rather odd semantics such that if there are other
627 * waiting threads it will give up the token even if the
628 * nesting_level_ > 1. I'm not sure if this is really the right
629 * thing to do (since it makes it possible for shared data to be
630 * changed unexpectedly) so use with caution... Returns 0 on
631 * success, -1 on failure with <ACE_Log_Msg::errnum> as the reason.
632 * If errnum == EWOULDBLOCK, and notify == 1,
633 * <ACE_Token_Proxy::sleep_hook> has been called on the current
634 * owner of the token.
636 virtual int renew (ACE_TPQ_Entry
*caller
,
637 int requeue_position
);
640 * Relinquish the token. If there are any waiters then the next one
641 * in line gets it. If the caller is not the owner, caller is
642 * removed from the waiter list.
644 virtual int release (ACE_TPQ_Entry
*caller
);
646 /// Dump the state of the class.
649 /// These are the types that proxies can be.
650 enum PROXY_TYPE
{ READER
, WRITER
};
652 /// Returns READER or WRITER.
653 virtual int type () const;
655 /// Returns a stack of the current owners. Returns -1 on error, 0 on
656 /// success. If @a id is non-zero, returns 1 if id is an owner.
657 virtual int owners (OWNER_STACK
&o
, const ACE_TCHAR
*id
);
659 /// Returns 1 if @a id is waiting for this token. 0 otherwise.
660 virtual int is_waiting_for (const ACE_TCHAR
*id
);
662 /// Returns 1 if @a id is an owner of this token. 0 otherwise.
663 virtual int is_owner (const ACE_TCHAR
*id
);
666 /// The number of waiting writers.
669 /// ACE_Mutex_Token used to lock internal data structures.
670 ACE_TOKEN_CONST::MUTEX lock_
;
672 /// Sets the new owner.
673 void notify_new_owner (ACE_TPQ_Entry
*caller
);
678 * @class ACE_Token_Name
680 * @brief Allows Token_Manger to identify tokens.
682 * For now, this is just a string. We need a string class
683 * anyway to use in ACE_Map_Manager. Having this class
684 * (instead of <ACE_SString>) allows us to easily change if
685 * needed. For instance, we may choose to identify tokens by
686 * name and *type* in the future.
688 class ACE_Export ACE_Token_Name
692 ACE_Token_Name (const ACE_TCHAR
*token_name
= 0);
694 /// Copy construction.
695 ACE_Token_Name (const ACE_Token_Name
&rhs
);
698 virtual ~ACE_Token_Name ();
701 void operator= (const ACE_Token_Name
&rhs
);
704 bool operator== (const ACE_Token_Name
&rhs
) const;
706 /// Get the token name.
707 const ACE_TCHAR
*name () const;
709 /// Set the token name.
710 void name (const ACE_TCHAR
*new_name
);
712 /// Dump the state of the class.
716 /// Name of the token.
717 ACE_TCHAR token_name_
[ACE_MAXTOKENNAMELEN
];
722 * @class ACE_Token_Proxy
724 * @brief Abstract representation of ACE tokens.
726 * Interface for all Tokens in ACE. This class implements the
727 * synchronization needed for tokens (condition variables etc.)
728 * The algorithms for the operations (acquire, release, etc.)
729 * operate on the generic ACE_Tokens interface. Thus, the _type_
730 * of token (mutex, rwlock) can be set at construction of
731 * ACE_Token_Proxy. You can use all Tokens in ACE through the
732 * ACE_Token_Proxy by passing the proper values at construction.
733 * Alternatively, there are class definitions which "know" how to
734 * do this (ACE_Local_Mutex, ACE_Local_RLock, ACE_Local_WLock).
735 * To add a new type of token (e.g. semaphore), this class is not
736 * changed. See ACE_Token_Manager for details.
737 * Tokens (e.g. ACE_Mutex_Token) assume that it can always call
738 * <ACE_Token_Proxy::token_acquired> on a new token owner. This
739 * is not a problem for synchronous use of token proxies (that is,
740 * when acquires block until successful.) However, for
741 * implementations of the Token Server, which may use asynch
742 * operations, the proxy can not go away after an acquire until
743 * the token is acquired. This is not really a problem, but
744 * should be understood.
746 class ACE_Export ACE_Token_Proxy
749 friend class ACE_Token_Manager
;
750 friend class ACE_Token_Invariant_Manager
; // For testing.
752 // Initialization and termination methods.
757 virtual ~ACE_Token_Proxy ();
760 * Open the <ACE_Token>.
761 * @param name The string uniquely identifying the token.
762 * @param ignore_deadlock Can be 1 to disable deadlock notifications.
763 * @param debug Prints debug messages.
765 virtual int open (const ACE_TCHAR
*name
,
766 int ignore_deadlock
= 0,
769 // = The following methods have implementations which are
770 // independent of the token semantics (mutex, rwlock, etc.) They
771 // forward operations to the underlying token and perform the
772 // necessary blocking semantics for operations (condition variables
773 // etc.) This allows reuse of the blocking code as well as having
774 // multiple proxies to the same token.
776 /// Calls acquire on the token. Blocks the calling thread if would
778 virtual int acquire (int notify
= 0,
779 void (*sleep_hook
)(void *) = 0,
780 ACE_Synch_Options
&options
=
781 ACE_Synch_Options::defaults
);
783 /// Calls renew on the token. Blocks the calling thread if would block.
784 virtual int renew (int requeue_position
= -1,
785 ACE_Synch_Options
&options
=
786 ACE_Synch_Options::defaults
);
788 /// Calls renew on the token.
789 virtual int tryacquire (void (*sleep_hook
)(void *) = 0);
791 /// Calls release on the token.
792 virtual int release (ACE_Synch_Options
&options
=
793 ACE_Synch_Options::defaults
);
795 /// Calls remove on the token.
796 virtual int remove (ACE_Synch_Options
&options
=
797 ACE_Synch_Options::defaults
);
799 /// Since the locking mechanism doesn't support read locks then this
800 /// just calls <acquire>.
801 virtual int acquire_read (int notify
= 0,
802 void (*sleep_hook
)(void *) = 0,
803 ACE_Synch_Options
&options
=
804 ACE_Synch_Options::defaults
);
806 /// Since the locking mechanism doesn't support write locks then this
807 /// just calls <acquire>.
808 virtual int acquire_write (int notify
= 0,
809 void (*sleep_hook
)(void *) = 0,
810 ACE_Synch_Options
&options
=
811 ACE_Synch_Options::defaults
);
813 /// Since the locking mechanism doesn't support read locks then this
814 /// just calls <tryacquire>.
815 virtual int tryacquire_read (void (*sleep_hook
)(void *) = 0);
817 /// Since the locking mechanism doesn't support write locks then this
818 /// just calls <tryacquire>.
819 virtual int tryacquire_write (void (*sleep_hook
)(void *) = 0);
821 // = Utility methods.
823 /// Get the client id of the proxy. This is implemented as
824 /// thread-specific data.
825 virtual const ACE_TCHAR
*client_id () const;
828 * Set the client_id for the calling thread. I strongly recommend
829 * that this not be used unless you really know what you're doing.
830 * I use this in the Token Server, and it caused many headaches.
832 virtual void client_id (const ACE_TCHAR
*client_id
);
835 * Return the name of the token. This is important for use within
836 * the token servers (local and remote) as well as with token
837 * collections. So, all derivations of ACE_Token_Proxy must be able to
838 * stringify some name. The name must uniquely identify a token.
839 * So, for instance, the token within the reactor should probably be
840 * called "Reactor Token."
842 virtual const ACE_TCHAR
*name () const;
845 * This should really be called <someone_waiting>. This is called
846 * by ACE_Token_xx's when another proxy enters the waiting list and
847 * requests that the current token holder be notified.
849 virtual void sleep_hook ();
851 /// This is called when a queued (waiting) proxy is removed from the
852 /// waiters list and given the token.
853 virtual void token_acquired (ACE_TPQ_Entry
*);
855 /// The client id of the current token holder
856 virtual const ACE_TCHAR
*owner_id ();
858 /// Return a dynamically allocated clone of the derived class.
859 virtual ACE_Token_Proxy
*clone () const = 0;
861 /// Dump the state of the class.
865 * This method can be used be Tokens (e.g. Readers/Writer Tokens) to
866 * distinguish between Proxy types. For instance a Reader proxy
867 * should return a different type value than a Writer proxy. The
868 * default implementation returns 0.
870 virtual int type () const;
874 ACE_Token_Proxy (const ACE_Token_Proxy
&);
876 /// If this is set, we ignore deadlock.
877 int ignore_deadlock_
;
879 /// Print a bunch of debug messages.
882 /// Reference to the actual logical token. Many ACE_Local_Mutex
883 /// proxies can reference the same ACE_Mutex_Token.
886 /// Handles cond_var waits.
887 int handle_options (ACE_Synch_Options
&options
,
888 ACE_TOKEN_CONST::COND_VAR
&cv
);
890 /// Waiter info used for asynchronous transactions.
891 ACE_TSS_TPQ_Entry waiter_
;
893 /// Make the correct type of ACE_Tokens. This is called by the Token
895 virtual ACE_Tokens
*create_token (const ACE_TCHAR
*name
) = 0;
900 * @class ACE_Null_Token
902 * @brief No op class for nonthreaded platform protocols.
904 class ACE_Export ACE_Null_Token
: public ACE_Token_Proxy
908 ACE_Null_Token () = default;
911 ~ACE_Null_Token () = default;
914 virtual int acquire (int /* notify */ = 0,
915 void (* /* sleep_hook */ )(void *) = 0,
916 ACE_Synch_Options
& /* options */ =
917 ACE_Synch_Options::defaults
) { return 0; }
920 virtual int renew (int /* requeue_position */ = -1,
921 ACE_Synch_Options
& /* options */ =
922 ACE_Synch_Options::defaults
) { return 0; }
925 virtual int tryacquire (void (* /* sleep_hook */)(void *) = 0) { return 0; }
928 virtual int release (ACE_Synch_Options
& /* options */ =
929 ACE_Synch_Options::defaults
) { return 0; }
932 virtual int remove (ACE_Synch_Options
& /* options */ =
933 ACE_Synch_Options::defaults
) { return 0; }
935 /// Return a dynamically allocated clone of the derived class.
936 virtual ACE_Token_Proxy
*clone () const { return new ACE_Null_Token
; }
938 /// Dump the state of the class.
941 /// Do not allow the Token Manager to create us.
942 virtual ACE_Tokens
*create_token (const ACE_TCHAR
*) { return 0; }
947 * @class ACE_Local_Mutex
949 * @brief Class that acquires, renews, and releases a synchronization
950 * token local to the process.
952 * This class is a more general-purpose synchronization mechanism
953 * than SunOS 5.x mutexes. For example, it implements "recursive
954 * mutex" semantics, where a thread that owns the token can
955 * reacquire it without deadlocking. In addition, threads that
956 * are blocked awaiting the token are serviced in strict FIFO
957 * order as other threads release the token (SunOS 5.x mutexes
958 * don't strictly enforce an acquisition order). Lastly,
959 * ACE_Local_Mutex performs deadlock detection on acquire calls.
960 * The interfaces for acquire, tryacquire, renew, release,
961 * etc. are defined in ACE_Token_Proxy. The semantics for
962 * ACE_Local_Mutex are that of a mutex.
964 class ACE_Export ACE_Local_Mutex
: public ACE_Token_Proxy
969 * @param token_name Uniquely id's the token.
970 * @param ignore_deadlock Will allow deadlock to occur (useful for testing).
971 * @param debug Prints a bunch of messages.
973 ACE_Local_Mutex (const ACE_TCHAR
*token_name
= 0,
974 int ignore_deadlock
= 0,
980 /// Dump the state of the class.
983 /// Return deep copy.
984 virtual ACE_Token_Proxy
*clone () const;
987 /// Return a new ACE_Local_Mutex.
988 virtual ACE_Tokens
*create_token (const ACE_TCHAR
*name
);
993 * @class ACE_Local_RLock
995 * @brief Class that acquires, renews, and releases a readers lock that
996 * is local to the process.
998 * This class implements the reader interface to canonical
999 * readers/writer locks. Multiple readers can hold the lock
1000 * simultaneously when no writers have the lock. Alternatively,
1001 * when a writer holds the lock, no other participants (readers
1002 * or writers) may hold the lock. This class is a more
1003 * general-purpose synchronization mechanism than SunOS 5.x
1004 * RLocks. For example, it implements "recursive RLock"
1005 * semantics, where a thread that owns the token can reacquire it
1006 * without deadlocking. In addition, threads that are blocked
1007 * awaiting the token are serviced in strict FIFO order as other
1008 * threads release the token (SunOS 5.x RLockes don't strictly
1009 * enforce an acquisition order).
1010 * The interfaces for acquire, tryacquire, renew, release,
1011 * etc. are defined in ACE_Token_Proxy. The semantics for
1012 * ACE_Local_RLock are that of a readers/writers lock. Acquire
1013 * for this class implies a reader acquisition. That is,
1014 * multiple clients may acquire a lock for read only.
1016 class ACE_Export ACE_Local_RLock
: public ACE_Token_Proxy
1021 * @param token_name Uniquely id's the token.
1022 * @param ignore_deadlock Will allow deadlock to occur (useful for testing).
1023 * @param debug Prints a bunch of messages.
1025 ACE_Local_RLock (const ACE_TCHAR
*token_name
= 0,
1026 int ignore_deadlock
= 0,
1030 ~ACE_Local_RLock ();
1032 /// Dump the state of the class.
1035 /// Returns ACE_RW_Token::RLOCK.
1036 virtual int type () const;
1038 /// Return deep copy.
1039 virtual ACE_Token_Proxy
*clone () const;
1042 /// Return a new ACE_Local_Mutex.
1043 virtual ACE_Tokens
*create_token (const ACE_TCHAR
*name
);
1048 * @class ACE_Local_WLock
1050 * @brief Class that acquires, renews, and releases a writer lock that
1051 * is local to the process.
1053 * This class implements the writer interface to canonical
1054 * readers/writer locks. Multiple readers can hold the lock
1055 * simultaneously when no writers have the lock. Alternatively,
1056 * when a writer holds the lock, no other participants (readers
1057 * or writers) may hold the lock. This class is a more
1058 * general-purpose synchronization mechanism than SunOS 5.x
1059 * WLock. For example, it implements "recursive WLock"
1060 * semantics, where a thread that owns the token can reacquire it
1061 * without deadlocking. In addition, threads that are blocked
1062 * awaiting the token are serviced in strict FIFO order as other
1063 * threads release the token (SunOS 5.x WLocks don't strictly
1064 * enforce an acquisition order).
1065 * The interfaces for acquire, tryacquire, renew, release,
1066 * etc. are defined in ACE_Token_Proxy. The semantics for
1067 * ACE_Local_WLock are that of a readers/writers lock. Acquire
1068 * for this class implies a writer acquisition. That is, only
1069 * one client may hold the lock for writing.
1071 class ACE_Export ACE_Local_WLock
: public ACE_Token_Proxy
1076 * @param token_name Uniquely id's the token.
1077 * @param ignore_deadlock Will allow deadlock to occur (useful for testing).
1078 * @param debug Prints a bunch of messages.
1080 ACE_Local_WLock (const ACE_TCHAR
*token_name
= 0,
1081 int ignore_deadlock
= 0,
1085 ~ACE_Local_WLock ();
1087 /// Dump the state of the class.
1090 /// Returns ACE_RW_Token::WLOCK.
1091 virtual int type () const;
1093 /// Return deep copy.
1094 virtual ACE_Token_Proxy
*clone () const;
1097 /// Return a new ACE_Local_Mutex.
1098 ACE_Tokens
*create_token (const ACE_TCHAR
*name
);
1101 ACE_END_VERSIONED_NAMESPACE_DECL
1103 #endif /* ACE_HAS_TOKENS_LIBRARY */
1105 #if defined (__ACE_INLINE__)
1106 #include "ace/Local_Tokens.inl"
1107 #endif /* __ACE_INLINE__ */
1108 #include /**/ "ace/post.h"
1109 #endif /* ACE_LOCAL_MUTEX_H */