Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

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 Methods

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

virtual ~ACE_Token (void)
 Destructor. More...

int queueing_strategy (void)
 Retrieve the current queueing strategy. More...

void queueing_strategy (int queueing_strategy)
 Set the queueing strategy. More...

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)
 Become interface-compliant with other lock mechanisms (implements a non-blocking <acquire>). More...

int remove (void)
 Shuts down the ACE_Token instance. More...

int release (void)
 Relinquish the token. If there are any waiters then the next one in line gets it. More...

int acquire_read (void)
 Behave like acquire but in a lower priority. It should probably be called acquire_yield. More...

int acquire_read (void(*sleep_hook)(void *), void *arg=0, ACE_Time_Value *timeout=0)
 More sophisticate version of acquire_read. More...

int acquire_write (void)
 Just calls <acquire>. More...

int acquire_write (void(*sleep_hook)(void *), void *arg=0, ACE_Time_Value *timeout=0)
 More sophisticate version of acquire_write. More...

int tryacquire_read (void)
 Lower priority try_acquire. More...

int tryacquire_write (void)
 Just calls <tryacquire>. More...

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

int waiters (void)
 Return the number of threads that are currently waiting to get the token. More...

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

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


Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks. More...


Private Types

enum  ACE_Token_Op_Type { READ_TOKEN = 1, WRITE_TOKEN }

Private Methods

int shared_acquire (void(*sleep_hook_func)(void *), void *arg, ACE_Time_Value *timeout, ACE_Token_Op_Type op_type)
 Implements the <acquire> and <tryacquire> methods above. More...

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


Private Attributes

ACE_Token_Queue writers_
 A queue of writer threads. More...

ACE_Token_Queue readers_
 A queue of reader threads. More...

ACE_Thread_Mutex lock_
 ACE_Thread_Mutex used to lock internal data structures. More...

ACE_thread_t owner_
 Current owner of the token. More...

int in_use_
 Some thread (i.e., <owner_>) is using the token. We need this extra variable to deal with POSIX pthreads madness... More...

int waiters_
 Number of waiters. More...

int nesting_level_
 Current nesting level. More...

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

int queueing_strategy_
 Queueing strategy, LIFO/FIFO. More...


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 <acquire> multiple times, however, it must call <release> 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 62 of file Token.h.


Member Enumeration Documentation

enum ACE_Token::ACE_Token_Op_Type [private]
 

Enumeration values:
READ_TOKEN 
WRITE_TOKEN 

Definition at line 238 of file Token.h.

00239   {
00240     READ_TOKEN = 1,
00241     WRITE_TOKEN
00242   };

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 69 of file Token.h.

00070   {
00071     /// FIFO, First In, First Out.
00072     FIFO = -1,
00073     /// LIFO, Last In, First Out
00074     LIFO = 0
00075   };


Constructor & Destructor Documentation

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

Constructor.

Definition at line 163 of file Token.cpp.

References ACE_TCHAR, attributes_, FIFO, in_use_, lock_, nesting_level_, owner_, queueing_strategy_, and waiters_.

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

ACE_Token::~ACE_Token void    [virtual]
 

Destructor.

Definition at line 175 of file Token.cpp.

References ACE_TRACE.

00176 {
00177   ACE_TRACE ("ACE_Token::~ACE_Token");
00178 }


Member Function Documentation

int ACE_Token::acquire ACE_Time_Value   timeout = 0
 

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

Definition at line 335 of file Token.cpp.

References ACE_TRACE, shared_acquire, and WRITE_TOKEN.

00336 {
00337   ACE_TRACE ("ACE_Token::acquire");
00338   return this->shared_acquire (0, 0, timeout, ACE_Token::WRITE_TOKEN);
00339 }

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 <timeout>, which is treated as "absolute" time. If some other thread currently holds the token then <sleep_hook> is called before our thread goes to sleep. This <sleep_hook> 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 <sleep_hook> 1 if <sleep_hook> is called. 2 if the token is signaled. -1 if failure or timeout occurs (if timeout occurs errno == ETIME) If <timeout> == <&ACE_Time_Value::zero> then acquire has polling semantics (and does *not* call <sleep_hook>).

Definition at line 345 of file Token.cpp.

References ACE_TRACE, shared_acquire, and WRITE_TOKEN.

00348 {
00349   ACE_TRACE ("ACE_Token::acquire");
00350   return this->shared_acquire (sleep_hook_func, arg, timeout, ACE_Token::WRITE_TOKEN);
00351 }

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

