ACE_Mutex_Token Class Reference

Class that acquires, renews, and releases a process-local synchronization token. More...

#include <Local_Tokens.h>

Inheritance diagram for ACE_Mutex_Token:

Inheritance graph
[legend]
Collaboration diagram for ACE_Mutex_Token:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 ACE_Mutex_Token (const ACE_TCHAR *name)
 Constructor.

virtual ~ACE_Mutex_Token (void)
 Destructor.

virtual int acquire (ACE_TPQ_Entry *caller, int ignore_deadlock, int notify)
virtual int tryacquire (ACE_TPQ_Entry *caller)
 Same as acquire, but fails if would block.

virtual int renew (ACE_TPQ_Entry *caller, int requeue_position)
virtual int release (ACE_TPQ_Entry *caller)
void dump (void) const
 Dump the state of the class.

virtual int type (void) const
 Returns ACE_Tokens::MUTEX.

virtual int owners (OWNER_STACK &o, const ACE_TCHAR *id)
virtual int is_waiting_for (const ACE_TCHAR *id)
 Returns 1 if is waiting for this token. 0 otherwise.

virtual int is_owner (const ACE_TCHAR *id)
 Returns 1 if is an owner of this token. 0 otherwise.


Private Attributes

ACE_TOKEN_CONST::MUTEX lock_
 ACE_Mutex_Token used to lock internal data structures.


Detailed Description

Class that acquires, renews, and releases a process-local synchronization token.

Not a public interface. This class is a more general-purpose synchronization mechanism than SunOS 5.x mutexes. For example, it implements "recursive mutex" semantics, where a thread that owns the token can reacquire it without deadlocking. In addition, threads that are blocked awaiting the token are serviced in strict FIFO order as other threads release the token (SunOS 5.x mutexes don't strictly enforce an acquisition order).

Definition at line 498 of file Local_Tokens.h.


Constructor & Destructor Documentation

ACE_Mutex_Token::ACE_Mutex_Token const ACE_TCHAR name  )  [explicit]
 

Constructor.

Definition at line 466 of file Local_Tokens.cpp.

References ACE_MAXTOKENNAMELEN, ACE_TCHAR, ACE_TRACE, and ACE_OS::strsncpy().

00467 {
00468   ACE_TRACE ("ACE_Mutex_Token::ACE_Mutex_Token");
00469 
00470   ACE_OS::strsncpy (this->token_name_,
00471                     name,
00472                     ACE_MAXTOKENNAMELEN);
00473 }

ACE_Mutex_Token::~ACE_Mutex_Token void   )  [virtual]
 

Destructor.

Definition at line 475 of file Local_Tokens.cpp.

References ACE_TRACE.

00476 {
00477   ACE_TRACE ("ACE_Mutex_Token::~ACE_Mutex_Token");
00478 }


Member Function Documentation

int ACE_Mutex_Token::acquire ACE_TPQ_Entry caller,
int  ignore_deadlock,
int  notify
[virtual]
 

Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as the reason. If errnum == EWOULDBLOCK, and notify == 1, <ACE_Token_Proxy::sleep_hook> has been called on the current owner of the token. If ignore_deadlock is passed as 1 and errnum == EDEADLK, then deadlock was detected via ace_token_manager.

Implements ACE_Tokens.

Definition at line 481 of file Local_Tokens.cpp.

References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::call_sleep_hook(), ACE_Token_Manager::check_deadlock(), ACE_TPQ_Entry::client_id(), EDEADLK, ACE_Token_Proxy_Queue::enqueue(), EWOULDBLOCK, ACE_Token_Manager::instance(), is_owner(), ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level(), ACE_Tokens::owner(), and ACE_TPQ_Entry::proxy().

00484 {
00485   ACE_TRACE ("ACE_Mutex_Token::acquire");
00486   // We need to acquire two locks. This one to ensure that only one
00487   // thread uses this token at a time.
00488   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
00489   // This one to ensure an atomic transaction across all tokens.  Note
00490   // that this order is crucial too.  It's resource coloring for other
00491   // threads which may be calling this same token.
00492   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
00493 
00494   // Does _anyone_ own the token?
00495   if (this->owner () == 0)
00496     {
00497       // there are no waiters, so queue as the first waiter (the owner.)
00498       this->waiters_.enqueue (caller, -1);
00499       return 0;  // success
00500     }
00501 
00502   // Does the caller already own it?
00503   if (this->is_owner (caller->client_id ()))
00504     {
00505       // Recursive acquisition.
00506       caller->nesting_level (1);
00507       return 0; // success
00508     }
00509 
00510   // Check for deadlock.
00511   if (!ignore_deadlock
00512       && ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1)
00513     {
00514       errno = EDEADLK;
00515       ACE_RETURN (-1);
00516     }
00517 
00518   // Someone owns it. Sorry, you're getting queued up at the end of
00519   // the waiter queue.
00520   this->waiters_.enqueue (caller, -1);
00521 
00522   if (notify)
00523     this->owner ()->call_sleep_hook ();
00524 
00525   errno = EWOULDBLOCK;
00526   ACE_RETURN (-1);
00527 
00528   ACE_NOTREACHED (return -1);
00529 }

