ACE_Token Class Reference

Class that acquires, renews, and releases a synchronization token that is serviced in strict FIFO/LIFO ordering and that also supports (1) recursion and (2) readers/writer semantics. More...

#include <Token.h>

Collaboration diagram for ACE_Token:

Collaboration graph
[legend]
List of all members.

Public Types

enum  QUEUEING_STRATEGY { FIFO = -1, LIFO = 0 }

Public Member Functions

 ACE_Token (const ACE_TCHAR *name=0, void *=0)
 Constructor.

virtual ~ACE_Token (void)
 Destructor.

int queueing_strategy (void)
 Retrieve the current queueing strategy.

void queueing_strategy (int queueing_strategy)
 Set the queueing strategy.

int acquire (void(*sleep_hook)(void *), void *arg=0, ACE_Time_Value *timeout=0)
int acquire (ACE_Time_Value *timeout=0)
virtual void sleep_hook (void)
int renew (int requeue_position=0, ACE_Time_Value *timeout=0)
int tryacquire (void)
int remove (void)
 Shuts down the ACE_Token instance.

int release (void)
int acquire_read (void)
int acquire_read (void(*sleep_hook)(void *), void *arg=0, ACE_Time_Value *timeout=0)
int acquire_write (void)
 Calls acquire().

int acquire_write (void(*sleep_hook)(void *), void *arg=0, ACE_Time_Value *timeout=0)
 Calls acquire().

int tryacquire_read (void)
 Lower priority try_acquire().

int tryacquire_write (void)
 Just calls .

int tryacquire_write_upgrade (void)
 Assumes the caller has acquired the token and returns 0.

int waiters (void)
ACE_thread_t current_owner (void)
 Return the id of the current thread that owns the token.

void dump (void) const
 Dump the state of an object.


Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks.


Private Types

enum  ACE_Token_Op_Type { READ_TOKEN = 1, WRITE_TOKEN }

Private Member Functions

int shared_acquire (void(*sleep_hook_func)(void *), void *arg, ACE_Time_Value *timeout, ACE_Token_Op_Type op_type)
 Implements the and methods above.

void wakeup_next_waiter (void)
 Wake next in line for ownership.


Private Attributes

ACE_Token_Queue writers_
 A queue of writer threads.

ACE_Token_Queue readers_
 A queue of reader threads.

ACE_Thread_Mutex lock_
 ACE_Thread_Mutex used to lock internal data structures.

ACE_thread_t owner_
 Current owner of the token.

int in_use_
int waiters_
 Number of waiters.

int nesting_level_
 Current nesting level.

ACE_Condition_Attributes attributes_
 The attributes for the condition variables, optimizes lock time.

int queueing_strategy_
 Queueing strategy, LIFO/FIFO.


Detailed Description

Class that acquires, renews, and releases a synchronization token that is serviced in strict FIFO/LIFO ordering and that also supports (1) recursion and (2) readers/writer semantics.

This class is a more general-purpose synchronization mechanism than many native OS mutexes. For example, it implements "recursive mutex" semantics, where a thread that owns the token can reacquire it without deadlocking. If the same thread calls multiple times, however, it must call an equal number of times before the token is actually released. Threads that are blocked awaiting the token are serviced in strict FIFO/LIFO order as other threads release the token (Solaris and Pthread mutexes don't strictly enforce an acquisition order). There are two lists within the class. Write acquires always have higher priority over read acquires. Which means, if you use both write/read operations, care must be taken to avoid starvation on the readers. Notice that the read/write acquire operations do not have the usual semantic of reader/writer locks. Only one reader can acquire the token at a time (which is different from the usual reader/writer locks where several readers can acquire a lock at the same time as long as there is no writer waiting for the lock). We choose the names to (1) borrow the semantic to give writers higher priority and (2) support a common interface for all locking classes in ACE.

Definition at line 76 of file Token.h.


Member Enumeration Documentation

enum ACE_Token::ACE_Token_Op_Type [private]
 

Enumeration values:
READ_TOKEN 
WRITE_TOKEN 

Definition at line 257 of file Token.h.

00258   {
00259     READ_TOKEN = 1,
00260     WRITE_TOKEN
00261   };

enum ACE_Token::QUEUEING_STRATEGY
 

Available queueing strategies.

Enumeration values:
FIFO  FIFO, First In, First Out.
LIFO  LIFO, Last In, First Out.

Definition at line 83 of file Token.h.

00084   {
00085     /// FIFO, First In, First Out.
00086     FIFO = -1,
00087     /// LIFO, Last In, First Out
00088     LIFO = 0
00089   };


Constructor & Destructor Documentation

ACE_Token::ACE_Token const ACE_TCHAR name = 0,
void *  = 0
 

Constructor.

Definition at line 166 of file Token.cpp.

References ACE_TCHAR, FIFO, and queueing_strategy_.

00167   : lock_ (name, (ACE_mutexattr_t *) any),
00168     owner_ (ACE_OS::NULL_thread),
00169     in_use_ (0),
00170     waiters_ (0),
00171     nesting_level_ (0),
00172     attributes_ (USYNC_THREAD),
00173     queueing_strategy_ (FIFO)
00174 {
00175 //  ACE_TRACE ("ACE_Token::ACE_Token");
00176 }

ACE_Token::~ACE_Token void   )  [virtual]
 