More sophisticate version of acquire_read.

Definition at line 78 of file Token.i.

References ACE_TRACE, READ_TOKEN, and shared_acquire.

00081 {
00082   ACE_TRACE ("ACE_Token::acquire_read");
00083   return this->shared_acquire (sleep_hook_func, arg, timeout, ACE_Token::READ_TOKEN);
00084 }

ACE_INLINE int ACE_Token::acquire_read void   
 

Behave like acquire but in a lower priority. It should probably be called acquire_yield.

Definition at line 54 of file Token.i.

References ACE_TRACE, READ_TOKEN, and shared_acquire.

00055 {
00056   ACE_TRACE ("ACE_Token::acquire_read");
00057   return this->shared_acquire
00058     (0, 0, 0, ACE_Token::READ_TOKEN);
00059 }

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

More sophisticate version of acquire_write.

Definition at line 102 of file Token.i.

References ACE_TRACE, shared_acquire, and WRITE_TOKEN.

00105 {
00106   ACE_TRACE ("ACE_Token::acquire_write");
00107   return this->shared_acquire (sleep_hook_func, arg, timeout, ACE_Token::WRITE_TOKEN);
00108 }

ACE_INLINE int ACE_Token::acquire_write void   
 

Just calls <acquire>.

Definition at line 62 of file Token.i.

References ACE_TRACE, shared_acquire, and WRITE_TOKEN.

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

ACE_INLINE ACE_thread_t ACE_Token::current_owner void   
 

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

Definition at line 45 of file Token.i.

References ACE_GUARD_RETURN, ACE_TRACE, and owner_.

00046 {
00047   ACE_TRACE ("ACE_Token::current_owner");
00048   ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, this->owner_);
00049 
00050   return this->owner_;
00051 }

void ACE_Token::dump void    const
 

Dump the state of an object.

Definition at line 25 of file Token.cpp.

References ACE_BEGIN_DUMP, ACE_DEBUG, ACE_END_DUMP, ACE_LIB_TEXT, ACE_TRACE, LM_DEBUG, and ACE_Thread::self.

Referenced by release, renew, and shared_acquire.

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

ACE_INLINE void ACE_Token::queueing_strategy int    queueing_strategy
 

Set the queueing strategy.

Definition at line 13 of file Token.i.

References queueing_strategy, and queueing_strategy_.

00014 {
00015   this->queueing_strategy_ = queueing_strategy == -1 ? -1 : 0;
00016 }

ACE_INLINE int ACE_Token::queueing_strategy void   
 

Retrieve the current queueing strategy.

Definition at line 7 of file Token.i.

References queueing_strategy_.

Referenced by queueing_strategy.

00008 {
00009   return this->queueing_strategy_;
00010 }

int ACE_Token::release void   
 

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

Definition at line 480 of file Token.cpp.

References ACE_GUARD_RETURN, ACE_TRACE, dump, nesting_level_, and wakeup_next_waiter.

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

ACE_INLINE int ACE_Token::remove void   
 

Shuts down the ACE_Token instance.

Definition at line 19 of file Token.i.

References ACE_TRACE.

