3 //==========================================================================
9 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
11 //==========================================================================
15 #include /**/ "ace/pre.h"
19 #if !defined (ACE_LACKS_PRAGMA_ONCE)
21 #endif /* ACE_LACKS_PRAGMA_ONCE */
23 // This should probably go somewhere else, but it's only used here and
25 // Note there is no ACE_TSS_SET because one would typically do
26 // 'ACE_TSS_GET()->xyz_ = value', so the macro would have been too
28 # if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
29 # define ACE_TSS_TYPE(T) ACE_TSS< T >
30 # define ACE_TSS_GET(I, T) ((I)->operator T * ())
32 # define ACE_TSS_TYPE(T) T
33 # define ACE_TSS_GET(I, T) (I)
34 # endif /* ACE_HAS_THREADS && (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION) */
36 #include "ace/Thread_Mutex.h"
37 #include "ace/Copy_Disabled.h"
39 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
41 #if defined (ACE_HAS_THR_C_DEST)
42 class ACE_TSS_Adapter
;
48 * @brief Allows objects that are "physically" in thread specific
49 * storage (i.e., private to a thread) to be accessed as though
50 * they were "logically" global to a program.
52 * This class helps to maintain a separate copy of an object for each thread
53 * that needs access to it. All threads access a single instance of ACE_TSS
54 * to obtain a pointer to a thread-specific copy of a TYPE object. Using
55 * a pointer to TYPE in TSS instead of TYPE itself is useful because,
56 * in addition to avoiding copies on what may be a complex class, it allows
57 * assignment of objects to thread-specific data that have arbitrarily
58 * complex constructors.
60 * When the ACE_TSS object is destroyed, all threads's instances of the
63 * Modern compilers have no problem using a built-in type for @c TYPE.
64 * However, if you must use an older compiler that won't work with a built-in
65 * type, the ACE_TSS_Type_Adapter class template, below, can be used for
66 * adapting built-in types to work with ACE_TSS.
68 * @note Beware when creating static instances of this type
69 * (as with any other, btw). The unpredictable order of initialization
70 * across different platforms may cause a situation where one uses
71 * the instance before it is fully initialized. That's why typically
72 * instances of this type are dynamicaly allocated. On the stack it is
73 * typically allocated inside the ACE_Thread::svc() method which
74 * limits its lifetime appropriately.
77 class ACE_TSS
: private ACE_Copy_Disabled
81 * Default constructor. Can also initialize this ACE_TSS instance,
82 * readying it for use by the calling thread as well as all other
83 * threads in the process. If the constructor does not initialize this
84 * object, the first access to it will perform the initialization, which
85 * could possibly (under odd error conditions) fail.
87 * @param ts_obj If non-zero, this object is initialized for use by
88 * all threads and @a ts_obj is used to set the
89 * thread-specific value for the calling thread. Other
90 * threads use the ts_object (TYPE *) method to set
93 ACE_TSS (TYPE
*ts_obj
= 0);
95 /// Deregister this object from thread-specific storage administration.
96 /// Will cause all threads' copies of TYPE to be destroyed.
97 virtual ~ACE_TSS (void);
100 * Set the thread-specific object for the calling thread.
101 * If this object has not been initialized yet, this method performs the
104 * @param new_ts_obj The new value for the calling thread's copy of
107 * @return The previous value of the calling thread's copy of this
108 * object; 0 if there was no previous value. This method also
109 * returns 0 on errors. To tell the difference between an error
110 * and a returned 0 pointer, it's recommended that one set errno
111 * to 0 prior to calling ts_object() and check for a new errno
112 * value if ts_object() returns 0.
114 TYPE
*ts_object (TYPE
*new_ts_obj
);
118 * All accessors return a pointer to the calling thread's copy of the
119 * TYPE data. The pointer may be 0 on error conditions or if the calling
120 * thread's copy of the data has not yet been set. See specific method
121 * descriptions for complete details.
125 * Get the thread-specific object for this object.
127 * @return 0 if the object has never been initialized, otherwise returns
128 * the calling thread's copy of the data. The returned pointer
129 * may be 0 under odd error conditions; check errno for further
132 TYPE
*ts_object (void) const;
135 * Use a "smart pointer" to get the thread-specific data associated
137 * If this ACE_TSS object hasn't been initialized, this method
138 * will initialize it as a side-affect. If the calling thread has not
139 * set a value, a default-constructed instance of TYPE is allocated and it
140 * becomes the thread's instance.
142 * @return The calling thread's copy of the data. The returned pointer
143 * may be 0 under odd error conditions; check errno for further
146 TYPE
*operator-> () const;
149 * Obtain a pointer to the calling thread's TYPE object.
150 * If this ACE_TSS object hasn't been initialized, this method
151 * will initialize it as a side-affect. If the calling thread has not
152 * set a value, a default-constructed instance of TYPE is allocated and it
153 * becomes the thread's instance.
155 * @return The calling thread's copy of the data. The returned pointer
156 * may be 0 under odd error conditions; check errno for further
159 operator TYPE
*(void) const;
163 /// Hook for construction parameters.
164 virtual TYPE
*make_TSS_TYPE (void) const;
166 // = Utility methods.
168 /// Dump the state of an object.
169 void dump (void) const;
171 /// Declare the dynamic allocation hooks.
172 ACE_ALLOC_HOOK_DECLARE
;
175 /// Actually implements the code that retrieves the object from
176 /// thread-specific storage.
177 TYPE
*ts_get (void) const;
179 /// Factors out common code for initializing TSS. This must NOT be
180 /// called with the lock held...
183 #if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)))
184 /// This implementation only works for non-threading systems...
187 /// Avoid race conditions during initialization.
188 ACE_Thread_Mutex keylock_
;
190 /// "First time in" flag.
193 /// Key for the thread-specific error data.
194 ACE_thread_key_t key_
;
196 /// "Destructor" that deletes internal TYPE * when thread exits.
197 static void cleanup (void *ptr
);
199 /// Obtains a plain value stored in the thread-specific storage.
200 # if defined (ACE_HAS_THR_C_DEST)
201 ACE_TSS_Adapter
*ts_value (void) const;
203 TYPE
*ts_value (void) const;
204 # endif /* ACE_HAS_THR_C_DEST */
206 /// Stores a new plain value in the thread-specific storage.
207 # if defined (ACE_HAS_THR_C_DEST)
208 int ts_value (ACE_TSS_Adapter
*new_tss_adapter
) const;
210 int ts_value (TYPE
*new_ts_obj
) const;
211 # endif /* ACE_HAS_THR_C_DEST */
212 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
216 * @class ACE_TSS_Type_Adapter
218 * @brief Adapter that allows built-in types to be used with ACE_TSS.
220 * Wraps a value of a built-in type, providing conversions to
221 * and from the type. Example use with ACE_TSS:
222 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
224 * ACE_OS::fprintf (stderr, "%d\n", *i);
225 * Unfortunately, though, some compilers have trouble with the
226 * implicit type conversions. This seems to work better:
227 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
228 * i->operator int & () = 37;
229 * ACE_OS::fprintf (stderr, "%d\n", i->operator int ());
231 template <class TYPE
>
232 class ACE_TSS_Type_Adapter
235 /// Constructor. Inlined here so that it should _always_ be inlined.
236 ACE_TSS_Type_Adapter (const TYPE value
= 0): value_ (value
) {}
238 /// TYPE conversion. Inlined here so that it should _always_ be
240 operator TYPE () const { return value_
; };
242 /// TYPE & conversion. Inlined here so that it should _always_ be
244 operator TYPE
&() { return value_
; };
247 /// The wrapped value.
251 ACE_END_VERSIONED_NAMESPACE_DECL
253 #if defined (__ACE_INLINE__)
254 #include "ace/TSS_T.inl"
255 #endif /* __ACE_INLINE__ */
257 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
258 #include "ace/TSS_T.cpp"
259 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
261 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
262 #pragma implementation ("TSS_T.cpp")
263 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
265 #include /**/ "ace/post.h"
266 #endif /* ACE_TSS_T_H */