Destructor.

Definition at line 178 of file Token.cpp.

References ACE_TRACE.

00179 {
00180   ACE_TRACE ("ACE_Token::~ACE_Token");
00181 }


Member Function Documentation

int ACE_Token::acquire ACE_Time_Value timeout = 0  ) 
 

This behaves just like the previous method, except that it invokes the virtual function called that can be overridden by a subclass of ACE_Token.

Definition at line 338 of file Token.cpp.

References ACE_TRACE, shared_acquire(), and WRITE_TOKEN.

00339 {
00340   ACE_TRACE ("ACE_Token::acquire");
00341   return this->shared_acquire (0, 0, timeout, ACE_Token::WRITE_TOKEN);
00342 }

int ACE_Token::acquire void(*  sleep_hook)(void *),
void *  arg = 0,
ACE_Time_Value timeout = 0
 

Acquire the token, sleeping until it is obtained or until the expiration of , which is treated as "absolute" time. If some other thread currently holds the token then is called before our thread goes to sleep. This can be used by the requesting thread to unblock a token-holder that is sleeping, e.g., by means of writing to a pipe (the ACE ACE_Reactor uses this functionality). Return values: 0 if acquires without calling 1 if is called. 2 if the token is signaled. -1 if failure or timeout occurs (if timeout occurs errno == ETIME) If == <&ACE_Time_Value::zero> then acquire has polling semantics (and does *not* call ).

Definition at line 348 of file Token.cpp.

References ACE_TRACE, shared_acquire(), and WRITE_TOKEN.

00351 {
00352   ACE_TRACE ("ACE_Token::acquire");
00353   return this->shared_acquire (sleep_hook_func, arg, timeout, ACE_Token::WRITE_TOKEN);
00354 }

ACE_INLINE int ACE_Token::acquire_read void(*  sleep_hook)(void *),
void *  arg = 0,
ACE_Time_Value timeout = 0
 

Behaves like acquire() but at a lower priority. It should probably be called acquire_yield() since the semantics aren't really what's commonly expected for readers/writer locks. See the class documentation above for more details.

Definition at line 86 of file Token.inl.

References ACE_TRACE, READ_TOKEN, and shared_acquire().

00089 {
00090   ACE_TRACE ("ACE_Token::acquire_read");
00091   return this->shared_acquire (sleep_hook_func, arg, timeout, ACE_Token::READ_TOKEN);
00092 }

ACE_INLINE int ACE_Token::acquire_read void   ) 
 

Behaves like acquire() but at a lower priority. It should probably be called acquire_yield() since the semantics aren't really what's commonly expected for readers/writer locks. See the class documentation above for more details.

Definition at line 62 of file Token.inl.

References ACE_TRACE, READ_TOKEN, and shared_acquire().

00063 {
00064   ACE_TRACE ("ACE_Token::acquire_read");
00065   return this->shared_acquire
00066     (0, 0, 0, ACE_Token::READ_TOKEN);
00067 }

