3 //==========================================================================
7 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
9 //==========================================================================
13 #include /**/ "ace/pre.h"
17 #if !defined (ACE_LACKS_PRAGMA_ONCE)
19 #endif /* ACE_LACKS_PRAGMA_ONCE */
21 // This should probably go somewhere else, but it's only used here and
23 // Note there is no ACE_TSS_SET because one would typically do
24 // 'ACE_TSS_GET()->xyz_ = value', so the macro would have been too
26 # if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
27 # define ACE_TSS_TYPE(T) ACE_TSS< T >
28 # define ACE_TSS_GET(I, T) ((I)->operator T * ())
30 # define ACE_TSS_TYPE(T) T
31 # define ACE_TSS_GET(I, T) (I)
32 # endif /* ACE_HAS_THREADS && (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION) */
34 #include "ace/Thread_Mutex.h"
35 #include "ace/Copy_Disabled.h"
37 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
39 #if defined (ACE_HAS_THR_C_DEST)
40 class ACE_TSS_Adapter
;
46 * @brief Allows objects that are "physically" in thread specific
47 * storage (i.e., private to a thread) to be accessed as though
48 * they were "logically" global to a program.
50 * This class helps to maintain a separate copy of an object for each thread
51 * that needs access to it. All threads access a single instance of ACE_TSS
52 * to obtain a pointer to a thread-specific copy of a TYPE object. Using
53 * a pointer to TYPE in TSS instead of TYPE itself is useful because,
54 * in addition to avoiding copies on what may be a complex class, it allows
55 * assignment of objects to thread-specific data that have arbitrarily
56 * complex constructors.
58 * When the ACE_TSS object is destroyed, all threads's instances of the
61 * Modern compilers have no problem using a built-in type for @c TYPE.
62 * However, if you must use an older compiler that won't work with a built-in
63 * type, the ACE_TSS_Type_Adapter class template, below, can be used for
64 * adapting built-in types to work with ACE_TSS.
66 * @note Beware when creating static instances of this type
67 * (as with any other, btw). The unpredictable order of initialization
68 * across different platforms may cause a situation where one uses
69 * the instance before it is fully initialized. That's why typically
70 * instances of this type are dynamicaly allocated. On the stack it is
71 * typically allocated inside the ACE_Thread::svc() method which
72 * limits its lifetime appropriately.
75 class ACE_TSS
: private ACE_Copy_Disabled
79 * Default constructor. Can also initialize this ACE_TSS instance,
80 * readying it for use by the calling thread as well as all other
81 * threads in the process. If the constructor does not initialize this
82 * object, the first access to it will perform the initialization, which
83 * could possibly (under odd error conditions) fail.
85 * @param ts_obj If non-zero, this object is initialized for use by
86 * all threads and @a ts_obj is used to set the
87 * thread-specific value for the calling thread. Other
88 * threads use the ts_object (TYPE *) method to set
91 ACE_TSS (TYPE
*ts_obj
= 0);
93 /// Deregister this object from thread-specific storage administration.
94 /// Will cause all threads' copies of TYPE to be destroyed.
98 * Set the thread-specific object for the calling thread.
99 * If this object has not been initialized yet, this method performs the
102 * @param new_ts_obj The new value for the calling thread's copy of
105 * @return The previous value of the calling thread's copy of this
106 * object; 0 if there was no previous value. This method also
107 * returns 0 on errors. To tell the difference between an error
108 * and a returned 0 pointer, it's recommended that one set errno
109 * to 0 prior to calling ts_object() and check for a new errno
110 * value if ts_object() returns 0.
112 TYPE
*ts_object (TYPE
*new_ts_obj
);
116 * All accessors return a pointer to the calling thread's copy of the
117 * TYPE data. The pointer may be 0 on error conditions or if the calling
118 * thread's copy of the data has not yet been set. See specific method
119 * descriptions for complete details.
123 * Get the thread-specific object for this object.
125 * @return 0 if the object has never been initialized, otherwise returns
126 * the calling thread's copy of the data. The returned pointer
127 * may be 0 under odd error conditions; check errno for further
130 TYPE
*ts_object () const;
133 * Use a "smart pointer" to get the thread-specific data associated
135 * If this ACE_TSS object hasn't been initialized, this method
136 * will initialize it as a side-affect. If the calling thread has not
137 * set a value, a default-constructed instance of TYPE is allocated and it
138 * becomes the thread's instance.
140 * @return The calling thread's copy of the data. The returned pointer
141 * may be 0 under odd error conditions; check errno for further
144 TYPE
*operator-> () const;
147 * Obtain a pointer to the calling thread's TYPE object.
148 * If this ACE_TSS object hasn't been initialized, this method
149 * will initialize it as a side-affect. If the calling thread has not
150 * set a value, a default-constructed instance of TYPE is allocated and it
151 * becomes the thread's instance.
153 * @return The calling thread's copy of the data. The returned pointer
154 * may be 0 under odd error conditions; check errno for further
157 operator TYPE
*() const;
161 /// Hook for construction parameters.
162 virtual TYPE
*make_TSS_TYPE () const;
164 // = Utility methods.
166 /// Dump the state of an object.
169 /// Declare the dynamic allocation hooks.
170 ACE_ALLOC_HOOK_DECLARE
;
173 /// Actually implements the code that retrieves the object from
174 /// thread-specific storage.
175 TYPE
*ts_get () const;
177 /// Factors out common code for initializing TSS. This must NOT be
178 /// called with the lock held...
181 #if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)))
182 /// This implementation only works for non-threading systems...
185 /// Avoid race conditions during initialization.
186 ACE_Thread_Mutex keylock_
;
188 /// "First time in" flag.
191 /// Key for the thread-specific error data.
192 ACE_thread_key_t key_
;
194 /// "Destructor" that deletes internal TYPE * when thread exits.
195 static void cleanup (void *ptr
);
197 /// Obtains a plain value stored in the thread-specific storage.
198 # if defined (ACE_HAS_THR_C_DEST)
199 ACE_TSS_Adapter
*ts_value () const;
201 TYPE
*ts_value () const;
202 # endif /* ACE_HAS_THR_C_DEST */
204 /// Stores a new plain value in the thread-specific storage.
205 # if defined (ACE_HAS_THR_C_DEST)
206 int ts_value (ACE_TSS_Adapter
*new_tss_adapter
) const;
208 int ts_value (TYPE
*new_ts_obj
) const;
209 # endif /* ACE_HAS_THR_C_DEST */
210 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
214 * @class ACE_TSS_Type_Adapter
216 * @brief Adapter that allows built-in types to be used with ACE_TSS.
218 * Wraps a value of a built-in type, providing conversions to
219 * and from the type. Example use with ACE_TSS:
220 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
222 * ACE_OS::fprintf (stderr, "%d\n", *i);
223 * Unfortunately, though, some compilers have trouble with the
224 * implicit type conversions. This seems to work better:
225 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
226 * i->operator int & () = 37;
227 * ACE_OS::fprintf (stderr, "%d\n", i->operator int ());
229 template <class TYPE
>
230 class ACE_TSS_Type_Adapter
233 /// Constructor. Inlined here so that it should _always_ be inlined.
234 ACE_TSS_Type_Adapter (const TYPE value
= 0): value_ (value
) {}
236 /// TYPE conversion. Inlined here so that it should _always_ be
238 operator TYPE () const { return value_
; }
240 /// TYPE & conversion. Inlined here so that it should _always_ be
242 operator TYPE
&() { return value_
; }
245 /// The wrapped value.
249 ACE_END_VERSIONED_NAMESPACE_DECL
251 #if defined (__ACE_INLINE__)
252 #include "ace/TSS_T.inl"
253 #endif /* __ACE_INLINE__ */
255 #include "ace/TSS_T.cpp"
257 #include /**/ "ace/post.h"
258 #endif /* ACE_TSS_T_H */