void ACE_Mutex_Token::dump void   )  const
 

Dump the state of the class.

Reimplemented from ACE_Tokens.

Definition at line 451 of file Local_Tokens.cpp.

References ACE_BEGIN_DUMP, ACE_DEBUG, ACE_END_DUMP, ACE_LIB_TEXT, ACE_TRACE, ACE_Tokens::dump(), ACE_Null_Mutex::dump(), and LM_DEBUG.

00452 {
00453 #if defined (ACE_HAS_DUMP)
00454   ACE_TRACE ("ACE_Mutex_Token::dump");
00455   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00456   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("ACE_Mutex_Token::dump:\n")));
00457   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("lock_\n")));
00458   lock_.dump ();
00459   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("base:\n")));
00460   ACE_Tokens::dump ();
00461   ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("ACE_Mutex_Token::dump end.\n")));
00462   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00463 #endif /* ACE_HAS_DUMP */
00464 }

int ACE_Mutex_Token::is_owner const ACE_TCHAR id  )  [virtual]
 

Returns 1 if is an owner of this token. 0 otherwise.

Implements ACE_Tokens.

Definition at line 678 of file Local_Tokens.cpp.

References ACE_TCHAR, ACE_TRACE, ACE_TPQ_Entry::equal_client_id(), and ACE_Tokens::owner().

Referenced by acquire(), is_waiting_for(), release(), renew(), and tryacquire().

00679 {
00680   ACE_TRACE ("ACE_Mutex_Token::is_owner");
00681   // If there is an owner, return whether it is <id>.
00682   if ((this->owner () != 0) &&
00683       this->owner ()->equal_client_id (id))
00684     return 1;
00685   else
00686     return 0;
00687 }

int ACE_Mutex_Token::is_waiting_for const ACE_TCHAR id  )  [virtual]
 

Returns 1 if is waiting for this token. 0 otherwise.

Implements ACE_Tokens.

Definition at line 656 of file Local_Tokens.cpp.

References ACE_TCHAR, ACE_TRACE, ACE_TPQ_Iterator::advance(), ACE_TPQ_Entry::equal_client_id(), is_owner(), ACE_TPQ_Iterator::next(), and ACE_Tokens::owner().

00657 {
00658   ACE_TRACE ("ACE_Mutex_Token::is_waiting_for");
00659   // If there is no owner, or <id> is the owner, return false.
00660   if ((this->owner () == 0) || this->is_owner (id))
00661     return 0;
00662 
00663   // Step through each waiter looking for <id>.
00664   ACE_TPQ_Iterator iterator (waiters_);
00665   iterator.advance ();
00666   for (ACE_TPQ_Entry *temp = 0;
00667        iterator.next (temp) != 0;
00668        iterator.advance ())
00669     {
00670       if (temp->equal_client_id (id))
00671         return 1;
00672     }
00673 
00674   return 0;
00675 }

int ACE_Mutex_Token::owners OWNER_STACK o,
const ACE_TCHAR id
[virtual]
 

Returns a stack of the current owners. Returns -1 on error, 0 on success. If is non-zero, returns 1 if id is an owner.

Implements ACE_Tokens.

Definition at line 639 of file Local_Tokens.cpp.

References ACE_TCHAR, ACE_TRACE, ACE_TPQ_Entry::equal_client_id(), and ACE_Tokens::owner().

00641 {
00642   ACE_TRACE ("ACE_Mutex_Token::owners");
00643   if (this->owner () != 0)
00644     {
00645       stack.push (this->owner ());
00646       // If an <id> is specified, return whether it is the owner being
00647       // returned.
00648       if (id != 0)
00649         return this->owner ()->equal_client_id (id);
00650     }
00651 
00652   return 0;
00653 }

int ACE_Mutex_Token::release ACE_TPQ_Entry caller  )  [virtual]
 

Relinquish the token. If there are any waiters then the next one in line gets it. If the caller is not the owner, caller is removed from the waiter list.

Implements ACE_Tokens.

Definition at line 606 of file Local_Tokens.cpp.

References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::client_id(), ACE_Token_Proxy_Queue::dequeue(), is_owner(), ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level(), ACE_Tokens::owner(), ACE_TPQ_Entry::proxy(), ACE_Tokens::remove(), and ACE_Token_Proxy::token_acquired().