ACE_INLINE int ACE_Token::acquire_write void(*  sleep_hook)(void *),
void *  arg = 0,
ACE_Time_Value timeout = 0
 

Calls acquire().

Definition at line 110 of file Token.inl.

References ACE_TRACE, shared_acquire(), and WRITE_TOKEN.

00113 {
00114   ACE_TRACE ("ACE_Token::acquire_write");
00115   return this->shared_acquire (sleep_hook_func, arg, timeout, ACE_Token::WRITE_TOKEN);
00116 }

ACE_INLINE int ACE_Token::acquire_write void   ) 
 

Calls acquire().

Definition at line 70 of file Token.inl.

References ACE_TRACE, shared_acquire(), and WRITE_TOKEN.

00071 {
00072   ACE_TRACE ("ACE_Token::acquire_write");
00073   return this->shared_acquire
00074     (0, 0, 0, ACE_Token::WRITE_TOKEN);
00075 }

ACE_INLINE ACE_thread_t ACE_Token::current_owner void   ) 
 

Return the id of the current thread that owns the token.

Definition at line 53 of file Token.inl.

References ACE_GUARD_RETURN, and ACE_TRACE.

00054 {
00055   ACE_TRACE ("ACE_Token::current_owner");
00056   ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, this->owner_);
00057 
00058   return this->owner_;
00059 }

ACE_BEGIN_VERSIONED_NAMESPACE_DECL void ACE_Token::dump void   )  const
 

Dump the state of an object.

Definition at line 26 of file Token.cpp.

References ACE_BEGIN_DUMP, ACE_DEBUG, ACE_END_DUMP, ACE_LIB_TEXT, ACE_TRACE, and LM_DEBUG.

Referenced by release(), renew(), and shared_acquire().

00027 {
00028 #if defined (ACE_HAS_DUMP)
00029   ACE_TRACE ("ACE_Token::dump");
00030 
00031   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00032 
00033   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nthread = %d"), ACE_Thread::self ()));
00034   // @@ Is there a portable way to do this?
00035   // ACE_DEBUG ((LM_DEBUG, "\nowner_ = %d", (long) this->owner_));
00036   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nowner_ addr = %x"), &this->owner_));
00037   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nwaiters_ = %d"), this->waiters_));
00038   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nin_use_ = %d"), this->in_use_));
00039   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nnesting level = %d"), this->nesting_level_));
00040   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00041 #endif /* ACE_HAS_DUMP */
00042 }

ACE_INLINE void ACE_Token::queueing_strategy int  queueing_strategy  ) 
 

Set the queueing strategy.

Definition at line 21 of file Token.inl.

References queueing_strategy_.

00022 {
00023   this->queueing_strategy_ = queueing_strategy == -1 ? -1 : 0;
00024 }

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE int ACE_Token::queueing_strategy void   ) 
 

Retrieve the current queueing strategy.

Definition at line 15 of file Token.inl.

References queueing_strategy_.

00016 {
00017   return this->queueing_strategy_;
00018 }

int ACE_Token::release void   ) 
 

Relinquish the token. If there are any waiters then the next one in line gets it.

Definition at line 483 of file Token.cpp.

References ACE_GUARD_RETURN, ACE_TRACE, dump(), and wakeup_next_waiter().

00484 {
00485   ACE_TRACE ("ACE_Token::release");
00486   ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
00487 
00488   // ACE_ASSERT (ACE_OS::thr_equal (ACE_Thread::self (), this->owner_));
00489 
00490 #if defined (DEBUGGING)
00491   this->dump ();
00492 #endif /* DEBUGGING */
00493 
00494   // Nested release...
00495   if (this->nesting_level_ > 0)
00496     --this->nesting_level_;
00497   else
00498     {
00499       //
00500       // Regular release...
00501       //
00502 
00503       // Wakeup waiter.
00504       this->wakeup_next_waiter ();
00505     }
00506 
00507   return 0;
00508 }

ACE_INLINE int ACE_Token::remove void   ) 
 

Shuts down the ACE_Token instance.

Definition at line 27 of file Token.inl.

References ACE_NOTSUP_RETURN, and ACE_TRACE.

