Revert to Current Include Style
[ACE_TAO.git] / ACE / ace / TSS_T.cpp
blob9d3444c07934118de379c9013ccf802215a55e7b
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_HAS_WINCE)
160 ::MessageBox (0,
161 ACE_TEXT ("ACE_Thread::keycreate() failed!"),
162 ACE_TEXT ("ACE_TSS::ACE_TSS"),
163 MB_OK);
164 #elif !defined (ACE_LACKS_VA_FUNCTIONS)
165 ACE_OS::fprintf (stderr,
166 "ACE_Thread::keycreate() failed!");
167 #endif /* ACE_HAS_WINCE */
168 return;
171 #if defined (ACE_HAS_THR_C_DEST)
172 // Encapsulate a ts_obj and it's destructor in an
173 // ACE_TSS_Adapter.
174 ACE_TSS_Adapter *tss_adapter = 0;
175 ACE_NEW (tss_adapter,
176 ACE_TSS_Adapter ((void *) ts_obj,
177 ACE_TSS<TYPE>::cleanup));
179 // Put the adapter in thread specific storage
180 if (this->ts_value (tss_adapter) == -1)
182 delete tss_adapter;
184 #else
185 this->ts_value (ts_obj);
186 #endif /* ACE_HAS_THR_C_DEST */
190 template <class TYPE> TYPE *
191 ACE_TSS<TYPE>::ts_get () const
193 if (!this->once_)
195 // Create and initialize thread-specific ts_obj.
196 if (const_cast< ACE_TSS < TYPE > * >(this)->ts_init () == -1)
197 // Seriously wrong..
198 return 0;
201 TYPE *ts_obj = 0;
203 #if defined (ACE_HAS_THR_C_DEST)
204 ACE_TSS_Adapter *tss_adapter = this->ts_value ();
205 ACE_TSS_Adapter *fake_tss_adapter = 0;
207 // If tss_adapter is not 0 but its ts_obj_ is 0 then we still need to create
208 // a proper ts_obj. That's the intent of this member function.
209 if (tss_adapter != 0 && tss_adapter->ts_obj_ == 0)
211 fake_tss_adapter = tss_adapter;
212 tss_adapter = 0;
215 // Check to see if this is the first time in for this thread.
216 if (tss_adapter == 0)
217 #else
218 ts_obj = this->ts_value ();
220 // Check to see if this is the first time in for this thread.
221 if (ts_obj == 0)
222 #endif /* ACE_HAS_THR_C_DEST */
224 // Allocate memory off the heap and store it in a pointer in
225 // thread-specific storage (on the stack...).
227 ts_obj = this->make_TSS_TYPE ();
229 if (ts_obj == 0)
230 return 0;
232 #if defined (ACE_HAS_THR_C_DEST)
233 // Encapsulate a ts_obj and it's destructor in an
234 // ACE_TSS_Adapter.
235 ACE_NEW_RETURN (tss_adapter,
236 ACE_TSS_Adapter (ts_obj,
237 ACE_TSS<TYPE>::cleanup), 0);
239 // Put the adapter in thread specific storage
240 if (this->ts_value (tss_adapter) == -1)
242 delete tss_adapter;
243 delete ts_obj;
244 return 0; // Major problems, this should *never* happen!
246 #else
247 // Store the dynamically allocated pointer in thread-specific
248 // storage.
249 if (this->ts_value (ts_obj) == -1)
251 delete ts_obj;
252 return 0; // Major problems, this should *never* happen!
254 #endif /* ACE_HAS_THR_C_DEST */
257 #if defined (ACE_HAS_THR_C_DEST)
258 // Delete the adapter that didn't actually have a real ts_obj.
259 delete fake_tss_adapter;
260 // Return the underlying ts object.
261 return static_cast <TYPE *> (tss_adapter->ts_obj_);
262 #else
263 return ts_obj;
264 #endif /* ACE_HAS_THR_C_DEST */
267 // Get the thread-specific object for the key associated with this
268 // object. Returns 0 if the ts_obj has never been initialized,
269 // otherwise returns a pointer to the ts_obj.
271 template <class TYPE> TYPE *
272 ACE_TSS<TYPE>::ts_object () const
274 if (!this->once_) // Return 0 if we've never been initialized.
275 return 0;
277 TYPE *ts_obj = 0;
279 #if defined (ACE_HAS_THR_C_DEST)
280 ACE_TSS_Adapter *tss_adapter = this->ts_value ();
282 if (tss_adapter != 0)
284 // Extract the real TS object.
285 ts_obj = static_cast <TYPE *> (tss_adapter->ts_obj_);
287 #else
288 ts_obj = this->ts_value ();
289 #endif /* ACE_HAS_THR_C_DEST */
291 return ts_obj;
294 template <class TYPE> TYPE *
295 ACE_TSS<TYPE>::ts_object (TYPE *new_ts_obj)
297 // Note, we shouldn't hold the keylock at this point because
298 // <ts_init> does it for us and we'll end up with deadlock
299 // otherwise...
300 if (!this->once_)
302 // Create and initialize thread-specific ts_obj.
303 if (this->ts_init () == -1)
304 return 0;
307 TYPE *ts_obj = 0;
309 #if defined (ACE_HAS_THR_C_DEST)
310 ACE_TSS_Adapter *tss_adapter = this->ts_value ();
312 if (tss_adapter != 0)
314 ts_obj = static_cast <TYPE *> (tss_adapter->ts_obj_);
315 // Don't delete tss_adapter yet. It can be double-deleted
316 // in case setspecific below fails.
319 ACE_TSS_Adapter *new_tss_adapter = 0;
320 ACE_NEW_RETURN (new_tss_adapter,
321 ACE_TSS_Adapter ((void *) new_ts_obj,
322 ACE_TSS<TYPE>::cleanup),
325 if (this->ts_value (new_tss_adapter) == -1)
327 delete new_tss_adapter;
329 else
331 // Now it's fine to delete the old tss_adapter.
332 delete tss_adapter;
334 #else
335 ts_obj = this->ts_value ();
336 this->ts_value (new_ts_obj);
337 #endif /* ACE_HAS_THR_C_DEST */
339 return ts_obj;
342 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_TSS_Guard)
344 template <class ACE_LOCK> void
345 ACE_TSS_Guard<ACE_LOCK>::dump () const
347 #if defined (ACE_HAS_DUMP)
348 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
349 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %d\n"), this->key_));
350 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
351 #endif /* ACE_HAS_DUMP */
354 template <class ACE_LOCK> void
355 ACE_TSS_Guard<ACE_LOCK>::init_key ()
357 this->key_ = ACE_OS::NULL_key;
358 ACE_Thread::keycreate (&this->key_,
359 #if defined (ACE_HAS_THR_C_DEST)
360 &ACE_TSS_C_cleanup
361 #else
362 &ACE_TSS_Guard<ACE_LOCK>::cleanup
363 #endif /* ACE_HAS_THR_C_DEST */
367 template <class ACE_LOCK>
368 ACE_TSS_Guard<ACE_LOCK>::ACE_TSS_Guard ()
370 this->init_key ();
373 template <class ACE_LOCK> int
374 ACE_TSS_Guard<ACE_LOCK>::release ()
376 Guard_Type *guard = 0;
378 #if defined (ACE_HAS_THR_C_DEST)
379 ACE_TSS_Adapter *tss_adapter = 0;
380 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
381 ACE_Thread::getspecific (this->key_, &temp);
382 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
383 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
384 #else
385 void *temp = guard; // Need this temp to keep G++ from complaining.
386 ACE_Thread::getspecific (this->key_, &temp);
387 guard = static_cast <Guard_Type *> (temp);
388 #endif /* ACE_HAS_THR_C_DEST */
390 return guard->release ();
393 template <class ACE_LOCK> int
394 ACE_TSS_Guard<ACE_LOCK>::remove ()
396 Guard_Type *guard = 0;
398 #if defined (ACE_HAS_THR_C_DEST)
399 ACE_TSS_Adapter *tss_adapter = 0;
400 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
401 ACE_Thread::getspecific (this->key_, &temp);
402 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
403 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
404 #else
405 void *temp = guard; // Need this temp to keep G++ from complaining.
406 ACE_Thread::getspecific (this->key_, &temp);
407 guard = static_cast <Guard_Type *> (temp);
408 #endif /* ACE_HAS_THR_C_DEST */
410 return guard->remove ();
413 template <class ACE_LOCK>
414 ACE_TSS_Guard<ACE_LOCK>::~ACE_TSS_Guard ()
416 Guard_Type *guard = 0;
418 #if defined (ACE_HAS_THR_C_DEST)
419 ACE_TSS_Adapter *tss_adapter = 0;
420 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
421 ACE_Thread::getspecific (this->key_, &temp);
422 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
423 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
424 #else
425 void *temp = guard; // Need this temp to keep G++ from complaining.
426 ACE_Thread::getspecific (this->key_, &temp);
427 guard = static_cast <Guard_Type *> (temp);
428 #endif /* ACE_HAS_THR_C_DEST */
430 // Make sure that this pointer is NULL when we shut down...
431 ACE_Thread::setspecific (this->key_, 0);
432 ACE_Thread::keyfree (this->key_);
433 // Destructor releases lock.
434 delete guard;
437 template <class ACE_LOCK> void
438 ACE_TSS_Guard<ACE_LOCK>::cleanup (void *ptr)
440 // Destructor releases lock.
441 delete (Guard_Type *) ptr;
444 template <class ACE_LOCK>
445 ACE_TSS_Guard<ACE_LOCK>::ACE_TSS_Guard (ACE_LOCK &lock, bool block)
447 this->init_key ();
448 Guard_Type *guard = 0;
449 ACE_NEW (guard,
450 Guard_Type (lock, block));
452 #if defined (ACE_HAS_THR_C_DEST)
453 ACE_TSS_Adapter *tss_adapter = 0;
454 ACE_NEW (tss_adapter,
455 ACE_TSS_Adapter ((void *) guard,
456 ACE_TSS_Guard<ACE_LOCK>::cleanup));
457 ACE_Thread::setspecific (this->key_,
458 (void *) tss_adapter);
459 #else
460 ACE_Thread::setspecific (this->key_,
461 (void *) guard);
462 #endif /* ACE_HAS_THR_C_DEST */
465 template <class ACE_LOCK> int
466 ACE_TSS_Guard<ACE_LOCK>::acquire ()
468 Guard_Type *guard = 0;
470 #if defined (ACE_HAS_THR_C_DEST)
471 ACE_TSS_Adapter *tss_adapter = 0;
472 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
473 ACE_Thread::getspecific (this->key_, &temp);
474 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
475 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
476 #else
477 void *temp = guard; // Need this temp to keep G++ from complaining.
478 ACE_Thread::getspecific (this->key_, &temp);
479 guard = static_cast <Guard_Type *> (temp);
480 #endif /* ACE_HAS_THR_C_DEST */
482 return guard->acquire ();
485 template <class ACE_LOCK> int
486 ACE_TSS_Guard<ACE_LOCK>::tryacquire ()
488 Guard_Type *guard = 0;
490 #if defined (ACE_HAS_THR_C_DEST)
491 ACE_TSS_Adapter *tss_adapter = 0;
492 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
493 ACE_Thread::getspecific (this->key_, &temp);
494 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
495 guard = static_cast <Guard_Type *> (tss_adapter->ts_obj_);
496 #else
497 void *temp = guard; // Need this temp to keep G++ from complaining.
498 ACE_Thread::getspecific (this->key_, &temp);
499 guard = static_cast <Guard_Type *> (temp);
500 #endif /* ACE_HAS_THR_C_DEST */
502 return guard->tryacquire ();
505 template <class ACE_LOCK>
506 ACE_TSS_Write_Guard<ACE_LOCK>::ACE_TSS_Write_Guard (ACE_LOCK &lock,
507 bool block)
509 this->init_key ();
510 Guard_Type *guard = 0;
511 ACE_NEW (guard,
512 Write_Guard_Type (lock, block));
514 #if defined (ACE_HAS_THR_C_DEST)
515 ACE_TSS_Adapter *tss_adapter = 0;
516 ACE_NEW (tss_adapter,
517 ACE_TSS_Adapter ((void *) guard,
518 ACE_TSS_Guard<ACE_LOCK>::cleanup));
519 ACE_Thread::setspecific (this->key_, (void *) tss_adapter);
520 #else
521 ACE_Thread::setspecific (this->key_, (void *) guard);
522 #endif /* ACE_HAS_THR_C_DEST */
525 template <class ACE_LOCK> int
526 ACE_TSS_Write_Guard<ACE_LOCK>::acquire ()
528 Write_Guard_Type *guard = 0;
530 #if defined (ACE_HAS_THR_C_DEST)
531 ACE_TSS_Adapter *tss_adapter = 0;
532 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
533 ACE_Thread::getspecific (this->key_, &temp);
534 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
535 guard = static_cast <Write_Guard_Type *> (tss_adapter->ts_obj_);
536 #else
537 void *temp = guard; // Need this temp to keep G++ from complaining.
538 ACE_Thread::getspecific (this->key_, &temp);
539 guard = static_cast <Write_Guard_Type *> (temp);
540 #endif /* ACE_HAS_THR_C_DEST */
542 return guard->acquire_write ();
545 template <class ACE_LOCK> int
546 ACE_TSS_Write_Guard<ACE_LOCK>::tryacquire ()
548 Write_Guard_Type *guard = 0;
550 #if defined (ACE_HAS_THR_C_DEST)
551 ACE_TSS_Adapter *tss_adapter = 0;
552 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
553 ACE_Thread::getspecific (this->key_, &temp);
554 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
555 guard = static_cast <Write_Guard_Type *> (tss_adapter->ts_obj_);
556 #else
557 void *temp = guard; // Need this temp to keep G++ from complaining.
558 ACE_Thread::getspecific (this->key_, &temp);
559 guard = static_cast <Write_Guard_Type *> (temp);
560 #endif /* ACE_HAS_THR_C_DEST */
562 return guard->tryacquire_write ();
565 template <class ACE_LOCK> int
566 ACE_TSS_Write_Guard<ACE_LOCK>::acquire_write ()
568 return this->acquire ();
571 template <class ACE_LOCK> int
572 ACE_TSS_Write_Guard<ACE_LOCK>::tryacquire_write ()
574 return this->tryacquire ();
577 template <class ACE_LOCK> void
578 ACE_TSS_Write_Guard<ACE_LOCK>::dump () const
580 #if defined (ACE_HAS_DUMP)
581 ACE_TSS_Guard<ACE_LOCK>::dump ();
582 #endif /* ACE_HAS_DUMP */
585 template <class ACE_LOCK>
586 ACE_TSS_Read_Guard<ACE_LOCK>::ACE_TSS_Read_Guard (ACE_LOCK &lock, bool block)
588 this->init_key ();
589 Guard_Type *guard = 0;
590 ACE_NEW (guard,
591 Read_Guard_Type (lock, block));
592 #if defined (ACE_HAS_THR_C_DEST)
593 ACE_TSS_Adapter *tss_adapter;
594 ACE_NEW (tss_adapter,
595 ACE_TSS_Adapter ((void *)guard,
596 ACE_TSS_Guard<ACE_LOCK>::cleanup));
597 ACE_Thread::setspecific (this->key_,
598 (void *) tss_adapter);
599 #else
600 ACE_Thread::setspecific (this->key_,
601 (void *) guard);
602 #endif /* ACE_HAS_THR_C_DEST */
605 template <class ACE_LOCK> int
606 ACE_TSS_Read_Guard<ACE_LOCK>::acquire ()
608 Read_Guard_Type *guard = 0;
610 #if defined (ACE_HAS_THR_C_DEST)
611 ACE_TSS_Adapter *tss_adapter = 0;
612 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
613 ACE_Thread::getspecific (this->key_, &temp);
614 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
615 guard = static_cast <Read_Guard_Type *> (tss_adapter->ts_obj_);
616 #else
617 void *temp = guard; // Need this temp to keep G++ from complaining.
618 ACE_Thread::getspecific (this->key_, &temp);
619 guard = static_cast <Read_Guard_Type *> (temp);
620 #endif /* ACE_HAS_THR_C_DEST */
622 return guard->acquire_read ();
625 template <class ACE_LOCK> int
626 ACE_TSS_Read_Guard<ACE_LOCK>::tryacquire ()
628 Read_Guard_Type *guard = 0;
630 #if defined (ACE_HAS_THR_C_DEST)
631 ACE_TSS_Adapter *tss_adapter = 0;
632 void *temp = tss_adapter; // Need this temp to keep G++ from complaining.
633 ACE_Thread::getspecific (this->key_, &temp);
634 tss_adapter = static_cast <ACE_TSS_Adapter *> (temp);
635 guard = static_cast <Read_Guard_Type *> (tss_adapter->ts_obj_);
636 #else
637 void *temp = guard; // Need this temp to keep G++ from complaining.
638 ACE_Thread::getspecific (this->key_, &temp);
639 guard = static_cast <Read_Guard_Type *> (temp);
640 #endif /* ACE_HAS_THR_C_DEST */
642 return guard->tryacquire_read ();
645 template <class ACE_LOCK> int
646 ACE_TSS_Read_Guard<ACE_LOCK>::acquire_read ()
648 return this->acquire ();
651 template <class ACE_LOCK> int
652 ACE_TSS_Read_Guard<ACE_LOCK>::tryacquire_read ()
654 return this->tryacquire ();
657 template <class ACE_LOCK> void
658 ACE_TSS_Read_Guard<ACE_LOCK>::dump () const
660 #if defined (ACE_HAS_DUMP)
661 ACE_TSS_Guard<ACE_LOCK>::dump ();
662 #endif /* ACE_HAS_DUMP */
665 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
667 ACE_END_VERSIONED_NAMESPACE_DECL
669 #endif /* ACE_TSS_T_CPP */