00020 {
00021   ACE_TRACE ("ACE_Token::remove");
00022   // Don't have an implementation for this yet...
00023   ACE_NOTSUP_RETURN (-1);
00024 }

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 <requeue_position> == -1 and there are other threads waiting to obtain the token we are queued according to the queueing strategy. If <requeue_position> > -1 then it indicates how many entries to skip over before inserting our thread into the list of waiters (e.g., <requeue_position> == 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 <acquire>, the <timeout> value is an absolute time.

Definition at line 356 of file Token.cpp.

References ACE_ASSERT, ACE_GUARD_RETURN, ACE_TRACE, dump, ETIME, ACE_Token::ACE_Token_Queue::head_, in_use_, ACE_Token::ACE_Token_Queue::insert_entry, nesting_level_, 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, waiters_, wakeup_next_waiter, WRITE_TOKEN, and writers_.

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

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 <acquire> and <tryacquire> methods above.

Definition at line 181 of file Token.cpp.

References ACE_ASSERT, ACE_GUARD_RETURN, ACE_thread_t, ACE_TRACE, dump, ETIME, in_use_, nesting_level_, owner_, READ_TOKEN, readers_, 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, waiters_, wakeup_next_waiter, and writers_.

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

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

void ACE_Token::sleep_hook void    [virtual]
 

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

Definition at line 329 of file Token.cpp.

References ACE_TRACE.

Referenced by shared_acquire.

00330 {
00331   ACE_TRACE ("ACE_Token::sleep_hook");
00332 }

ACE_INLINE int ACE_Token::tryacquire void   
 

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

Definition at line 27 of file Token.i.

References ACE_TRACE, shared_acquire, WRITE_TOKEN, and ACE_Time_Value::zero.

00028 {
00029   ACE_TRACE ("ACE_Token::tryacquire");
00030   return this->shared_acquire 
00031     (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero, ACE_Token::WRITE_TOKEN);
00032 }

ACE_INLINE int ACE_Token::tryacquire_read void   
 

Lower priority try_acquire.

Definition at line 70 of file Token.i.

References ACE_TRACE, READ_TOKEN, shared_acquire, and ACE_Time_Value::zero.

00071 {
00072   ACE_TRACE ("ACE_Token::tryacquire_read");
00073   return this->shared_acquire
00074     (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero, ACE_Token::READ_TOKEN);
00075 }

ACE_INLINE int ACE_Token::tryacquire_write void   
 

Just calls <tryacquire>.

Definition at line 87 of file Token.i.

References ACE_TRACE, shared_acquire, WRITE_TOKEN, and ACE_Time_Value::zero.

00088 {
00089   ACE_TRACE ("ACE_Token::tryacquire_write");
00090   return this->shared_acquire
00091     (0, 0, (ACE_Time_Value *) &ACE_Time_Value::zero, ACE_Token::WRITE_TOKEN);
00092 }

ACE_INLINE int ACE_Token::tryacquire_write_upgrade void   
 

Assumes the caller has acquired the token and returns 0.

Definition at line 95 of file Token.i.

References ACE_TRACE.

00096 {
00097   ACE_TRACE ("ACE_Token::tryacquire_write_upgrade");
00098   return 0;
00099 }

ACE_INLINE int ACE_Token::waiters void   
 

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

Definition at line 35 of file Token.i.

References ACE_GUARD_RETURN, ACE_TRACE, and waiters_.

00036 {
00037   ACE_TRACE ("ACE_Token::waiters");
00038   ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1);
00039 
00040   int ret = this->waiters_;
00041   return ret;
00042 }

void ACE_Token::wakeup_next_waiter void    [private]
 

Wake next in line for ownership.

Definition at line 508 of file Token.cpp.

References ACE_TRACE, ACE_Token::ACE_Token_Queue::head_, in_use_, ACE_OS::NULL_thread, owner_, READ_TOKEN, readers_, ACE_Token::ACE_Token_Queue_Entry::runable_, WRITE_TOKEN, and writers_.

Referenced by release, renew, and shared_acquire.

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


Member Data Documentation

ACE_Token::ACE_ALLOC_HOOK_DECLARE
 

Declare the dynamic allocation hooks.

Definition at line 198 of file Token.h.

ACE_Condition_Attributes ACE_Token::attributes_ [private]
 

The attributes for the condition variables, optimizes lock time.

Definition at line 295 of file Token.h.

Referenced by ACE_Token.

int ACE_Token::in_use_ [private]
 

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

Definition at line 286 of file Token.h.

Referenced by ACE_Token, renew, shared_acquire, and wakeup_next_waiter.

ACE_Thread_Mutex ACE_Token::lock_ [private]
 

ACE_Thread_Mutex used to lock internal data structures.

Definition at line 279 of file Token.h.

Referenced by ACE_Token.

int ACE_Token::nesting_level_ [private]
 

Current nesting level.

Definition at line 292 of file Token.h.

Referenced by ACE_Token, release, renew, and shared_acquire.

ACE_thread_t ACE_Token::owner_ [private]
 

Current owner of the token.

Definition at line 282 of file Token.h.

Referenced by ACE_Token, current_owner, shared_acquire, and wakeup_next_waiter.

int ACE_Token::queueing_strategy_ [private]
 

Queueing strategy, LIFO/FIFO.

Definition at line 298 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 276 of file Token.h.

Referenced by renew, shared_acquire, and wakeup_next_waiter.

int ACE_Token::waiters_ [private]
 

Number of waiters.

Definition at line 289 of file Token.h.

Referenced by ACE_Token, renew, shared_acquire, and waiters.

ACE_Token_Queue ACE_Token::writers_ [private]
 

A queue of writer threads.

Definition at line 273 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 Mon Jun 16 12:58:22 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002