00028 {
00029   ACE_TRACE ("ACE_Token::remove");
00030   // Don't have an implementation for this yet...
00031   ACE_NOTSUP_RETURN (-1);
00032 }

int ACE_Token::renew int  requeue_position = 0,
ACE_Time_Value timeout = 0
 

An optimized method that efficiently reacquires the token if no other threads are waiting. This is useful for situations where you don't want to degrade the quality of service if there are other threads waiting to get the token. If == -1 and there are other threads waiting to obtain the token we are queued according to the queueing strategy. If > -1 then it indicates how many entries to skip over before inserting our thread into the list of waiters (e.g., == 0 means "insert at front of the queue"). Renew has the rather odd semantics such that if there are other waiting threads it will give up the token even if the nesting_level_ > 1. I'm not sure if this is really the right thing to do (since it makes it possible for shared data to be changed unexpectedly) so use with caution... This method maintians the original token priority. As in , the value is an absolute time.

Definition at line 359 of file Token.cpp.

References ACE_ASSERT, ACE_GUARD_RETURN, ACE_TRACE, dump(), ETIME, ACE_Token::ACE_Token_Queue::head_, ACE_Token::ACE_Token_Queue::insert_entry(), READ_TOKEN, readers_, ACE_Token::ACE_Token_Queue::remove_entry(), ACE_Token::ACE_Token_Queue_Entry::runable_, ACE_Thread::self(), ACE_OS::thr_equal(), ACE_Token::ACE_Token_Queue_Entry::thread_id_, ACE_Token::ACE_Token_Queue_Entry::wait(), wakeup_next_waiter(), WRITE_TOKEN, and writers_.

00361 {
00362   ACE_TRACE ("ACE_Token::renew");
00363   ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
00364 
00365 #if defined (DEBUGGING)
00366   this->dump ();
00367 #endif /* DEBUGGING */
00368   // ACE_ASSERT (ACE_OS::thr_equal (ACE_Thread::self (), this->owner_));
00369 
00370   // Check to see if there are any waiters worth giving up the lock
00371   // for.
00372 
00373   // If no writers and either we are a writer or there are no readers.
00374   if (this->writers_.head_ == 0 &&
00375       (this->in_use_ == ACE_Token::WRITE_TOKEN ||
00376        this->readers_.head_ == 0))
00377     // Immediate return.
00378     return 0;
00379 
00380   // We've got to sleep until we get the token again.
00381 
00382   // Determine which queue should this thread go to.
00383   ACE_Token::ACE_Token_Queue *this_threads_queue =
00384     this->in_use_ == ACE_Token::READ_TOKEN ?
00385     &this->readers_ : &this->writers_;
00386 
00387   ACE_Token::ACE_Token_Queue_Entry my_entry (this->lock_,
00388                                              this->owner_);
00389 
00390   this_threads_queue->insert_entry (my_entry,
00391                                     // if requeue_position == 0 then we want to go next,
00392                                     // otherwise use the queueing strategy, which might also
00393                                     // happen to be 0.
00394                                     requeue_position == 0 ? 0 : this->queueing_strategy_);
00395   ++this->waiters_;
00396 
00397   // Remember nesting level...
00398   int const save_nesting_level_ = this->nesting_level_;
00399 
00400   // Reset state for new owner.
00401   this->nesting_level_ = 0;
00402 
00403   // Wakeup waiter.
00404   this->wakeup_next_waiter ();
00405 
00406   int timed_out = 0;
00407   int error = 0;
00408 
00409   // Sleep until we've got the token (ignore signals).
00410   do
00411     {
00412       int result = my_entry.wait (timeout,
00413                                   this->lock_);
00414 
00415       if (result == -1)
00416         {
00417           // Note, this should obey whatever thread-specific interrupt
00418           // policy is currently in place...
00419           if (errno == EINTR)
00420             continue;
00421 
00422 #if defined (DEBUGGING)
00423           cerr << '(' << ACE_Thread::self () << ')'
00424                << " renew: "
00425                << (errno == ETIME ? "timed out" : "error occurred")
00426                << endl;
00427 #endif /* DEBUGGING */
00428 
00429           // We come here if a timeout occurs or some serious
00430           // ACE_Condition object error.
00431           if (errno == ETIME)
00432             timed_out = 1;
00433           else
00434             error = 1;
00435 
00436           // Stop the loop.
00437           break;
00438         }
00439     }
00440   while (!ACE_OS::thr_equal (my_entry.thread_id_, this->owner_));
00441 
00442   // Do this always and irrespective of the result of wait().
00443   --this->waiters_;
00444   this_threads_queue->remove_entry (&my_entry);
00445 
00446 #if defined (DEBUGGING)
00447   cerr << '(' << ACE_Thread::self () << ')'
00448        << " acquire (UNBLOCKED)" << endl;
00449 #endif /* DEBUGGING */
00450 
00451   // If timeout occured
00452   if (timed_out)
00453     {
00454       // This thread was still selected to own the token.
00455       if (my_entry.runable_)
00456         {
00457           // Wakeup next waiter since this thread timed out.
00458           this->wakeup_next_waiter ();
00459         }
00460 
00461       // Return error.
00462      return -1;
00463     }
00464   else if (error)
00465     {
00466       // Return error.
00467       return -1;
00468     }
00469 
00470   // If this is a normal wakeup, this thread should be runnable.
00471   ACE_ASSERT (my_entry.runable_);
00472 
00473   // Reinstate nesting level.
00474   this->nesting_level_ = save_nesting_level_;
00475 
00476   return 0;
00477 }

