Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / TSS_T.h
blobaf13d17b733cebd3688725fd74bd1e086ea82e71
1 // -*- C++ -*-
3 //==========================================================================
4 /**
5 * @file TSS_T.h
7 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
8 */
9 //==========================================================================
11 #ifndef ACE_TSS_T_H
12 #define ACE_TSS_T_H
13 #include /**/ "ace/pre.h"
15 #include "ace/Lock.h"
17 #if !defined (ACE_LACKS_PRAGMA_ONCE)
18 # pragma once
19 #endif /* ACE_LACKS_PRAGMA_ONCE */
21 // This should probably go somewhere else, but it's only used here and
22 // in Thread_Manager.
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
25 // complicated.
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 * ())
29 # else
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;
41 #endif
43 /**
44 * @class ACE_TSS
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
59 * data are deleted.
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.
74 template <class TYPE>
75 class ACE_TSS : private ACE_Copy_Disabled
77 public:
78 /**
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
89 * a specific value.
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.
95 virtual ~ACE_TSS ();
97 /**
98 * Set the thread-specific object for the calling thread.
99 * If this object has not been initialized yet, this method performs the
100 * initialization.
102 * @param new_ts_obj The new value for the calling thread's copy of
103 * this object.
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);
114 /** @name Accessors
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.
121 //@{
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
128 * information.
130 TYPE *ts_object () const;
133 * Use a "smart pointer" to get the thread-specific data associated
134 * with this object.
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
142 * information.
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
155 * information.
157 operator TYPE *() const;
159 //@}
161 /// Hook for construction parameters.
162 virtual TYPE *make_TSS_TYPE () const;
164 // = Utility methods.
166 /// Dump the state of an object.
167 void dump () const;
169 /// Declare the dynamic allocation hooks.
170 ACE_ALLOC_HOOK_DECLARE;
172 protected:
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...
179 int ts_init ();
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...
183 TYPE *type_;
184 #else
185 /// Avoid race conditions during initialization.
186 ACE_Thread_Mutex keylock_;
188 /// "First time in" flag.
189 volatile bool once_;
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;
200 # else
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;
207 # else
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;
221 * *i = 37;
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
232 public:
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
237 /// inlined.
238 operator TYPE () const { return value_; }
240 /// TYPE & conversion. Inlined here so that it should _always_ be
241 /// inlined.
242 operator TYPE &() { return value_; }
244 private:
245 /// The wrapped value.
246 TYPE 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 */