#include <Local_Tokens.h>
Inheritance diagram for ACE_RW_Token:


Public Types | |
| enum | PROXY_TYPE { READER, WRITER } |
| These are the types that proxies can be. More... | |
Public Methods | |
| ACE_EXPLICIT | ACE_RW_Token (const ACE_TCHAR *name) |
| Constructor. More... | |
| virtual | ~ACE_RW_Token (void) |
| Destructor. More... | |
| virtual int | acquire (ACE_TPQ_Entry *caller, int ignore_deadlock, int notify) |
| virtual int | tryacquire (ACE_TPQ_Entry *caller) |
| Same as acquire except fails on would block. More... | |
| 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. More... | |
| virtual int | type (void) const |
| Returns READER or WRITER. More... | |
| virtual int | owners (OWNER_STACK &o, const ACE_TCHAR *id) |
| Returns a stack of the current owners. Returns -1 on error, 0 on success. If <id> is non-zero, returns 1 if id is an owner. More... | |
| virtual int | is_waiting_for (const ACE_TCHAR *id) |
| Returns 1 if <id> is waiting for this token. 0 otherwise. More... | |
| virtual int | is_owner (const ACE_TCHAR *id) |
| Returns 1 if <id> is an owner of this token. 0 otherwise. More... | |
Protected Methods | |
| void | notify_new_owner (ACE_TPQ_Entry *caller) |
| Sets the new owner. More... | |
Protected Attributes | |
| int | num_writers_ |
| The number of waiting writers. More... | |
| ACE_TOKEN_CONST::MUTEX | lock_ |
| ACE_Mutex_Token used to lock internal data structures. More... | |
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 588 of file Local_Tokens.h.
|
|
These are the types that proxies can be.
Definition at line 650 of file Local_Tokens.h.
|
|
|
Constructor.
Definition at line 672 of file Local_Tokens.cpp. References ACE_MAXTOKENNAMELEN, ACE_TCHAR, ACE_TRACE, ACE_Tokens::name, and ACE_OS_String::strsncpy.
00673 : num_writers_ (0) 00674 { 00675 ACE_TRACE ("ACE_RW_Token::ACE_RW_Token"); 00676 00677 ACE_OS::strsncpy (this->token_name_, 00678 name, 00679 ACE_MAXTOKENNAMELEN); 00680 } |
|
|
Destructor.
Definition at line 682 of file Local_Tokens.cpp. References ACE_TRACE.
00683 {
00684 ACE_TRACE ("ACE_RW_Token::~ACE_RW_Token");
00685 }
|
|
||||||||||||||||
|
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 688 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_Null_Mutex::lock_, ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level, ACE_TPQ_Entry::next_, num_writers_, ACE_Tokens::owner, ACE_TPQ_Entry::proxy, READER, ACE_Token_Proxy::type, ACE_Tokens::waiters_, and WRITER.
00691 {
00692 ACE_TRACE ("ACE_RW_Token::acquire");
00693 // We need to acquire two locks. This one to ensure that only one
00694 // thread uses this token at a time.
00695 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
00696 // This one to ensure an atomic transaction across all tokens. Note
00697 // that this order is crucial too. It's resource coloring for other
00698 // threads which may be calling this same token.
00699 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
00700
00701 if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
00702 this->num_writers_++;
00703
00704 // Does _anyone_ own the token?
00705 if (this->owner () == 0)
00706 {
00707 // There are no waiters, so queue as the first waiter (the owner).
00708 this->waiters_.enqueue (caller, -1);
00709 return 0;
00710 }
00711
00712 // Check for recursive acquisition.
00713 if (this->is_owner (caller->client_id ()))
00714 {
00715 caller->nesting_level (1);
00716 return 0; // Success.
00717 }
00718
00719 // Reader.
00720 if (caller->proxy ()->type () == ACE_RW_Token::READER)
00721 {
00722 // Are there any writers?
00723 if (this->num_writers_ == 0)
00724 {
00725 // Queue the caller at the end of the queue.
00726 this->waiters_.enqueue (caller, -1);
00727 return 0;
00728 }
00729 // Else failure.
00730 }
00731
00732 // Failure code.
00733
00734 // Check for deadlock.
00735 if (!ignore_deadlock &&
00736 ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1)
00737 {
00738 if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
00739 this->num_writers_--;
00740 errno = EDEADLK;
00741 ACE_RETURN (-1);
00742 }
00743
00744 // Queue the caller at the end of the queue.
00745 this->waiters_.enqueue (caller, -1);
00746
00747 if (notify)
00748 {
00749 // If it's a writer, just notify it.
00750 if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER)
00751 this->owner ()->call_sleep_hook ();
00752 else
00753 {
00754 // Call back all reader owners.
00755 ACE_TPQ_Entry *temp = this->owner ();
00756 do
00757 {
00758 temp->call_sleep_hook ();
00759 temp = temp->next_;
00760 }
00761 while (temp != 0 &&
00762 temp->proxy ()->type () == ACE_RW_Token::READER);
00763 }
00764 }
00765
00766 errno = EWOULDBLOCK;
00767 ACE_RETURN (-1);
00768
00769 ACE_NOTREACHED (return -1);
00770 }
|
|
|
Dump the state of the class.
Reimplemented from ACE_Tokens. Definition at line 658 of file Local_Tokens.cpp. References ACE_BEGIN_DUMP, ACE_DEBUG, ACE_END_DUMP, ACE_LIB_TEXT, ACE_TRACE, ACE_Tokens::dump, LM_DEBUG, lock_, and num_writers_.
00659 {
00660 ACE_TRACE ("ACE_RW_Token::dump");
00661 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00662 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_RW_Token::dump:\n")
00663 ACE_LIB_TEXT ("num_writers_ = %d\n"), num_writers_));
00664 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("lock_\n")));
00665 this->lock_.dump ();
00666 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("base:\n")));
00667 ACE_Tokens::dump ();
00668 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_RW_Token::dump end.\n")));
00669 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00670 }
|
|
|
Returns 1 if <id> is an owner of this token. 0 otherwise.
Implements ACE_Tokens. Definition at line 1009 of file Local_Tokens.cpp. References ACE_TCHAR, ACE_TRACE, ACE_TPQ_Iterator::advance, ACE_TPQ_Entry::equal_client_id, ACE_TPQ_Iterator::next, ACE_Tokens::owner, ACE_TPQ_Entry::proxy, READER, ACE_Token_Proxy::type, ACE_Tokens::waiters_, and WRITER. Referenced by acquire, is_waiting_for, release, renew, and tryacquire.
01010 {
01011 ACE_TRACE ("ACE_RW_Token::is_owner");
01012 // If there is no owner, return false.
01013 if (this->owner () == 0)
01014 return 0;
01015
01016 // A writer owns us.
01017 if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER)
01018 return this->owner ()->equal_client_id (id);
01019
01020 // Readers own us.
01021 // Step through each owning reader looking for <id>.
01022 ACE_TPQ_Iterator iterator (waiters_);
01023 for (ACE_TPQ_Entry *temp = 0;
01024 iterator.next (temp) != 0;
01025 iterator.advance ())
01026 {
01027 if (temp->proxy ()->type () != ACE_RW_Token::READER)
01028 break;
01029
01030 if (temp->equal_client_id (id))
01031 return 1;
01032 }
01033
01034 return 0;
01035 }
|
|
|
Returns 1 if <id> is waiting for this token. 0 otherwise.
Implements ACE_Tokens. Definition at line 986 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, ACE_Tokens::owner, and ACE_Tokens::waiters_.
00987 {
00988 ACE_TRACE ("ACE_RW_Token::is_waiting_for");
00989 // If there is no owner, or <id> is the owner, return false.
00990 if ((this->owner () == 0) ||
00991 this->is_owner (id))
00992 return 0;
00993
00994 // Step through each waiter looking for <id>.
00995 ACE_TPQ_Iterator iterator (waiters_);
00996 iterator.advance ();
00997 for (ACE_TPQ_Entry *temp = 0;
00998 iterator.next (temp) != 0;
00999 iterator.advance ())
01000 {
01001 if (temp->equal_client_id (id))
01002 return 1;
01003 }
01004
01005 return 0;
01006 }
|
|
|
Sets the new owner.
Definition at line 907 of file Local_Tokens.cpp. References ACE_TRACE, ACE_TPQ_Iterator::advance, ACE_TPQ_Iterator::next, ACE_Tokens::owner, ACE_TPQ_Entry::proxy, READER, ACE_Token_Proxy::token_acquired, ACE_Token_Proxy::type, ACE_Tokens::waiters_, and WRITER. Referenced by release, and renew.
00908 {
00909 ACE_TRACE ("ACE_RW_Token::notify_new_owner");
00910
00911 if (this->owner () == 0)
00912 return;
00913
00914 if (this->owner ()->proxy ()->type () == ACE_RW_Token::READER)
00915 {
00916 if (old_owner->proxy ()->type () == ACE_RW_Token::READER)
00917 // the owners already know that they're owners
00918 return;
00919
00920 // The current owner is a reader and the previous owner was a
00921 // writer, so notify all waiting readers up to the first writer.
00922 // call back all reader owners.
00923 ACE_TPQ_Iterator iterator (waiters_);
00924 for (ACE_TPQ_Entry *temp = 0;
00925 iterator.next (temp) != 0;
00926 iterator.advance ())
00927 {
00928 if (temp->proxy ()->type () == WRITER)
00929 // We've gone through all the readers.
00930 break;
00931
00932 temp->proxy ()->token_acquired (temp);
00933 }
00934 }
00935 else // writer
00936 this->owner ()->proxy ()->token_acquired (this->owner ());
00937 }
|
|
||||||||||||
|
Returns a stack of the current owners. Returns -1 on error, 0 on success. If <id> is non-zero, returns 1 if id is an owner.
Implements ACE_Tokens. Definition at line 941 of file Local_Tokens.cpp. References ACE_TCHAR, ACE_TRACE, ACE_TPQ_Iterator::advance, ACE_TPQ_Entry::client_id, ACE_TPQ_Iterator::next, ACE_Tokens::owner, ACE_TPQ_Entry::proxy, ACE_OS_String::strcmp, ACE_Token_Proxy::type, ACE_Tokens::waiters_, and WRITER.
00943 {
00944 ACE_TRACE ("ACE_RW_Token::owners");
00945
00946 if (this->owner () == 0)
00947 return 0;
00948
00949 int id_is_owner = 0;
00950
00951 // The first waiter is a writer, so there is only one owner.
00952 if (this->owner ()->proxy ()->type () == WRITER)
00953 {
00954 stack.push (this->owner ());
00955 // If an <id> is specified, return whether it is the owner being
00956 // returned.
00957 if ((id != 0) &&
00958 (ACE_OS::strcmp (id, this->owner ()->client_id ()) == 0))
00959 id_is_owner = 1;
00960 }
00961 // The first waiter is a reader, so there can be multiple owning
00962 // readers.
00963 else
00964 {
00965 ACE_TPQ_Iterator iterator (waiters_);
00966 for (ACE_TPQ_Entry *temp = 0;
00967 iterator.next (temp) != 0;
00968 iterator.advance ())
00969 {
00970 if (temp->proxy ()->type () == WRITER)
00971 // We've gone through all the readers.
00972 break;
00973
00974 stack.push (temp);
00975
00976 if (!id_is_owner && (id != 0) &&
00977 (ACE_OS::strcmp (id, temp->client_id ()) == 0))
00978 id_is_owner = 1;
00979 }
00980 }
00981
00982 return id_is_owner;
00983 }
|
|
|
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 876 of file Local_Tokens.cpp. References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::client_id, is_owner, ACE_Null_Mutex::lock_, ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level, notify_new_owner, num_writers_, ACE_Tokens::owner, ACE_TPQ_Entry::proxy, ACE_Tokens::remove, ACE_Token_Proxy::type, and WRITER.
00877 {
00878 ACE_TRACE ("ACE_RW_Token::release");
00879 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
00880
00881 // Check for errors.
00882 if ((this->owner () == 0) ||
00883 (this->is_owner (caller->client_id ()) == 0))
00884 {
00885 errno = EACCES;
00886 ACE_RETURN (-1);
00887 }
00888
00889 if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
00890 num_writers_--;
00891
00892 // Recursive release.
00893 if (caller->nesting_level () > 0)
00894 {
00895 caller->nesting_level (-1);
00896 return 0;
00897 }
00898
00899 // Remove the caller and notify the new owner(s).
00900 this->remove (caller);
00901 this->notify_new_owner (caller);
00902
00903 return 0;
00904 }
|
|
||||||||||||
|
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 at the end of the list of waiters. 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... 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 830 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_Null_Mutex::lock_, ACE_TOKEN_CONST::MUTEX, notify_new_owner, ACE_TPQ_Entry::proxy, READER, ACE_Tokens::remove, ACE_Token_Proxy_Queue::size, ACE_Token_Proxy::type, and ACE_Tokens::waiters_.
00832 {
00833 ACE_TRACE ("ACE_RW_Token::renew");
00834 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);
00835
00836 // Werify that the caller is the owner
00837 if (this->is_owner (caller->client_id ()) == 0)
00838 {
00839 errno = EACCES;
00840 ACE_RETURN (-1);
00841 }
00842
00843 // The caller is the owner, so check to see if there are any
00844 // waiters. If not, we just keep the token.
00845 if (this->waiters_.size () == 1 || requeue_position == 0)
00846 return 0;
00847
00848 // There are waiters, so remove the caller.
00849 this->remove (caller);
00850
00851 // Requeue the caller.
00852 this->waiters_.enqueue (caller, requeue_position);
00853
00854 if (caller->proxy ()->type () == ACE_RW_Token::READER)
00855 {
00856 // If the caller got queued before any writers, the caller is
00857 // still the owner.
00858 if (this->is_owner (caller->client_id ()))
00859 return 0; // success
00860 // else fallthrough and return would block.
00861 }
00862 // Writers will always have to block since waiters_.size () == 1 or
00863 // requeue_position == 0.
00864
00865 // Get a new owner.
00866 this->notify_new_owner (caller);
00867
00868 // Tell the caller that the operation would block.
00869 errno = EWOULDBLOCK;
00870 ACE_RETURN (-1);
00871
00872 ACE_NOTREACHED (return -1);
00873 }
|
|
|
Same as acquire except fails on would block.
Implements ACE_Tokens. Definition at line 773 of file Local_Tokens.cpp. References ACE_GUARD_RETURN, ACE_RETURN, ACE_TRACE, ACE_TPQ_Entry::client_id, ACE_Token_Proxy_Queue::enqueue, EWOULDBLOCK, ACE_Token_Manager::instance, is_owner, ACE_Null_Mutex::lock_, ACE_TOKEN_CONST::MUTEX, ACE_TPQ_Entry::nesting_level, num_writers_, ACE_Tokens::owner, ACE_TPQ_Entry::proxy, READER, ACE_Token_Proxy::type, ACE_Tokens::waiters_, and WRITER.
00774 {
00775 ACE_TRACE ("ACE_RW_Token::tryacquire");
00776 // We need to acquire two locks. This one to ensure that only one
00777 // thread uses this token at a time.
00778 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
00779 // This one to ensure an atomic transaction across all tokens. Note
00780 // that this order is crucial too. It's resource coloring for other
00781 // threads which may be calling this same token.
00782 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);
00783
00784 if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
00785 {
00786 this->num_writers_++;
00787 }
00788
00789 // Does _anyone_ own the token?
00790 if (this->owner () == 0)
00791 {
00792 // There are no waiters, so queue as the first waiter (the owner).
00793 this->waiters_.enqueue (caller, -1);
00794 return 0;
00795 }
00796
00797 // Check for recursive acquisition.
00798 if (this->is_owner (caller->client_id ()))
00799 {
00800 caller->nesting_level (1);
00801 return 0; // Success.
00802 }
00803
00804 // Reader.
00805 if (caller->proxy ()->type () == ACE_RW_Token::READER)
00806 {
00807 // Are there any writers?
00808 if (this->num_writers_ == 0)
00809 {
00810 // queue the caller at the end of the queue.
00811 this->waiters_.enqueue (caller, -1);
00812 return 0;
00813 }
00814 // Else, fail.
00815 }
00816 else // Writer.
00817 // We're going to fail, so decrement the num_writers.
00818 {
00819 this->num_writers_--;
00820 }
00821
00822
00823 errno = EWOULDBLOCK;
00824 ACE_RETURN (-1);
00825
00826 ACE_NOTREACHED (return -1);
00827 }
|
|
|
Returns READER or WRITER.
Implements ACE_Tokens. |
|
|
ACE_Mutex_Token used to lock internal data structures.
Definition at line 670 of file Local_Tokens.h. Referenced by dump. |
|
|
The number of waiting writers.
Definition at line 667 of file Local_Tokens.h. Referenced by acquire, dump, release, and tryacquire. |
1.2.14 written by Dimitri van Heesch,
© 1997-2002