1 #include "ace/Local_Tokens.h"
3 #if defined (ACE_HAS_TOKENS_LIBRARY)
5 #include "ace/Thread.h"
6 #include "ace/Token_Manager.h"
7 #include "ace/OS_NS_unistd.h"
9 #if !defined (__ACE_INLINE__)
10 #include "ace/Local_Tokens.inl"
11 #endif /* __ACE_INLINE__ */
13 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
16 ACE_Tokens::dump () const
18 #if defined (ACE_HAS_DUMP)
19 ACE_TRACE ("ACE_Tokens::dump");
20 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
21 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Tokens::dump:\n")
22 ACE_TEXT (" reference_cont_ = %d\n")
23 ACE_TEXT (" token_name_ = %s\n"),
24 reference_count_
, token_name_
));
25 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("waiters_\n")));
26 this->waiters_
.dump ();
27 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
28 #endif /* ACE_HAS_DUMP */
31 ACE_Tokens::ACE_Tokens ()
35 ACE_TRACE ("ACE_Tokens::ACE_Tokens");
39 ACE_Tokens::make_owner (ACE_TPQ_Entry
*caller
)
41 this->waiters_
.remove (caller
);
42 this->waiters_
.enqueue (caller
, 0);
45 ACE_Token_Proxy_Queue
*
46 ACE_Tokens::waiters ()
48 ACE_TRACE ("ACE_Tokens::waiters");
49 return &this->waiters_
;
53 ACE_Tokens::no_of_waiters ()
55 ACE_TRACE ("ACE_Tokens::no_of_waiters");
56 return this->waiters_
.size ();
60 ACE_TPQ_Entry::dump () const
62 #if defined (ACE_HAS_DUMP)
63 ACE_TRACE ("ACE_TPQ_Entry::dump");
64 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
65 ACELIB_DEBUG ((LM_DEBUG
,
66 ACE_TEXT ("ACE_TPQ_Entry::dump:\n")
67 ACE_TEXT (" nesting_level_ = %d\n")
68 ACE_TEXT (" client_id_ = %s\n"),
74 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("next:.\n")));
78 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_TPQ_Entry::dump end.\n")));
79 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
80 #endif /* ACE_HAS_DUMP */
83 ACE_TPQ_Entry::ACE_TPQ_Entry (const ACE_Token_Proxy
*new_proxy
,
84 const ACE_TCHAR
*client_id
)
87 // This const typecast is safe.
88 proxy_ ((ACE_Token_Proxy
*) new_proxy
),
92 ACE_TRACE ("ACE_TPQ_Entry::ACE_TPQ_Entry");
95 this->client_id (client_id
);
98 // Just make sure we have enough space.
99 ACE_TCHAR host_name
[MAXHOSTNAMELEN
];
100 ACE_TCHAR name
[(sizeof host_name
/ sizeof (ACE_TCHAR
)) + 256];
101 ACE_OS::hostname (host_name
, sizeof host_name
);
103 ACE_thread_t thread_id
= ACE_Thread::self ();
105 // The cast is an attempt to get this to compile (and run,
106 // hopefully) regardless of the type of ACE_thread_t.
107 ACE_OS::snprintf (name
, sizeof name
/ sizeof name
[0],
108 ACE_TEXT ("/%s/%u/%lu"),
110 static_cast<u_int
> (ACE_OS::getpid ()),
111 *reinterpret_cast<u_long
*> (&thread_id
));
113 this->client_id (name
);
117 ACE_TPQ_Entry::ACE_TPQ_Entry ()
123 ACE_TRACE ("ACE_TPQ_Entry::ACE_TPQ_Entry null const.");
126 ACE_TPQ_Entry::ACE_TPQ_Entry (const ACE_TPQ_Entry
&rhs
)
129 ACE_TRACE ("ACE_TPQ_Entry::ACE_TPQ_Entry copy const.");
133 ACE_TPQ_Entry::~ACE_TPQ_Entry ()
135 ACE_TRACE ("ACE_TPQ_Entry::~ACE_TPQ_Entry");
139 ACE_TPQ_Entry::operator= (const ACE_TPQ_Entry
& rhs
)
141 ACE_TRACE ("ACE_TPQ_Entry::operator=");
144 this->proxy_
= rhs
.proxy ();
145 this->nesting_level_
= rhs
.nesting_level ();
146 this->client_id (rhs
.client_id ());
147 this->sleep_hook_
= rhs
.sleep_hook ();
151 ACE_TPQ_Entry::client_id (const ACE_TCHAR
*id
)
153 ACE_TRACE ("ACE_TPQ_Entry::client_id");
158 ACE_OS::strsncpy (this->client_id_
,
164 ACE_TSS_TPQ_Entry::dump () const
166 #if defined (ACE_HAS_DUMP)
167 ACE_TRACE ("ACE_TSS_TPQ_Entry::dump");
168 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
169 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_TSS_TPQ_Entry::dump:\n")
170 ACE_TEXT (" client_id_ = %s\n"),
171 client_id_
== 0 ? ACE_TEXT ("0") : client_id_
));
172 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("base:\n")));
173 ACE_TPQ_ENTRY::dump ();
174 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
175 #endif /* ACE_HAS_DUMP */
178 ACE_TSS_TPQ_Entry::ACE_TSS_TPQ_Entry (const ACE_Token_Proxy
*proxy
,
179 const ACE_TCHAR
*client_id
)
181 client_id_ (client_id
)
183 ACE_TRACE ("ACE_TSS_TPQ_Entry::ACE_TSS_TPQ_Entry");
187 ACE_TSS_TPQ_Entry::make_TSS_TYPE () const
189 ACE_TRACE ("ACE_TSS_TPQ_Entry::make_TSS_TYPE");
192 ACE_NEW_RETURN (temp
,
193 ACE_TPQ_Entry (this->proxy_
,
199 ACE_TSS_TPQ_Entry::operator ACE_TPQ_Entry
* ()
201 #if !defined (ACE_NO_TSS_TOKENS)
202 return (ACE_TPQ_Entry
*) (*((ACE_TSS
<ACE_TPQ_Entry
> *) this));
204 // Not sure this is the right thing to do, but it seems to work.
205 // The base class ALSO has a proxy_ and client_id_ members (weird?)
206 // which don't get initialised. The following two lines make this
207 // the same as the subclass, so that the slicing works .
208 ACE_TPQ_ENTRY::proxy ((ACE_Token_Proxy
*)(this->proxy_
));
209 ACE_TPQ_ENTRY::client_id (this->client_id_
);
210 return (ACE_TPQ_Entry
*) this;
211 #endif /* !ACE_NO_TSS_TOKENS */
214 ACE_TPQ_Iterator::ACE_TPQ_Iterator (ACE_Token_Proxy_Queue
&q
)
217 ACE_TRACE ("ACE_TPQ_Iterator::ACE_TPQ_Iterator");
221 ACE_TPQ_Iterator::next (ACE_TPQ_Entry
*&next_item
)
223 ACE_TRACE ("ACE_TPQ_Iterator::next");
225 next_item
= this->current_
;
227 return current_
!= 0;
231 ACE_TPQ_Iterator::done () const
233 ACE_TRACE ("ACE_TPQ_Iterator::done");
235 return this->current_
== 0;
239 ACE_TPQ_Iterator::advance ()
241 ACE_TRACE ("ACE_TPQ_Iterator::advance");
244 this->current_
= this->current_
->next_
;
248 ACE_TPQ_Iterator::dump () const
250 #if defined (ACE_HAS_DUMP)
251 ACE_TRACE ("ACE_TPQ_Iterator::dump");
252 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
253 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_TPQ_Iterator::dump:\n")
254 ACE_TEXT (" current_ = %d\n"),
255 (long) this->current_
));
256 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("head_ and tail_\n")));
257 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
258 #endif /* ACE_HAS_DUMP */
262 ACE_Token_Proxy_Queue::dump () const
264 #if defined (ACE_HAS_DUMP)
265 ACE_TRACE ("ACE_Token_Proxy_Queue::dump");
266 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
267 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Token_Proxy_Queue::dump:\n")
268 ACE_TEXT (" size_ = %d\n"),
270 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("head_ and tail_\n")));
271 if (this->head_
!= 0)
272 this->head_
->dump ();
274 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Token_Proxy_Queue::dump end.\n")));
275 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
276 #endif /* ACE_HAS_DUMP */
279 ACE_Token_Proxy_Queue::ACE_Token_Proxy_Queue ()
284 ACE_TRACE ("ACE_Token_Proxy_Queue::ACE_Token_Proxy_Queue");
288 ACE_Token_Proxy_Queue::enqueue (ACE_TPQ_Entry
*tpq
,
291 ACE_TRACE ("ACE_Token_Proxy_Queue::enqueue");
296 if (this->head_
== 0)
298 // make tpq the entire list
299 this->head_
= this->tail_
= tpq
;
306 tpq
->next_
= this->head_
;
313 // stick at back of list
314 this->tail_
->next_
= tpq
;
319 // walk through list to insertion point
320 ACE_TPQ_Entry
*temp
= head_
;
322 for (int x
= position
;
327 if (temp
->next_
== 0)
334 // insert new tpq after temp
335 tpq
->next_
= temp
->next_
;
340 ACE_Token_Proxy_Queue::dequeue ()
342 ACE_TRACE ("ACE_Token_Proxy_Queue::dequeue");
347 ACE_TPQ_Entry
*temp
= this->head_
;
349 this->head_
= this->head_
->next_
;
355 if (this->head_
== 0 && this->size_
!= 0)
356 ACELIB_ERROR ((LM_ERROR
,
357 ACE_TEXT ("incorrect size = %d\n"),
363 ACE_Token_Proxy_Queue::member (const ACE_TCHAR *id)
365 ACE_TRACE ("ACE_Token_Proxy_Queue::member");
367 for (ACE_TPQ_Entry *temp = this->head_;
370 if (ACE_OS::strcmp (temp->client_id (), id) == 0)
374 // We didn't find it :-(
380 ACE_Token_Proxy_Queue::remove (const ACE_TPQ_Entry
*remove_me
)
382 ACE_TRACE ("ACE_Token_Proxy_Queue::remove");
384 if ((remove_me
== 0) || (this->head_
== 0))
388 if (this->head_
== remove_me
) // pointer comparison.
390 this->head_
= this->head_
->next_
;
391 if (this->head_
== 0)
398 ACE_TPQ_Entry
*temp
= this->head_
;
399 ACE_TPQ_Entry
*previous
= 0;
401 // is it in the middle or tail?
404 if (temp
== remove_me
)
406 // previous should never be null since the first if
407 // conditional should always be false
408 previous
->next_
= temp
->next_
;
410 if (this->tail_
== temp
)
411 this->tail_
= previous
;
421 // it wasn't in the list.
426 ACE_Mutex_Token::dump () const
428 #if defined (ACE_HAS_DUMP)
429 ACE_TRACE ("ACE_Mutex_Token::dump");
430 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
431 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Mutex_Token::dump:\n")));
432 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("lock_\n")));
434 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("base:\n")));
436 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Mutex_Token::dump end.\n")));
437 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
438 #endif /* ACE_HAS_DUMP */
441 ACE_Mutex_Token::ACE_Mutex_Token (const ACE_TCHAR
*name
)
443 ACE_TRACE ("ACE_Mutex_Token::ACE_Mutex_Token");
445 ACE_OS::strsncpy (this->token_name_
,
447 ACE_MAXTOKENNAMELEN
);
450 ACE_Mutex_Token::~ACE_Mutex_Token ()
452 ACE_TRACE ("ACE_Mutex_Token::~ACE_Mutex_Token");
456 ACE_Mutex_Token::acquire (ACE_TPQ_Entry
*caller
,
460 ACE_TRACE ("ACE_Mutex_Token::acquire");
461 // We need to acquire two locks. This one to ensure that only one
462 // thread uses this token at a time.
463 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon1
, this->lock_
, -1);
464 // This one to ensure an atomic transaction across all tokens. Note
465 // that this order is crucial too. It's resource coloring for other
466 // threads which may be calling this same token.
467 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon2
, ACE_Token_Manager::instance ()->mutex (), -1);
469 // Does _anyone_ own the token?
470 if (this->owner () == 0)
472 // there are no waiters, so queue as the first waiter (the owner.)
473 this->waiters_
.enqueue (caller
, -1);
477 // Does the caller already own it?
478 if (this->is_owner (caller
->client_id ()))
480 // Recursive acquisition.
481 caller
->nesting_level (1);
485 // Check for deadlock.
487 && ACE_Token_Manager::instance ()->check_deadlock (caller
->proxy ()) == 1)
493 // Someone owns it. Sorry, you're getting queued up at the end of
495 this->waiters_
.enqueue (caller
, -1);
498 this->owner ()->call_sleep_hook ();
503 ACE_NOTREACHED (return -1);
507 ACE_Mutex_Token::tryacquire (ACE_TPQ_Entry
*caller
)
509 ACE_TRACE ("ACE_Mutex_Token::tryacquire");
510 // We need to acquire two locks. This one to ensure that only one
511 // thread uses this token at a time.
512 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon1
, this->lock_
, -1);
513 // This one to ensure an atomic transaction across all tokens. Note
514 // that this order is crucial too. It's resource coloring for other
515 // threads which may be calling this same token.
516 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon2
, ACE_Token_Manager::instance ()->mutex (), -1);
518 // Does _anyone_ own the token?
519 if (this->owner () == 0)
521 this->waiters_
.enqueue (caller
, -1);
524 // Does the caller already own it?
525 if (this->is_owner (caller
->client_id ()))
527 // recursive acquisition
528 caller
->nesting_level (1);
532 // Someone owns it. Fail.
538 ACE_NOTREACHED (return -1);
542 ACE_Mutex_Token::renew (ACE_TPQ_Entry
*caller
,
543 int requeue_position
)
545 ACE_TRACE ("ACE_Mutex_Token::renew");
546 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon
, this->lock_
, -1);
548 // Verify that the caller is the owner.
549 if (this->is_owner (caller
->client_id ()) == 0)
555 // The caller is the owner, so check to see if there are any
556 // waiters. If not, we just keep the token. == 1 means that there
557 // is only the owner.
558 if (this->waiters_
.size () == 1 || requeue_position
== 0)
561 // Requeue the caller.
562 this->waiters_
.dequeue ();
564 this->waiters_
.enqueue (caller
, requeue_position
);
567 if (this->owner () != 0)
568 this->owner ()->proxy ()->token_acquired (this->owner ());
570 // Tell the caller that the operation would block.
574 ACE_NOTREACHED (return -1);
577 // Release the current holder of the token (which had
578 // better be the caller's thread!).
581 ACE_Mutex_Token::release (ACE_TPQ_Entry
*caller
)
583 ACE_TRACE ("ACE_Mutex_Token::release");
584 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon
, this->lock_
, -1);
586 // Does anyone own the token?
587 if (this->owner () == 0)
593 // Is the caller the owner.
594 if (this->is_owner (caller
->client_id ()))
596 // Check the nesting level.
597 if (caller
->nesting_level () > 0)
598 caller
->nesting_level (-1);
601 this->waiters_
.dequeue ();
603 if (this->owner () != 0)
604 this->owner ()->proxy ()->token_acquired (this->owner ());
608 this->remove (caller
);
614 ACE_Mutex_Token::owners (OWNER_STACK
&stack
,
617 ACE_TRACE ("ACE_Mutex_Token::owners");
618 if (this->owner () != 0)
620 stack
.push (this->owner ());
621 // If an <id> is specified, return whether it is the owner being
624 return this->owner ()->equal_client_id (id
);
631 ACE_Mutex_Token::is_waiting_for (const ACE_TCHAR
*id
)
633 ACE_TRACE ("ACE_Mutex_Token::is_waiting_for");
634 // If there is no owner, or <id> is the owner, return false.
635 if ((this->owner () == 0) || this->is_owner (id
))
638 // Step through each waiter looking for <id>.
639 ACE_TPQ_Iterator
iterator (waiters_
);
641 for (ACE_TPQ_Entry
*temp
= 0;
642 iterator
.next (temp
) != 0;
645 if (temp
->equal_client_id (id
))
653 ACE_Mutex_Token::is_owner (const ACE_TCHAR
*id
)
655 ACE_TRACE ("ACE_Mutex_Token::is_owner");
656 // If there is an owner, return whether it is <id>.
657 if ((this->owner () != 0) &&
658 this->owner ()->equal_client_id (id
))
665 ACE_Mutex_Token::type () const
667 ACE_TRACE ("ACE_Mutex_Token::type");
668 return (int) ACE_Tokens::MUTEX
;
671 // ************************************************************
674 ACE_RW_Token::type () const
676 ACE_TRACE ("ACE_RW_Token::type");
677 return (int) ACE_Tokens::RWLOCK
;
681 ACE_RW_Token::dump () const
683 #if defined (ACE_HAS_DUMP)
684 ACE_TRACE ("ACE_RW_Token::dump");
685 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
686 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_RW_Token::dump:\n")
687 ACE_TEXT ("num_writers_ = %d\n"), num_writers_
));
688 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("lock_\n")));
690 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("base:\n")));
692 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_RW_Token::dump end.\n")));
693 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
694 #endif /* ACE_HAS_DUMP */
697 ACE_RW_Token::ACE_RW_Token (const ACE_TCHAR
*name
)
700 ACE_TRACE ("ACE_RW_Token::ACE_RW_Token");
702 ACE_OS::strsncpy (this->token_name_
,
704 ACE_MAXTOKENNAMELEN
);
707 ACE_RW_Token::~ACE_RW_Token ()
709 ACE_TRACE ("ACE_RW_Token::~ACE_RW_Token");
713 ACE_RW_Token::acquire (ACE_TPQ_Entry
*caller
,
717 ACE_TRACE ("ACE_RW_Token::acquire");
718 // We need to acquire two locks. This one to ensure that only one
719 // thread uses this token at a time.
720 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon1
, this->lock_
, -1);
721 // This one to ensure an atomic transaction across all tokens. Note
722 // that this order is crucial too. It's resource coloring for other
723 // threads which may be calling this same token.
724 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon2
, ACE_Token_Manager::instance ()->mutex (), -1);
726 if (caller
->proxy ()->type () == ACE_RW_Token::WRITER
)
727 this->num_writers_
++;
729 // Does _anyone_ own the token?
730 if (this->owner () == 0)
732 // There are no waiters, so queue as the first waiter (the owner).
733 this->waiters_
.enqueue (caller
, -1);
737 // Check for recursive acquisition.
738 if (this->is_owner (caller
->client_id ()))
740 caller
->nesting_level (1);
741 return 0; // Success.
745 if (caller
->proxy ()->type () == ACE_RW_Token::READER
)
747 // Are there any writers?
748 if (this->num_writers_
== 0)
750 // Queue the caller at the end of the queue.
751 this->waiters_
.enqueue (caller
, -1);
759 // Check for deadlock.
760 if (!ignore_deadlock
&&
761 ACE_Token_Manager::instance ()->check_deadlock (caller
->proxy ()) == 1)
763 if (caller
->proxy ()->type () == ACE_RW_Token::WRITER
)
764 this->num_writers_
--;
769 // Queue the caller at the end of the queue.
770 this->waiters_
.enqueue (caller
, -1);
774 // If it's a writer, just notify it.
775 if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER
)
776 this->owner ()->call_sleep_hook ();
779 // Call back all reader owners.
780 ACE_TPQ_Entry
*temp
= this->owner ();
783 temp
->call_sleep_hook ();
787 temp
->proxy ()->type () == ACE_RW_Token::READER
);
794 ACE_NOTREACHED (return -1);
798 ACE_RW_Token::tryacquire (ACE_TPQ_Entry
*caller
)
800 ACE_TRACE ("ACE_RW_Token::tryacquire");
801 // We need to acquire two locks. This one to ensure that only one
802 // thread uses this token at a time.
803 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon1
, this->lock_
, -1);
804 // This one to ensure an atomic transaction across all tokens. Note
805 // that this order is crucial too. It's resource coloring for other
806 // threads which may be calling this same token.
807 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon2
, ACE_Token_Manager::instance ()->mutex (), -1);
809 if (caller
->proxy ()->type () == ACE_RW_Token::WRITER
)
811 this->num_writers_
++;
814 // Does _anyone_ own the token?
815 if (this->owner () == 0)
817 // There are no waiters, so queue as the first waiter (the owner).
818 this->waiters_
.enqueue (caller
, -1);
822 // Check for recursive acquisition.
823 if (this->is_owner (caller
->client_id ()))
825 caller
->nesting_level (1);
826 return 0; // Success.
830 if (caller
->proxy ()->type () == ACE_RW_Token::READER
)
832 // Are there any writers?
833 if (this->num_writers_
== 0)
835 // queue the caller at the end of the queue.
836 this->waiters_
.enqueue (caller
, -1);
842 // We're going to fail, so decrement the num_writers.
844 this->num_writers_
--;
851 ACE_NOTREACHED (return -1);
855 ACE_RW_Token::renew (ACE_TPQ_Entry
*caller
,
856 int requeue_position
)
858 ACE_TRACE ("ACE_RW_Token::renew");
859 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon
, this->lock_
, -1);
861 // Werify that the caller is the owner
862 if (this->is_owner (caller
->client_id ()) == 0)
868 // The caller is the owner, so check to see if there are any
869 // waiters. If not, we just keep the token.
870 if (this->waiters_
.size () == 1 || requeue_position
== 0)
873 // There are waiters, so remove the caller.
874 this->remove (caller
);
876 // Requeue the caller.
877 this->waiters_
.enqueue (caller
, requeue_position
);
879 if (caller
->proxy ()->type () == ACE_RW_Token::READER
)
881 // If the caller got queued before any writers, the caller is
883 if (this->is_owner (caller
->client_id ()))
885 // else fallthrough and return would block.
887 // Writers will always have to block since waiters_.size () == 1 or
888 // requeue_position == 0.
891 this->notify_new_owner (caller
);
893 // Tell the caller that the operation would block.
897 ACE_NOTREACHED (return -1);
901 ACE_RW_Token::release (ACE_TPQ_Entry
*caller
)
903 ACE_TRACE ("ACE_RW_Token::release");
904 ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX
, ace_mon
, this->lock_
, -1);
907 if ((this->owner () == 0) ||
908 (this->is_owner (caller
->client_id ()) == 0))
914 if (caller
->proxy ()->type () == ACE_RW_Token::WRITER
)
917 // Recursive release.
918 if (caller
->nesting_level () > 0)
920 caller
->nesting_level (-1);
924 // Remove the caller and notify the new owner(s).
925 this->remove (caller
);
926 this->notify_new_owner (caller
);
932 ACE_RW_Token::notify_new_owner (ACE_TPQ_Entry
*old_owner
)
934 ACE_TRACE ("ACE_RW_Token::notify_new_owner");
936 if (this->owner () == 0)
939 if (this->owner ()->proxy ()->type () == ACE_RW_Token::READER
)
941 if (old_owner
->proxy ()->type () == ACE_RW_Token::READER
)
942 // the owners already know that they're owners
945 // The current owner is a reader and the previous owner was a
946 // writer, so notify all waiting readers up to the first writer.
947 // call back all reader owners.
948 ACE_TPQ_Iterator
iterator (waiters_
);
949 for (ACE_TPQ_Entry
*temp
= 0;
950 iterator
.next (temp
) != 0;
953 if (temp
->proxy ()->type () == WRITER
)
954 // We've gone through all the readers.
957 temp
->proxy ()->token_acquired (temp
);
961 this->owner ()->proxy ()->token_acquired (this->owner ());
966 ACE_RW_Token::owners (OWNER_STACK
&stack
,
969 ACE_TRACE ("ACE_RW_Token::owners");
971 if (this->owner () == 0)
976 // The first waiter is a writer, so there is only one owner.
977 if (this->owner ()->proxy ()->type () == WRITER
)
979 stack
.push (this->owner ());
980 // If an <id> is specified, return whether it is the owner being
983 (ACE_OS::strcmp (id
, this->owner ()->client_id ()) == 0))
986 // The first waiter is a reader, so there can be multiple owning
990 ACE_TPQ_Iterator
iterator (waiters_
);
991 for (ACE_TPQ_Entry
*temp
= 0;
992 iterator
.next (temp
) != 0;
995 if (temp
->proxy ()->type () == WRITER
)
996 // We've gone through all the readers.
1001 if (!id_is_owner
&& (id
!= 0) &&
1002 (ACE_OS::strcmp (id
, temp
->client_id ()) == 0))
1011 ACE_RW_Token::is_waiting_for (const ACE_TCHAR
*id
)
1013 ACE_TRACE ("ACE_RW_Token::is_waiting_for");
1014 // If there is no owner, or <id> is the owner, return false.
1015 if ((this->owner () == 0) ||
1016 this->is_owner (id
))
1019 // Step through each waiter looking for <id>.
1020 ACE_TPQ_Iterator
iterator (waiters_
);
1021 iterator
.advance ();
1022 for (ACE_TPQ_Entry
*temp
= 0;
1023 iterator
.next (temp
) != 0;
1024 iterator
.advance ())
1026 if (temp
->equal_client_id (id
))
1034 ACE_RW_Token::is_owner (const ACE_TCHAR
*id
)
1036 ACE_TRACE ("ACE_RW_Token::is_owner");
1037 // If there is no owner, return false.
1038 if (this->owner () == 0)
1041 // A writer owns us.
1042 if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER
)
1043 return this->owner ()->equal_client_id (id
);
1046 // Step through each owning reader looking for <id>.
1047 ACE_TPQ_Iterator
iterator (waiters_
);
1048 for (ACE_TPQ_Entry
*temp
= 0;
1049 iterator
.next (temp
) != 0;
1050 iterator
.advance ())
1052 if (temp
->proxy ()->type () != ACE_RW_Token::READER
)
1055 if (temp
->equal_client_id (id
))
1063 ACE_Token_Proxy::dump () const
1065 #if defined (ACE_HAS_DUMP)
1066 ACE_TRACE ("ACE_Token_Proxy::dump");
1067 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
1068 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Token_Proxy::dump:\n")
1069 ACE_TEXT (" type = %d\n")
1070 ACE_TEXT (" ignore_deadlock_ = %d\n")
1071 ACE_TEXT (" debug_ = %d\n"),
1072 (int) this->type (), ignore_deadlock_
, debug_
));
1073 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("mutex_, and waiter_\n")));
1075 if (this->token_
!= 0)
1076 this->token_
->dump ();
1078 this->waiter_
.dump ();
1079 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Token_Proxy::dump end.\n")));
1080 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
1081 #endif /* ACE_HAS_DUMP */
1085 ACE_Token_Proxy::client_id () const
1087 ACE_TRACE ("ACE_Token_Proxy::client_id");
1089 const ACE_TPQ_Entry
*temp
= this->waiter_
.operator->();
1090 const ACE_TCHAR
*id
= temp
->client_id ();
1093 return ACE_TEXT ("ERROR NO CLIENT ID");
1099 ACE_Token_Proxy::client_id (const ACE_TCHAR
*client_id
)
1101 ACE_TRACE ("ACE_Token_Proxy::client_id");
1102 this->waiter_
->client_id (client_id
);
1106 ACE_Token_Proxy::owner_id ()
1108 ACE_TRACE ("ACE_Token_Proxy::owner_id");
1109 return this->token_
->owner_id ();
1113 ACE_Token_Proxy::name () const
1115 ACE_TRACE ("ACE_Token_Proxy::name");
1116 return this->token_
->name ();
1119 #if defined (_MSC_VER)
1120 # pragma warning (push)
1121 # pragma warning (disable:4355) /* Use of 'this' in initializer list */
1123 ACE_Token_Proxy::ACE_Token_Proxy ()
1127 ACE_TRACE ("ACE_Token_Proxy::ACE_Token_Proxy");
1130 // Notice the token_ (0). Do *not* copy the token pointer. This must
1131 // be obtained through the token manager. Also, we don't copy any
1132 // waiter info. A copied Proxy does *not* inherit client_id.
1134 ACE_Token_Proxy::ACE_Token_Proxy (const ACE_Token_Proxy
&)
1138 ACE_TRACE ("ACE_Token_Proxy::ACE_Token_Proxy");
1140 #if defined (_MSC_VER)
1141 # pragma warning (pop)
1144 // @@ should I do a mutex_->release ()?
1145 ACE_Token_Proxy::~ACE_Token_Proxy ()
1147 ACE_TRACE ("ACE_Token_Proxy::~ACE_Token_Proxy");
1150 // notify token manager that we are done with it so it can
1151 // free it if necessary
1152 ACE_Token_Manager::instance ()->release_token (token_
);
1156 ACE_Token_Proxy::open (const ACE_TCHAR
*token_name
,
1157 int ignore_deadlock
,
1160 ACE_TRACE ("ACE_Token_Proxy::open");
1162 // Store some parameters.
1163 this->ignore_deadlock_
= ignore_deadlock
;
1164 this->debug_
= debug
;
1166 // Used in case a name was not specified.
1167 ACE_TCHAR name
[BUFSIZ
];
1169 // We must have a name.
1170 if (token_name
== 0)
1172 ACE_OS::snprintf (name
, BUFSIZ
, ACE_TEXT ("token %lx"),
1173 reinterpret_cast<long> (this));
1177 // Get or create the underlying token. The Token Manager will call
1178 // us back to set token_.
1179 ACE_Token_Manager::instance ()->get_token (this, token_name
);
1181 // Check for failed get or failed new.
1182 if (this->token_
== 0)
1185 ACELIB_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("Can't allocate mutex")), -1);
1192 ACE_Token_Proxy::acquire (int notify
,
1193 void (*sleep_hook
)(void *),
1194 ACE_Synch_Options
&options
)
1196 ACE_TRACE ("ACE_Token_Proxy::acquire");
1197 if (this->token_
== 0)
1200 ACELIB_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("Not open.\n")), -1);
1203 // Make sure no one calls our token_acquired until we have a chance
1204 // to sleep first! If after we call an EWOULDBLOCK
1205 // mutex_->acquire() below, but before we enter handle_options to
1206 // wait on the cond_var, a thread tries to give take us off the
1207 // waiter queue and signal us, IT WILL FIRST HAVE TO ACQUIRE THIS
1208 // cond_var.mutex (). _This_ is why we acquire it.
1209 this->waiter_
->cond_var_
.mutex ().acquire ();
1211 this->waiter_
->sleep_hook (sleep_hook
);
1213 if (this->token_
->acquire (this->waiter_
, this->ignore_deadlock_
, notify
) == -1)
1219 if (!ignore_deadlock_
)
1221 waiter_
->cond_var_
.mutex ().release ();
1225 // Else, fallthrough and block!
1230 ACELIB_DEBUG ((LM_DEBUG
,
1231 ACE_TEXT ("(%t) waiting for %s, owner is %s, ")
1232 ACE_TEXT ("total waiters == %d\n"),
1234 this->token_
->owner_id (),
1235 token_
->no_of_waiters ()));
1237 // no error, but would block, if error, return error (-1),
1238 // otherwise, return whether we called the holder or not.
1240 if (this->handle_options (options
,
1241 waiter_
->cond_var_
) == -1)
1244 return_value
= notify
== 1;
1246 errno
= EWOULDBLOCK
;
1247 ACE_RETURN (return_value
);
1250 waiter_
->cond_var_
.mutex ().release ();
1251 ACELIB_ERROR_RETURN ((LM_ERROR
,
1253 ACE_TEXT ("Token Proxy acquire.")),
1258 // we have the token
1261 ACELIB_DEBUG ((LM_DEBUG
,
1262 ACE_TEXT ("(%t) acquired %s\n"),
1264 waiter_
->cond_var_
.mutex ().release ();
1271 ACE_Token_Proxy::tryacquire (void (*sleep_hook
)(void *))
1273 ACE_TRACE ("ACE_Token_Proxy::tryacquire");
1274 if (this->token_
== 0)
1277 ACELIB_ERROR_RETURN ((LM_ERROR
,
1278 ACE_TEXT ("Not open.\n")),
1282 this->waiter_
->sleep_hook (sleep_hook
);
1284 return this->token_
->tryacquire (waiter_
);
1288 ACE_Token_Proxy::renew (int requeue_position
,
1289 ACE_Synch_Options
&options
)
1291 ACE_TRACE ("ACE_Token_Proxy::renew");
1292 if (this->token_
== 0)
1295 ACELIB_ERROR_RETURN ((LM_ERROR
,
1296 ACE_TEXT ("Not open.\n")),
1300 // Make sure no one calls our token_acquired until we have a chance
1302 this->waiter_
->cond_var_
.mutex ().acquire ();
1304 if (this->token_
->renew (this->waiter_
, requeue_position
) == -1)
1307 if (errno
!= EWOULDBLOCK
)
1308 ACELIB_ERROR_RETURN ((LM_ERROR
,
1309 ACE_TEXT ("%p renew failed\n"), ACE_TEXT ("ACE_Token_Proxy")), -1);
1312 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) renew blocking for %s, owner is %s\n"),
1314 token_
->owner_id ()));
1316 // no error, but would block, so block or return
1317 return this->handle_options (options
, waiter_
->cond_var_
);
1320 // we have the token
1323 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) renewed %s\n"),
1325 waiter_
->cond_var_
.mutex ().release ();
1331 ACE_Token_Proxy::handle_options (ACE_Synch_Options
&options
,
1332 ACE_TOKEN_CONST::COND_VAR
&cv
)
1334 // Some operation failed with EWOULDBLOCK.
1335 ACE_TRACE ("ACE_Token_Proxy::handle_options");
1337 if (options
[ACE_Synch_Options::USE_REACTOR
] == 1)
1340 // Save/restore errno.
1341 ACE_Errno_Guard
error (errno
);
1342 cv
.mutex ().release ();
1348 // Block on condition variable.
1349 while (cv
.wait ((ACE_Time_Value
*) options
.time_value ()) == -1)
1351 // Note, this should obey whatever thread-specific
1352 // interrupt policy is currently in place...
1355 // We come here if a timeout occurs or some serious
1356 // ACE_Condition object error.
1357 cv
.mutex ().release ();
1358 ACELIB_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("condition variable wait")
1359 ACE_TEXT (" bombed.")), -1);
1363 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) unblocking %s.\n"),
1364 this->client_id ()));
1365 cv
.mutex ().release ();
1366 return 0; // operation succeeded
1371 ACE_Token_Proxy::release (ACE_Synch_Options
&)
1373 ACE_TRACE ("ACE_Token_Proxy::release");
1375 if (this->token_
== 0)
1379 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("Must open before releasing.\n")));
1383 if (this->token_
->release (waiter_
) != 0)
1386 this->token_
->remove (this->waiter_
);
1388 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) %p.\n"), ACE_TEXT ("release failed")));
1394 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%t) released %s, owner is %s\n"),
1396 token_
->owner_id ()));
1403 ACE_Token_Proxy::remove (ACE_Synch_Options
&)
1405 ACE_TRACE ("ACE_Token_Proxy::remove");
1410 ACE_Token_Proxy::sleep_hook ()
1412 ACE_TRACE ("ACE_Token_Proxy::sleep_hook");
1413 // Somebody wants our token! (Let'em wait...)
1418 ACE_Token_Proxy::token_acquired (ACE_TPQ_Entry
*e
)
1420 ACE_TRACE ("ACE_Token_Proxy::token_acquired");
1421 e
->cond_var_
.mutex ().acquire ();
1422 // We've been taken off the waiters list and given the token!
1423 // This implementation signals the internal condition
1424 // variable. Thus, if asynchronous acquires are used, this must be
1425 // overriden to do something more useful!
1426 e
->cond_var_
.signal ();
1427 e
->cond_var_
.mutex ().release ();
1433 ACE_Token_Proxy::type () const
1435 ACE_TRACE ("ACE_Token_Proxy::type");
1440 ACE_Token_Proxy::acquire_read (int notify
,
1441 void (*sleep_hook
)(void *),
1442 ACE_Synch_Options
&options
)
1444 return this->acquire (notify
,
1450 ACE_Token_Proxy::acquire_write (int notify
,
1451 void (*sleep_hook
)(void *),
1452 ACE_Synch_Options
&options
)
1454 return this->acquire (notify
,
1460 ACE_Token_Proxy::tryacquire_read (void (*sleep_hook
)(void *))
1462 return this->tryacquire (sleep_hook
);
1466 ACE_Token_Proxy::tryacquire_write (void (*sleep_hook
)(void *))
1468 return this->tryacquire (sleep_hook
);
1471 ACE_Token_Name::ACE_Token_Name (const ACE_TCHAR
*token_name
)
1473 ACE_TRACE ("ACE_Token_Name::ACE_Token_Name");
1474 this->name (token_name
);
1477 ACE_Token_Name::ACE_Token_Name (const ACE_Token_Name
&rhs
)
1479 ACE_TRACE ("ACE_Token_Name::ACE_Token_Name");
1480 this->name (rhs
.name ());
1483 ACE_Token_Name::~ACE_Token_Name ()
1485 ACE_TRACE ("ACE_Token_Name::~ACE_Token_Name");
1489 ACE_Token_Name::dump () const
1491 #if defined (ACE_HAS_DUMP)
1492 ACE_TRACE ("ACE_Token_Name::dump");
1493 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
1494 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("ACE_Token_Name::dump:\n")
1495 ACE_TEXT (" token_name_ = %s\n"),
1496 token_name_
== 0 ? ACE_TEXT ("no name") : token_name_
));
1497 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
1498 #endif /* ACE_HAS_DUMP */
1501 // ************************************************************
1504 ACE_Local_Mutex::clone () const
1506 ACE_Token_Proxy
*temp
= 0;
1507 ACE_NEW_RETURN (temp
,
1508 ACE_Local_Mutex (token_
->name (),
1516 ACE_Local_Mutex::create_token (const ACE_TCHAR
*name
)
1518 ACE_Tokens
*temp
= 0;
1519 ACE_NEW_RETURN (temp
,
1520 ACE_Mutex_Token (name
),
1525 ACE_Local_Mutex::~ACE_Local_Mutex ()
1529 // ************************************************************
1531 ACE_Local_RLock::~ACE_Local_RLock ()
1536 ACE_Local_RLock::create_token (const ACE_TCHAR
*name
)
1538 ACE_Tokens
*temp
= 0;
1539 ACE_NEW_RETURN (temp
,
1540 ACE_RW_Token (name
),
1546 ACE_Local_RLock::type () const
1548 return ACE_RW_Token::READER
;
1552 ACE_Local_RLock::clone () const
1554 ACE_Token_Proxy
*temp
= 0;
1555 ACE_NEW_RETURN (temp
,
1556 ACE_Local_RLock (token_
->name (),
1563 // ************************************************************
1565 ACE_Local_WLock::~ACE_Local_WLock ()
1570 ACE_Local_WLock::create_token (const ACE_TCHAR
*name
)
1572 ACE_Tokens
*temp
= 0;
1573 ACE_NEW_RETURN (temp
,
1574 ACE_RW_Token (name
),
1580 ACE_Local_WLock::type () const
1582 return ACE_RW_Token::WRITER
;
1586 ACE_Local_WLock::clone () const
1588 ACE_Token_Proxy
*temp
= 0;
1589 ACE_NEW_RETURN (temp
,
1590 ACE_Local_WLock (token_
->name (),
1597 ACE_END_VERSIONED_NAMESPACE_DECL
1599 #endif /* ACE_HAS_TOKENS_LIBRARY */