00607 {
00608   ACE_TRACE ("ACE_Mutex_Token::release");
00609   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
00610 
00611   // Does anyone own the token?
00612   if (this->owner () == 0)
00613     {
00614       errno = EACCES;
00615       ACE_RETURN (-1);
00616     }
00617 
00618   // Is the caller the owner.
00619   if (this->is_owner (caller->client_id ()))
00620     {
00621       // Check the nesting level.
00622       if (caller->nesting_level () > 0)
00623         caller->nesting_level (-1);
00624       else
00625         {
00626           this->waiters_.dequeue ();
00627           // Notify new owner.
00628           if (this->owner () != 0)
00629             this->owner ()->proxy ()->token_acquired (this->owner ());
00630         }
00631     }
00632   else
00633     this->remove (caller);
00634 
00635   return 0;
00636 }

int ACE_Mutex_Token::renew ACE_TPQ_Entry caller,
int  requeue_position
[virtual]
 

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 at the end of the list of waiters. 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... Returns 0 on success, -1 on failure with <ACE_Log_Msg::errnum> as the reason. If errnum == EWOULDBLOCK, and notify == 1, <ACE_Token_Proxy::sleep_hook> has been called on the current owner of the token.

Implements ACE_Tokens.

Definition at line 567 of file Local_Tokens.cpp.

References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::client_id(), ACE_Token_Proxy_Queue::dequeue(), ACE_Token_Proxy_Queue::enqueue(), EWOULDBLOCK, is_owner(), ACE_TOKEN_CONST::MUTEX, ACE_Tokens::owner(), ACE_TPQ_Entry::proxy(), ACE_Token_Proxy_Queue::size(), and ACE_Token_Proxy::token_acquired().

00569 {
00570   ACE_TRACE ("ACE_Mutex_Token::renew");
00571   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
00572 
00573   // Verify that the caller is the owner.
00574   if (this->is_owner (caller->client_id ()) == 0)
00575     {
00576       errno = EACCES;
00577       ACE_RETURN (-1);
00578     }
00579 
00580   // The caller is the owner, so check to see if there are any
00581   // waiters.  If not, we just keep the token.  == 1 means that there
00582   // is only the owner.
00583   if (this->waiters_.size () == 1 || requeue_position == 0)
00584     return 0;
00585 
00586   // Requeue the caller.
00587   this->waiters_.dequeue ();
00588 
00589   this->waiters_.enqueue (caller, requeue_position);
00590 
00591   // Notify new owner.
00592   if (this->owner () != 0)
00593     this->owner ()->proxy ()->token_acquired (this->owner ());
00594 
00595   // Tell the caller that the operation would block.
00596   errno = EWOULDBLOCK;
00597   ACE_RETURN (-1);
00598 
00599   ACE_NOTREACHED (return -1);
00600 }

int ACE_Mutex_Token::tryacquire ACE_TPQ_Entry caller  )  [virtual]
 

Same as acquire, but fails if would block.

Implements ACE_Tokens.

Definition at line 532 of file Local_Tokens.cpp.

References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::client_id(), ACE_Token_Proxy_Queue::enqueue(), EWOULDBLOCK, is_owner(), ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level(), and ACE_Tokens::owner().

00533 {
00534   ACE_TRACE ("ACE_Mutex_Token::tryacquire");
00535   // We need to acquire two locks. This one to ensure that only one
00536   // thread uses this token at a time.
00537   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
00538   // This one to ensure an atomic transaction across all tokens.  Note
00539   // that this order is crucial too.  It's resource coloring for other
00540   // threads which may be calling this same token.
00541   ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
00542 
00543   // Does _anyone_ own the token?
00544   if (this->owner () == 0)
00545     {
00546       this->waiters_.enqueue (caller, -1);
00547       return 0;  // success
00548     }
00549   // Does the caller already own it?
00550   if (this->is_owner (caller->client_id ()))
00551     {
00552       // recursive acquisition
00553       caller->nesting_level (1);
00554       return 0;  // success
00555     }
00556   else
00557     // Someone owns it.  Fail.
00558     {
00559       errno = EWOULDBLOCK;
00560       ACE_RETURN (-1);
00561     }
00562 
00563   ACE_NOTREACHED (return -1);
00564 }

int ACE_Mutex_Token::type void   )  const [virtual]
 

Returns ACE_Tokens::MUTEX.

Implements ACE_Tokens.

Definition at line 690 of file Local_Tokens.cpp.

References ACE_TRACE.

00691 {
00692   ACE_TRACE ("ACE_Mutex_Token::type");
00693   return (int) ACE_Tokens::MUTEX;
00694 }


Member Data Documentation

ACE_TOKEN_CONST::MUTEX ACE_Mutex_Token::lock_ [private]
 

ACE_Mutex_Token used to lock internal data structures.

Definition at line 574 of file Local_Tokens.h.


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