Merge pull request #2301 from sonndinh/remove-dup-reactor-functions
[ACE_TAO.git] / ACE / ace / TSS_T.cpp
blobc483d468db34c4926112a1317d5b04fe9fee00fa
1 #ifndef ACE_TSS_T_CPP
2 #define ACE_TSS_T_CPP
4 #include "ace/TSS_T.h"
6 #if !defined (ACE_LACKS_PRAGMA_ONCE)
7 # pragma once
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
10 #if !defined (__ACE_INLINE__)
11 #include "ace/TSS_T.inl"
12 #endif /* __ACE_INLINE__ */
14 #include "ace/Thread.h"
15 #include "ace/Log_Category.h"
16 #include "ace/Guard_T.h"
17 #include "ace/OS_NS_stdio.h"
18 #if defined (ACE_HAS_ALLOC_HOOKS)
19 # include "ace/Malloc_Base.h"
20 #endif /* ACE_HAS_ALLOC_HOOKS */
22 #if defined (ACE_HAS_THR_C_DEST)
23 # include "ace/TSS_Adapter.h"
24 #endif /* ACE_HAS_THR_C_DEST */
26 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
28 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_TSS)
30 #if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
31 # if defined (ACE_HAS_THR_C_DEST)
32 extern "C" ACE_Export void ACE_TSS_C_cleanup (void *);
33 # endif /* ACE_HAS_THR_C_DEST */
34 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
36 template <class TYPE>
37 ACE_TSS<TYPE>::~ACE_TSS ()
39 #if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
40 if (this->once_)
42 # if defined (ACE_HAS_THR_C_DEST)
43 ACE_TSS_Adapter *tss_adapter = this->ts_value ();
44 this->ts_value (0);
45 ACE_TSS_C_cleanup (tss_adapter);
46 # else
47 TYPE *ts_obj = this->ts_value ();
48 this->ts_value (0);
49 # if !defined ACE_HAS_LYNXOS_178 || defined ACE_HAS_TSS_EMULATION
50 // A bug in LynxOS-178 causes pthread_setspecific (called from ts_value(0)
51 // above) to call the cleanup function, so we need to avoid calling it here.
52 ACE_TSS<TYPE>::cleanup (ts_obj);
53 # else
54 ACE_UNUSED_ARG (ts_obj);
55 # endif
56 # endif /* ACE_HAS_THR_C_DEST */
58 ACE_OS::thr_key_detach (this->key_);
59 ACE_OS::thr_keyfree (this->key_);
61 #else // defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
62 // We own it, we need to delete it.
63 delete type_;
64 #endif // defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
67 template <class TYPE> TYPE *
68 ACE_TSS<TYPE>::operator-> () const
70 return this->ts_get ();
73 template <class TYPE>
74 ACE_TSS<TYPE>::operator TYPE *() const
76 return this->ts_get ();
79 template <class TYPE> TYPE *
80 ACE_TSS<TYPE>::make_TSS_TYPE () const
82 TYPE *temp = 0;
83 ACE_NEW_RETURN (temp,
84 TYPE,
85 0);
86 return temp;
89 template <class TYPE> void
90 ACE_TSS<TYPE>::dump () const
92 #if defined (ACE_HAS_DUMP)
93 #if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
94 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
95 this->keylock_.dump ();
96 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %d\n"), this->key_));
97 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nonce_ = %d\n"), this->once_));
98 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
99 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
100 #endif /* ACE_HAS_DUMP */
103 #if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
105 template <class TYPE> void
106 ACE_TSS<TYPE>::cleanup (void *ptr)
108 // Cast this to the concrete TYPE * so the destructor gets called.
109 delete (TYPE *) ptr;
112 template <class TYPE> int
113 ACE_TSS<TYPE>::ts_init ()
115 // Ensure that we are serialized!
116 ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->keylock_, 0);
118 // Use the Double-Check pattern to make sure we only create the key
119 // once!
120 if (!this->once_)
122 if (ACE_Thread::keycreate (&this->key_,
123 #if defined (ACE_HAS_THR_C_DEST)
124 &ACE_TSS_C_cleanup
125 #else
126 &ACE_TSS<TYPE>::cleanup
127 #endif /* ACE_HAS_THR_C_DEST */
128 ) != 0)
129 return -1; // Major problems, this should *never* happen!
130 else
132 // This *must* come last to avoid race conditions!
133 this->once_ = true;
134 return 0;
138 return 0;
141 template <class TYPE>
142 ACE_TSS<TYPE>::ACE_TSS (TYPE *ts_obj)
143 : once_ (false),
144 key_ (ACE_OS::NULL_key)
146 // If caller has passed us a non-NULL TYPE *, then we'll just use
147 // this to initialize the thread-specific value. Thus, subsequent
148 // calls to operator->() will return this value. This is useful
149 // since it enables us to assign objects to thread-specific data
150 // that have arbitrarily complex constructors!
152 if (ts_obj != 0)
154 if (this->ts_init () == -1)
156 // Save/restore errno.
157 ACE_Errno_Guard error (errno);
158 // What should we do if this call fails?!
159 #if !defined (ACE_LACKS_VA_FUNCTIONS)
160 ACE_OS::fprintf (stderr,
161 "ACE_Thread::keycreate() failed!");
162 #endif /* !ACE_LACKS_VA_FUNCTIONS */
163 return;
166 #if defined (ACE_HAS_THR_C_DEST)
167 // Encapsulate a ts_obj and it's destructor in an
168 // ACE_TSS_Adapter.
169 ACE_TSS_Adapter *tss_adapter = 0;
170 ACE_NEW (tss_adapter,
171 ACE_TSS_Adapter ((void *) ts_obj,
172 ACE_TSS<TYPE>::cleanup));
174 // Put the adapter in thread specific storage
175 if (this->ts_value (tss_adapter) == -1)
177 delete tss_adapter;
179 #else
180 this->ts_value (ts_obj);
181 #endif /* ACE_HAS_THR_C_DEST */
185 template <class TYPE> TYPE *
186 ACE_TSS<TYPE>::ts_get () const
188 if (!this->once_)
190 // Create and initialize thread-specific ts_obj.
191 if (const_cast< ACE_TSS < TYPE > * >(this)->ts_init () == -1)
192 // Seriously wrong..
193 return 0;
196 TYPE *ts_obj = 0;
198 #if defined (ACE_HAS_THR_C_DEST)
199 ACE_TSS_Adapter *tss_adapter = this->ts_value ();
200 ACE_TSS_Adapter *fake_tss_adapter = 0;
202 // If tss_adapter is not 0 but its ts_obj_ is 0 then we still need to create
203 // a proper ts_obj. That's the intent of this member function.
204 if (tss_adapter != 0 && tss_adapter->ts_obj_ == 0)
206 fake_tss_adapter = tss_adapter;
207 tss_adapter = 0;
210 // Check to see if this is the first time in for this thread.
211 if (tss_adapter == 0)
212 #else
213 ts_obj = this->ts_value ();
215 // Check to see if this is the first time in for this thread.
216 if (ts_obj == 0)
217 #endif /* ACE_HAS_THR_C_DEST */
219 // Allocate memory off the heap and store it in a pointer in
220 // thread-specific storage (on the stack...).
222 ts_obj = this->make_TSS_TYPE ();
224 if (ts_obj == 0)
225 return 0;
227 #if defined (ACE_HAS_THR_C_DEST)
228 // Encapsulate a ts_obj and it's destructor in an
229 // ACE_TSS_Adapter.
230 ACE_NEW_RETURN (tss_adapter,
231 ACE_TSS_Adapter (ts_obj,
232 ACE_TSS<TYPE>::cleanup), 0);
234 // Put the adapter in thread specific storage
235 if (this->ts_value (tss_adapter) == -1)
237 delete tss_adapter;
238 delete ts_obj;
239 return 0; // Major problems, this should *never* happen!
241 #else
242 // Store the dynamically allocated pointer in thread-specific
243 // storage.
244 if (this->ts_value (ts_obj) == -1)
246 delete ts_obj;
247 return 0; // Major problems, this should *never* happen!
249 #endif /* ACE_HAS_THR_C_DEST */
252 #if defined (ACE_HAS_THR_C_DEST)
253 // Delete the adapter that didn't actually have a real ts_obj.
254 delete fake_tss_adapter;
255 // Return the underlying ts object.
256 return static_cast <TYPE *> (tss_adapter->ts_obj_);
257 #else
258 return ts_obj;
259 #endif /* ACE_HAS_THR_C_DEST */
262 // Get the thread-specific object for the key associated with this
263 // object. Returns 0 if the ts_obj has never been initialized,
264 // otherwise returns a pointer to the ts_obj.
266 template <class TYPE> TYPE *
267 ACE_TSS<TYPE>::ts_object () const
269 if (!this->once_) // Return 0 if we've never been initialized.
270 return 0;
272 TYPE *ts_obj = 0;
274 #if defined (ACE_HAS_THR_C_DEST)
275 ACE_TSS_Adapter *tss_adapter = this->ts_value ();
277 if (tss_adapter != 0)
279 // Extract the real TS object.
280 ts_obj = static_cast <TYPE *> (tss_adapter->ts_obj_);
282 #else
283 ts_obj = this->ts_value ();
284 #endif /* ACE_HAS_THR_C_DEST */
286 return ts_obj;
289 template <class TYPE> TYPE *
290 ACE_TSS<TYPE>::ts_object (TYPE *new_ts_obj)
292 // Note, we shouldn't hold the keylock at this point because
293 // <ts_init> does it for us and we'll end up with deadlock
294 // otherwise...
295 if (!this->once_)
297 // Create and initialize thread-specific ts_obj.
298 if (this->ts_init () == -1)
299 return 0;
302 TYPE *ts_obj = 0;
304 #if defined (ACE_HAS_THR_C_DEST)
305 ACE_TSS_Adapter *tss_adapter = this->ts_value ();
307 if (tss_adapter != 0)
309 ts_obj = static_cast <TYPE *> (tss_adapter->ts_obj_);
310 // Don't delete tss_adapter yet. It can be double-deleted
311 // in case setspecific below fails.
314 ACE_TSS_Adapter *new_tss_adapter = 0;
315 ACE_NEW_RETURN (new_tss_adapter,
316 ACE_TSS_Adapter ((void *) new_ts_obj,
317 ACE_TSS<TYPE>::cleanup),
320 if (this->ts_value (new_tss_adapter) == -1)
322 delete new_tss_adapter;
324 else
326 // Now it's fine to delete the old tss_adapter.
327 delete tss_adapter;
329 #else
330 ts_obj = this->ts_value ();
331 this->ts_value (new_ts_obj);
332 #endif /* ACE_HAS_THR_C_DEST */
334 return ts_obj;
337 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_TSS_Guard)
339 template <class ACE_LOCK> void
340 ACE_TSS_Guard<ACE_LOCK>::dump () const
342 #if defined (ACE_HAS_DUMP)
343 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
344 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %d\n"), this->key_));
345 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
346 #endif /* ACE_HAS_DUMP */
349 template <class ACE_LOCK> void
350 ACE_TSS_Guard<ACE_LOCK>::init_key ()
352 this->key_ = ACE_OS::NULL_key;
353 ACE_Thread::keycreate (&this->key_,
354 #if defined (ACE_HAS_THR_C_DEST)
355 &ACE_TSS_C_cleanup
356 #else
357 &ACE_TSS_Guard<ACE_LOCK>::cleanup
358 #endif /* ACE_HAS_THR_C_DEST */
362 template <class ACE_LOCK>
363 ACE_TSS_Guard<ACE_LOCK>::ACE_TSS_Guard ()
365 this->init_key ();
368 template <class ACE_LOCK> int
369 ACE_TSS_Guard<ACE_LOCK>::release ()
371 Guard_Type *guard = 0;
373 #if defined (ACE_HAS_THR_C_DEST)
374 ACE_TSS_Adapter *tss_adapter = 0;
375 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
376 ACE_Thread::getspecific (this->key_, &temp);
377 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
378 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
379 #else
380 void *temp = guard; // Need this temp to keep G++ from complaining.
381 ACE_Thread::getspecific (this->key_, &temp);
382 guard = static_cast <Guard_Type *> (temp);
383 #endif /* ACE_HAS_THR_C_DEST */
385 return guard->release ();
388 template <class ACE_LOCK> int
389 ACE_TSS_Guard<ACE_LOCK>::remove ()
391 Guard_Type *guard = 0;
393 #if defined (ACE_HAS_THR_C_DEST)
394 ACE_TSS_Adapter *tss_adapter = 0;
395 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
396 ACE_Thread::getspecific (this->key_, &temp);
397 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
398 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
399 #else
400 void *temp = guard; // Need this temp to keep G++ from complaining.
401 ACE_Thread::getspecific (this->key_, &temp);
402 guard = static_cast <Guard_Type *> (temp);
403 #endif /* ACE_HAS_THR_C_DEST */
405 return guard->remove ();
408 template <class ACE_LOCK>
409 ACE_TSS_Guard<ACE_LOCK>::~ACE_TSS_Guard ()
411 Guard_Type *guard = 0;
413 #if defined (ACE_HAS_THR_C_DEST)
414 ACE_TSS_Adapter *tss_adapter = 0;
415 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
416 ACE_Thread::getspecific (this->key_, &temp);
417 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
418 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
419 #else
420 void *temp = guard; // Need this temp to keep G++ from complaining.
421 ACE_Thread::getspecific (this->key_, &temp);
422 guard = static_cast <Guard_Type *> (temp);
423 #endif /* ACE_HAS_THR_C_DEST */
425 // Make sure that this pointer is NULL when we shut down...
426 ACE_Thread::setspecific (this->key_, 0);
427 ACE_Thread::keyfree (this->key_);
428 // Destructor releases lock.
429 delete guard;
432 template <class ACE_LOCK> void
433 ACE_TSS_Guard<ACE_LOCK>::cleanup (void *ptr)
435 // Destructor releases lock.
436 delete (Guard_Type *) ptr;
439 template <class ACE_LOCK>
440 ACE_TSS_Guard<ACE_LOCK>::ACE_TSS_Guard (ACE_LOCK &lock, bool block)
442 this->init_key ();
443 Guard_Type *guard = 0;
444 ACE_NEW (guard,
445 Guard_Type (lock, block));
447 #if defined (ACE_HAS_THR_C_DEST)
448 ACE_TSS_Adapter *tss_adapter = 0;
449 ACE_NEW (tss_adapter,
450 ACE_TSS_Adapter ((void *) guard,
451 ACE_TSS_Guard<ACE_LOCK>::cleanup));
452 ACE_Thread::setspecific (this->key_,
453 (void *) tss_adapter);
454 #else
455 ACE_Thread::setspecific (this->key_,
456 (void *) guard);
457 #endif /* ACE_HAS_THR_C_DEST */
460 template <class ACE_LOCK> int
461 ACE_TSS_Guard<ACE_LOCK>::acquire ()
463 Guard_Type *guard = 0;
465 #if defined (ACE_HAS_THR_C_DEST)
466 ACE_TSS_Adapter *tss_adapter = 0;
467 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
468 ACE_Thread::getspecific (this->key_, &temp);
469 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
470 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
471 #else
472 void *temp = guard; // Need this temp to keep G++ from complaining.
473 ACE_Thread::getspecific (this->key_, &temp);
474 guard = static_cast <Guard_Type *> (temp);
475 #endif /* ACE_HAS_THR_C_DEST */
477 return guard->acquire ();
480 template <class ACE_LOCK> int
481 ACE_TSS_Guard<ACE_LOCK>::tryacquire ()
483 Guard_Type *guard = 0;
485 #if defined (ACE_HAS_THR_C_DEST)
486 ACE_TSS_Adapter *tss_adapter = 0;
487 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
488 ACE_Thread::getspecific (this->key_, &temp);
489 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
490 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
491 #else
492 void *temp = guard; // Need this temp to keep G++ from complaining.
493 ACE_Thread::getspecific (this->key_, &temp);
494 guard = static_cast <Guard_Type *> (temp);
495 #endif /* ACE_HAS_THR_C_DEST */
497 return guard->tryacquire ();
500 template <class ACE_LOCK>
501 ACE_TSS_Write_Guard<ACE_LOCK>::ACE_TSS_Write_Guard (ACE_LOCK &lock,
502 bool block)
504 this->init_key ();
505 Guard_Type *guard = 0;
506 ACE_NEW (guard,
507 Write_Guard_Type (lock, block));
509 #if defined (ACE_HAS_THR_C_DEST)
510 ACE_TSS_Adapter *tss_adapter = 0;
511 ACE_NEW (tss_adapter,
512 ACE_TSS_Adapter ((void *) guard,
513 ACE_TSS_Guard<ACE_LOCK>::cleanup));
514 ACE_Thread::setspecific (this->key_, (void *) tss_adapter);
515 #else
516 ACE_Thread::setspecific (this->key_, (void *) guard);
517 #endif /* ACE_HAS_THR_C_DEST */
520 template <class ACE_LOCK> int
521 ACE_TSS_Write_Guard<ACE_LOCK>::acquire ()
523 Write_Guard_Type *guard = 0;
525 #if defined (ACE_HAS_THR_C_DEST)
526 ACE_TSS_Adapter *tss_adapter = 0;
527 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
528 ACE_Thread::getspecific (this->key_, &temp);
529 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
530 guard = static_cast <Write_Guard_Type *> (tss_adapter->ts_obj_);
531 #else
532 void *temp = guard; // Need this temp to keep G++ from complaining.
533 ACE_Thread::getspecific (this->key_, &temp);
534 guard = static_cast <Write_Guard_Type *> (temp);
535 #endif /* ACE_HAS_THR_C_DEST */
537 return guard->acquire_write ();
540 template <class ACE_LOCK> int
541 ACE_TSS_Write_Guard<ACE_LOCK>::tryacquire ()
543 Write_Guard_Type *guard = 0;
545 #if defined (ACE_HAS_THR_C_DEST)
546 ACE_TSS_Adapter *tss_adapter = 0;
547 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
548 ACE_Thread::getspecific (this->key_, &temp);
549 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
550 guard = static_cast <Write_Guard_Type *> (tss_adapter->ts_obj_);
551 #else
552 void *temp = guard; // Need this temp to keep G++ from complaining.
553 ACE_Thread::getspecific (this->key_, &temp);
554 guard = static_cast <Write_Guard_Type *> (temp);
555 #endif /* ACE_HAS_THR_C_DEST */
557 return guard->tryacquire_write ();
560 template <class ACE_LOCK> int
561 ACE_TSS_Write_Guard<ACE_LOCK>::acquire_write ()
563 return this->acquire ();
566 template <class ACE_LOCK> int
567 ACE_TSS_Write_Guard<ACE_LOCK>::tryacquire_write ()
569 return this->tryacquire ();
572 template <class ACE_LOCK> void
573 ACE_TSS_Write_Guard<ACE_LOCK>::dump () const
575 #if defined (ACE_HAS_DUMP)
576 ACE_TSS_Guard<ACE_LOCK>::dump ();
577 #endif /* ACE_HAS_DUMP */
580 template <class ACE_LOCK>
581 ACE_TSS_Read_Guard<ACE_LOCK>::ACE_TSS_Read_Guard (ACE_LOCK &lock, bool block)
583 this->init_key ();
584 Guard_Type *guard = 0;
585 ACE_NEW (guard,
586 Read_Guard_Type (lock, block));
587 #if defined (ACE_HAS_THR_C_DEST)
588 ACE_TSS_Adapter *tss_adapter;
589 ACE_NEW (tss_adapter,
590 ACE_TSS_Adapter ((void *)guard,
591 ACE_TSS_Guard<ACE_LOCK>::cleanup));
592 ACE_Thread::setspecific (this->key_,
593 (void *) tss_adapter);
594 #else
595 ACE_Thread::setspecific (this->key_,
596 (void *) guard);
597 #endif /* ACE_HAS_THR_C_DEST */
600 template <class ACE_LOCK> int
601 ACE_TSS_Read_Guard<ACE_LOCK>::acquire ()
603 Read_Guard_Type *guard = 0;
605 #if defined (ACE_HAS_THR_C_DEST)
606 ACE_TSS_Adapter *tss_adapter = 0;
607 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
608 ACE_Thread::getspecific (this->key_, &temp);
609 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
610 guard = static_cast <Read_Guard_Type *> (tss_adapter->ts_obj_);
611 #else
612 void *temp = guard; // Need this temp to keep G++ from complaining.
613 ACE_Thread::getspecific (this->key_, &temp);
614 guard = static_cast <Read_Guard_Type *> (temp);
615 #endif /* ACE_HAS_THR_C_DEST */
617 return guard->acquire_read ();
620 template <class ACE_LOCK> int
621 ACE_TSS_Read_Guard<ACE_LOCK>::tryacquire ()
623 Read_Guard_Type *guard = 0;
625 #if defined (ACE_HAS_THR_C_DEST)
626 ACE_TSS_Adapter *tss_adapter = 0;
627 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
628 ACE_Thread::getspecific (this->key_, &temp);
629 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
630 guard = static_cast <Read_Guard_Type *> (tss_adapter->ts_obj_);
631 #else
632 void *temp = guard; // Need this temp to keep G++ from complaining.
633 ACE_Thread::getspecific (this->key_, &temp);
634 guard = static_cast <Read_Guard_Type *> (temp);
635 #endif /* ACE_HAS_THR_C_DEST */
637 return guard->tryacquire_read ();
640 template <class ACE_LOCK> int
641 ACE_TSS_Read_Guard<ACE_LOCK>::acquire_read ()
643 return this->acquire ();
646 template <class ACE_LOCK> int
647 ACE_TSS_Read_Guard<ACE_LOCK>::tryacquire_read ()
649 return this->tryacquire ();
652 template <class ACE_LOCK> void
653 ACE_TSS_Read_Guard<ACE_LOCK>::dump () const
655 #if defined (ACE_HAS_DUMP)
656 ACE_TSS_Guard<ACE_LOCK>::dump ();
657 #endif /* ACE_HAS_DUMP */
660 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
662 ACE_END_VERSIONED_NAMESPACE_DECL
664 #endif /* ACE_TSS_T_CPP */