int ACE_Token::shared_acquire void(*  sleep_hook_func)(void *),
void *  arg,
ACE_Time_Value timeout,
ACE_Token_Op_Type  op_type
[private]
 

Implements the and methods above.

Definition at line 184 of file Token.cpp.

References ACE_ASSERT, ACE_GUARD_RETURN, ACE_thread_t, ACE_TRACE, dump(), ETIME, ACE_Token::ACE_Token_Queue::insert_entry(), READ_TOKEN, readers_, ACE_Token::ACE_Token_Queue::remove_entry(), ACE_Token::ACE_Token_Queue_Entry::runable_, ACE_Time_Value::sec(), ACE_Thread::self(), sleep_hook(), ACE_OS::thr_equal(), ACE_Time_Value::usec(), ACE_Token::ACE_Token_Queue_Entry::wait(), wakeup_next_waiter(), and writers_.

Referenced by acquire(), acquire_read(), acquire_write(), tryacquire(), tryacquire_read(), and tryacquire_write().

00188 {
00189   ACE_TRACE ("ACE_Token::shared_acquire");
00190   ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
00191 
00192 #if defined (DEBUGGING)
00193   this->dump ();
00194 #endif /* DEBUGGING */
00195 
00196   ACE_thread_t thr_id = ACE_Thread::self ();
00197 
00198   // Nobody holds the token.
00199   if (!this->in_use_)
00200     {
00201       // Its mine!
00202       this->in_use_ = op_type;
00203       this->owner_ = thr_id;
00204       return 0;
00205     }
00206 
00207   //
00208   // Someone already holds the token.
00209   //
00210 
00211   // Check if it is us.
00212   if (ACE_OS::thr_equal (thr_id, this->owner_))
00213     {
00214       ++this->nesting_level_;
00215       return 0;
00216     }
00217 
00218   // Do a quick check for "polling" behavior.
00219   if (timeout != 0 && timeout->sec () == 0 && timeout->usec () == 0)
00220     {
00221       errno = ETIME;
00222       return -1;
00223     }
00224 
00225   //
00226   // We've got to sleep until we get the token.
00227   //
00228 
00229   // Which queue we should end up in...
00230   ACE_Token_Queue *queue = (op_type == ACE_Token::READ_TOKEN
00231                             ? &this->readers_
00232                             : &this->writers_);
00233 
00234   // Allocate queue entry on stack.  This works since we don't exit
00235   // this method's activation record until we've got the token.
00236   ACE_Token::ACE_Token_Queue_Entry my_entry (this->lock_,
00237                                              thr_id,
00238                                              this->attributes_);
00239   queue->insert_entry (my_entry, this->queueing_strategy_);
00240   ++this->waiters_;
00241 
00242   // Execute appropriate <sleep_hook> callback.  (@@ should these
00243   // methods return a success/failure status, and if so, what should
00244   // we do with it?)
00245   int ret = 0;
00246   if (sleep_hook_func)
00247     {
00248       (*sleep_hook_func) (arg);
00249       ++ret;
00250     }
00251   else
00252     {
00253       // Execute virtual method.
00254       this->sleep_hook ();
00255       ++ret;
00256     }
00257 
00258   int timed_out = 0;
00259   int error = 0;
00260 
00261   // Sleep until we've got the token (ignore signals).
00262   do
00263     {
00264       int result = my_entry.wait (timeout,
00265                                   this->lock_);
00266 
00267       if (result == -1)
00268         {
00269           // Note, this should obey whatever thread-specific interrupt
00270           // policy is currently in place...
00271           if (errno == EINTR)
00272             continue;
00273 
00274 #if defined (DEBUGGING)
00275           cerr << '(' << ACE_Thread::self () << ')'
00276                << " acquire: "
00277                << (errno == ETIME ? "timed out" : "error occurred")
00278                << endl;
00279 #endif /* DEBUGGING */
00280 
00281           // We come here if a timeout occurs or some serious
00282           // ACE_Condition object error.
00283           if (errno == ETIME)
00284             timed_out = 1;
00285           else
00286             error = 1;
00287 
00288           // Stop the loop.
00289           break;
00290         }
00291     }
00292   while (!ACE_OS::thr_equal (thr_id, this->owner_));
00293 
00294   // Do this always and irrespective of the result of wait().
00295   --this->waiters_;
00296   queue->remove_entry (&my_entry);
00297 
00298 #if defined (DEBUGGING)
00299   cerr << '(' << ACE_Thread::self () << ')'
00300        << " acquire (UNBLOCKED)" << endl;
00301 #endif /* DEBUGGING */
00302 
00303   // If timeout occured
00304   if (timed_out)
00305     {
00306       // This thread was still selected to own the token.
00307       if (my_entry.runable_)
00308         {
00309           // Wakeup next waiter since this thread timed out.
00310           this->wakeup_next_waiter ();
00311         }
00312 
00313       // Return error.
00314      return -1;
00315     }
00316   else if (error)
00317     {
00318       // Return error.
00319       return -1;
00320     }
00321 
00322   // If this is a normal wakeup, this thread should be runnable.
00323   ACE_ASSERT (my_entry.runable_);
00324 
00325   return ret;
00326 }

