#include <Token.h>
Collaboration diagram for ACE_Token:

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... | |
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.
|
|
Definition at line 238 of file Token.h.
00239 {
00240 READ_TOKEN = 1,
00241 WRITE_TOKEN
00242 };
|
|
|
Available queueing strategies. Definition at line 69 of file Token.h.
|
|
||||||||||||
|
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 } |
|
|
Destructor.
Definition at line 175 of file Token.cpp. References ACE_TRACE.
00176 {
00177 ACE_TRACE ("ACE_Token::~ACE_Token");
00178 }
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
Declare the dynamic allocation hooks.
|
|
|
The attributes for the condition variables, optimizes lock time.
Definition at line 295 of file Token.h. Referenced by ACE_Token. |
|
|
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 used to lock internal data structures.
Definition at line 279 of file Token.h. Referenced by ACE_Token. |
|
|
Current nesting level.
Definition at line 292 of file Token.h. Referenced by ACE_Token, release, renew, and shared_acquire. |
|
|
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. |
|
|
Queueing strategy, LIFO/FIFO.
Definition at line 298 of file Token.h. Referenced by ACE_Token, and queueing_strategy. |
|
|
A queue of reader threads.
Definition at line 276 of file Token.h. Referenced by renew, shared_acquire, and wakeup_next_waiter. |
|
|
Number of waiters.
Definition at line 289 of file Token.h. Referenced by ACE_Token, renew, shared_acquire, and waiters. |
|
|
A queue of writer threads.
Definition at line 273 of file Token.h. Referenced by renew, shared_acquire, and wakeup_next_waiter. |
1.2.14 written by Dimitri van Heesch,
© 1997-2002