6 #if !defined (ACE_LACKS_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)) */
37 ACE_TSS
<TYPE
>::~ACE_TSS ()
39 #if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
42 # if defined (ACE_HAS_THR_C_DEST)
43 ACE_TSS_Adapter
*tss_adapter
= this->ts_value ();
45 ACE_TSS_C_cleanup (tss_adapter
);
47 TYPE
*ts_obj
= this->ts_value ();
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
);
54 ACE_UNUSED_ARG (ts_obj
);
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.
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 ();
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
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.
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
122 if (ACE_Thread::keycreate (&this->key_
,
123 #if defined (ACE_HAS_THR_C_DEST)
126 &ACE_TSS
<TYPE
>::cleanup
127 #endif /* ACE_HAS_THR_C_DEST */
129 return -1; // Major problems, this should *never* happen!
132 // This *must* come last to avoid race conditions!
141 template <class TYPE
>
142 ACE_TSS
<TYPE
>::ACE_TSS (TYPE
*ts_obj
)
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!
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)
161 ACE_TEXT ("ACE_Thread::keycreate() failed!"),
162 ACE_TEXT ("ACE_TSS::ACE_TSS"),
164 #elif !defined (ACE_LACKS_VA_FUNCTIONS)
165 ACE_OS::fprintf (stderr
,
166 "ACE_Thread::keycreate() failed!");
167 #endif /* ACE_HAS_WINCE */
171 #if defined (ACE_HAS_THR_C_DEST)
172 // Encapsulate a ts_obj and it's destructor in an
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)
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
195 // Create and initialize thread-specific ts_obj.
196 if (const_cast< ACE_TSS
< TYPE
> * >(this)->ts_init () == -1)
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
;
215 // Check to see if this is the first time in for this thread.
216 if (tss_adapter
== 0)
218 ts_obj
= this->ts_value ();
220 // Check to see if this is the first time in for this thread.
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 ();
232 #if defined (ACE_HAS_THR_C_DEST)
233 // Encapsulate a ts_obj and it's destructor in an
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)
244 return 0; // Major problems, this should *never* happen!
247 // Store the dynamically allocated pointer in thread-specific
249 if (this->ts_value (ts_obj
) == -1)
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_
);
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.
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_
);
288 ts_obj
= this->ts_value ();
289 #endif /* ACE_HAS_THR_C_DEST */
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
302 // Create and initialize thread-specific ts_obj.
303 if (this->ts_init () == -1)
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
;
331 // Now it's fine to delete the old tss_adapter.
335 ts_obj
= this->ts_value ();
336 this->ts_value (new_ts_obj
);
337 #endif /* ACE_HAS_THR_C_DEST */
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)
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 ()
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_
);
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_
);
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_
);
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.
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
)
448 Guard_Type
*guard
= 0;
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
);
460 ACE_Thread::setspecific (this->key_
,
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_
);
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_
);
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
,
510 Guard_Type
*guard
= 0;
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
);
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_
);
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_
);
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
)
589 Guard_Type
*guard
= 0;
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
);
600 ACE_Thread::setspecific (this->key_
,
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_
);
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_
);
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 */