void ACE_Token::sleep_hook void   )  [virtual]
 

This should be overridden by a subclass to define the appropriate behavior before goes to sleep. By default, this is a no-op...

Definition at line 332 of file Token.cpp.

References ACE_TRACE.

Referenced by shared_acquire().

00333 {
00334   ACE_TRACE ("ACE_Token::sleep_hook");
00335 }

ACE_INLINE int ACE_Token::tryacquire void   ) 
 

Become interface-compliant with other lock mechanisms (implements a non-blocking ).

Definition at line 35 of file Token.inl.

References ACE_TRACE, shared_acquire(), and WRITE_TOKEN.

00036 {
00037   ACE_TRACE ("ACE_Token::tryacquire");
00038   return this->shared_acquire
00039     (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero, ACE_Token::WRITE_TOKEN);
00040 }

ACE_INLINE int ACE_Token::tryacquire_read void   ) 
 

Lower priority try_acquire().

Definition at line 78 of file Token.inl.

References ACE_TRACE, READ_TOKEN, and shared_acquire().

00079 {
00080   ACE_TRACE ("ACE_Token::tryacquire_read");
00081   return this->shared_acquire
00082     (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero, ACE_Token::READ_TOKEN);
00083 }

ACE_INLINE int ACE_Token::tryacquire_write void   ) 
 

Just calls .

Definition at line 95 of file Token.inl.

References ACE_TRACE, shared_acquire(), and WRITE_TOKEN.

00096 {
00097   ACE_TRACE ("ACE_Token::tryacquire_write");
00098   return this->shared_acquire
00099     (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero, ACE_Token::WRITE_TOKEN);
00100 }

