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_LACKS_VA_FUNCTIONS)
160 ACE_OS::fprintf (stderr
,
161 "ACE_Thread::keycreate() failed!");
162 #endif /* !ACE_LACKS_VA_FUNCTIONS */
166 #if defined (ACE_HAS_THR_C_DEST)
167 // Encapsulate a ts_obj and it's destructor in an
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)
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
190 // Create and initialize thread-specific ts_obj.
191 if (const_cast< ACE_TSS
< TYPE
> * >(this)->ts_init () == -1)
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
;
210 // Check to see if this is the first time in for this thread.
211 if (tss_adapter
== 0)
213 ts_obj
= this->ts_value ();
215 // Check to see if this is the first time in for this thread.
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 ();
227 #if defined (ACE_HAS_THR_C_DEST)
228 // Encapsulate a ts_obj and it's destructor in an
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)
239 return 0; // Major problems, this should *never* happen!
242 // Store the dynamically allocated pointer in thread-specific
244 if (this->ts_value (ts_obj
) == -1)
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_
);
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.
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_
);
283 ts_obj
= this->ts_value ();
284 #endif /* ACE_HAS_THR_C_DEST */
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
297 // Create and initialize thread-specific ts_obj.
298 if (this->ts_init () == -1)
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
;
326 // Now it's fine to delete the old tss_adapter.
330 ts_obj
= this->ts_value ();
331 this->ts_value (new_ts_obj
);
332 #endif /* ACE_HAS_THR_C_DEST */
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)
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 ()
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_
);
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_
);
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_
);
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.
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
)
443 Guard_Type
*guard
= 0;
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
);
455 ACE_Thread::setspecific (this->key_
,
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_
);
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_
);
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
,
505 Guard_Type
*guard
= 0;
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
);
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_
);
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_
);
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
)
584 Guard_Type
*guard
= 0;
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
);
595 ACE_Thread::setspecific (this->key_
,
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_
);
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_
);
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 */