Fixed typos
[ACE_TAO.git] / ACE / ace / TSS_T.h
blobd3097d544398e699143bad6e9530303a4e2e2d30
1 // -*- C++ -*-
3 //==========================================================================
4 /**
5 * @file TSS_T.h
7 * Moved from Synch.h.
9 * @author Douglas C. Schmidt <d.schmidt@vanderbilt.edu>
11 //==========================================================================
13 #ifndef ACE_TSS_T_H
14 #define ACE_TSS_T_H
15 #include /**/ "ace/pre.h"
17 #include "ace/Lock.h"
19 #if !defined (ACE_LACKS_PRAGMA_ONCE)
20 # pragma once
21 #endif /* ACE_LACKS_PRAGMA_ONCE */
23 // This should probably go somewhere else, but it's only used here and
24 // in Thread_Manager.
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
27 // complicated.
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 * ())
31 # else
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;
43 #endif
45 /**
46 * @class ACE_TSS
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
61 * data are deleted.
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.
76 template <class TYPE>
77 class ACE_TSS : private ACE_Copy_Disabled
79 public:
80 /**
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
91 * a specific value.
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);
99 /**
100 * Set the thread-specific object for the calling thread.
101 * If this object has not been initialized yet, this method performs the
102 * initialization.
104 * @param new_ts_obj The new value for the calling thread's copy of
105 * this object.
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);
116 /** @name Accessors
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.
123 //@{
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
130 * information.
132 TYPE *ts_object (void) const;
135 * Use a "smart pointer" to get the thread-specific data associated
136 * with this object.
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
144 * information.
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
157 * information.
159 operator TYPE *(void) const;
161 //@}
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;
174 protected:
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...
181 int ts_init (void);
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...
185 TYPE *type_;
186 #else
187 /// Avoid race conditions during initialization.
188 ACE_Thread_Mutex keylock_;
190 /// "First time in" flag.
191 volatile bool once_;
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;
202 # else
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;
209 # else
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;
223 * *i = 37;
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
234 public:
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
239 /// inlined.
240 operator TYPE () const { return value_; };
242 /// TYPE & conversion. Inlined here so that it should _always_ be
243 /// inlined.
244 operator TYPE &() { return value_; };
246 private:
247 /// The wrapped value.
248 TYPE 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 */