ACE_INLINE int ACE_Token::tryacquire_write_upgrade void   ) 
 

Assumes the caller has acquired the token and returns 0.

Definition at line 103 of file Token.inl.

References ACE_TRACE.

00104 {
00105   ACE_TRACE ("ACE_Token::tryacquire_write_upgrade");
00106   return 0;
00107 }

ACE_INLINE int ACE_Token::waiters void   ) 
 

Return the number of threads that are currently waiting to get the token.

Definition at line 43 of file Token.inl.

References ACE_GUARD_RETURN, and ACE_TRACE.

00044 {
00045   ACE_TRACE ("ACE_Token::waiters");
00046   ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
00047 
00048   int const ret = this->waiters_;
00049   return ret;
00050 }

void ACE_Token::wakeup_next_waiter void   )  [private]
 

Wake next in line for ownership.

Definition at line 511 of file Token.cpp.

References ACE_TRACE, ACE_Token::ACE_Token_Queue::head_, READ_TOKEN, readers_, ACE_Token::ACE_Token_Queue_Entry::runable_, ACE_Token::ACE_Token_Queue_Entry::signal(), ACE_Token::ACE_Token_Queue_Entry::thread_id_, WRITE_TOKEN, and writers_.

Referenced by release(), renew(), and shared_acquire().

00512 {
00513   ACE_TRACE ("ACE_Token::wakeup_next_waiter");
00514 
00515   // Reset state for new owner.
00516   this->owner_ = ACE_OS::NULL_thread;
00517   this->in_use_ = 0;
00518 
00519   // Any waiters...
00520   if (this->writers_.head_ == 0 &&
00521       this->readers_.head_ == 0)
00522     {
00523       // No more waiters...
00524       return;
00525     }
00526 
00527   // Wakeup next waiter.
00528   ACE_Token_Queue *queue = 0;
00529 
00530   // Writer threads get priority to run first.
00531   if (this->writers_.head_ != 0)
00532     {
00533       this->in_use_ = ACE_Token::WRITE_TOKEN;
00534       queue = &this->writers_;
00535     }
00536   else
00537     {
00538       this->in_use_ = ACE_Token::READ_TOKEN;
00539       queue = &this->readers_;
00540     }
00541 
00542   // Wake up waiter and make it runable.
00543   queue->head_->runable_ = 1;
00544   queue->head_->signal ();
00545 
00546   this->owner_ = queue->head_->thread_id_;
00547 }


Member Data Documentation

ACE_Token::ACE_ALLOC_HOOK_DECLARE
 

Declare the dynamic allocation hooks.

Definition at line 217 of file Token.h.

ACE_Condition_Attributes ACE_Token::attributes_ [private]
 

The attributes for the condition variables, optimizes lock time.

Definition at line 314 of file Token.h.

int ACE_Token::in_use_ [private]
 

Some thread (i.e., ) is using the token. We need this extra variable to deal with POSIX pthreads madness...

Definition at line 305 of file Token.h.

ACE_Thread_Mutex ACE_Token::lock_ [private]
 

ACE_Thread_Mutex used to lock internal data structures.

Definition at line 298 of file Token.h.

int ACE_Token::nesting_level_ [private]
 

Current nesting level.

Definition at line 311 of file Token.h.

ACE_thread_t ACE_Token::owner_ [private]
 

Current owner of the token.

Definition at line 301 of file Token.h.

int ACE_Token::queueing_strategy_ [private]
 

Queueing strategy, LIFO/FIFO.

Definition at line 317 of file Token.h.

Referenced by ACE_Token(), and queueing_strategy().

ACE_Token_Queue ACE_Token::readers_ [private]
 

A queue of reader threads.

Definition at line 295 of file Token.h.

Referenced by renew(), shared_acquire(), and wakeup_next_waiter().

int ACE_Token::waiters_ [private]
 

Number of waiters.

Definition at line 308 of file Token.h.

ACE_Token_Queue ACE_Token::writers_ [private]
 

A queue of writer threads.

Definition at line 292 of file Token.h.

Referenced by renew(), shared_acquire(), and wakeup_next_waiter().


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 11:31:40 2006 for ACE by doxygen 1.3.6