00001 // -*- C++ -*- 00002 00003 //========================================================================== 00004 /** 00005 * @file TSS_T.h 00006 * 00007 * $Id: TSS_T.h 91124 2010-07-19 11:54:35Z vzykov $ 00008 * 00009 * Moved from Synch.h. 00010 * 00011 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> 00012 */ 00013 //========================================================================== 00014 00015 #ifndef ACE_TSS_T_H 00016 #define ACE_TSS_T_H 00017 #include /**/ "ace/pre.h" 00018 00019 #include "ace/Lock.h" 00020 00021 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00022 # pragma once 00023 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00024 00025 // This should probably go somewhere else, but it's only used here and 00026 // in Thread_Manager. 00027 // Note there is no ACE_TSS_SET because one would typicaly do 00028 // 'ACE_TSS_GET()->xyz_ = value', so the macro would have been too 00029 // complicated. 00030 # if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) 00031 # define ACE_TSS_TYPE(T) ACE_TSS< T > 00032 # define ACE_TSS_GET(I, T) ((I)->operator T * ()) 00033 # else 00034 # define ACE_TSS_TYPE(T) T 00035 # define ACE_TSS_GET(I, T) (I) 00036 # endif /* ACE_HAS_THREADS && (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION) */ 00037 00038 #include "ace/Thread_Mutex.h" 00039 00040 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00041 00042 #if defined (ACE_HAS_THR_C_DEST) 00043 class ACE_TSS_Adapter; 00044 #endif 00045 00046 /** 00047 * @class ACE_TSS 00048 * 00049 * @brief Allows objects that are "physically" in thread specific 00050 * storage (i.e., private to a thread) to be accessed as though 00051 * they were "logically" global to a program. 00052 * 00053 * This class helps to maintain a separate copy of an object for each thread 00054 * that needs access to it. All threads access a single instance of ACE_TSS 00055 * to obtain a pointer to a thread-specific copy of a TYPE object. Using 00056 * a pointer to TYPE in TSS instead of TYPE itself is useful because, 00057 * in addition to avoiding copies on what may be a complex class, it allows 00058 * assignment of objects to thread-specific data that have arbitrarily 00059 * complex constructors. 00060 * 00061 * When the ACE_TSS object is destroyed, all threads's instances of the 00062 * data are deleted. 00063 * 00064 * Modern compilers have no problem using a built-in type for @c TYPE. 00065 * However, if you must use an older compiler that won't work with a built-in 00066 * type, the ACE_TSS_Type_Adapter class template, below, can be used for 00067 * adapting built-in types to work with ACE_TSS. 00068 * 00069 * @note Beware when creating static instances of this type 00070 * (as with any other, btw). The unpredictable order of initialization 00071 * across different platforms may cause a situation where one uses 00072 * the instance before it is fully initialized. That's why typically 00073 * instances of this type are dynamicaly allocated. On the stack it is 00074 * typically allocated inside the ACE_Thread::svc() method which 00075 * limits its lifetime appropriately. 00076 * 00077 */ 00078 template <class TYPE> 00079 class ACE_TSS 00080 { 00081 public: 00082 /** 00083 * Default constructor. Can also initialize this ACE_TSS instance, 00084 * readying it for use by the calling thread as well as all other 00085 * threads in the process. If the constructor does not initialize this 00086 * object, the first access to it will perform the initialization, which 00087 * could possibly (under odd error conditions) fail. 00088 * 00089 * @param ts_obj If non-zero, this object is initialized for use by 00090 * all threads and @a ts_obj is used to set the 00091 * thread-specific value for the calling thread. Other 00092 * threads use the ts_object (TYPE *) method to set 00093 * a specific value. 00094 */ 00095 ACE_TSS (TYPE *ts_obj = 0); 00096 00097 /// Deregister this object from thread-specific storage administration. 00098 /// Will cause all threads' copies of TYPE to be destroyed. 00099 virtual ~ACE_TSS (void); 00100 00101 /** 00102 * Set the thread-specific object for the calling thread. 00103 * If this object has not been initialized yet, this method performs the 00104 * initialization. 00105 * 00106 * @param new_ts_obj The new value for the calling thread's copy of 00107 * this object. 00108 * 00109 * @return The previous value of the calling thread's copy of this 00110 * object; 0 if there was no previous value. This method also 00111 * returns 0 on errors. To tell the difference between an error 00112 * and a returned 0 pointer, it's recommended that one set errno 00113 * to 0 prior to calling ts_object() and check for a new errno 00114 * value if ts_object() returns 0. 00115 */ 00116 TYPE *ts_object (TYPE *new_ts_obj); 00117 00118 /** @name Accessors 00119 * 00120 * All accessors return a pointer to the calling thread's copy of the 00121 * TYPE data. The pointer may be 0 on error conditions or if the calling 00122 * thread's copy of the data has not yet been set. See specific method 00123 * descriptions for complete details. 00124 */ 00125 //@{ 00126 /** 00127 * Get the thread-specific object for this object. 00128 * 00129 * @return 0 if the object has never been initialized, otherwise returns 00130 * the calling thread's copy of the data. The returned pointer 00131 * may be 0 under odd error conditions; check errno for further 00132 * information. 00133 */ 00134 TYPE *ts_object (void) const; 00135 00136 /** 00137 * Use a "smart pointer" to get the thread-specific data associated 00138 * with this object. 00139 * If this ACE_TSS object hasn't been initialized, this method 00140 * will initialize it as a side-affect. If the calling thread has not 00141 * set a value, a default-constructed instance of TYPE is allocated and it 00142 * becomes the thread's instance. 00143 * 00144 * @return The calling thread's copy of the data. The returned pointer 00145 * may be 0 under odd error conditions; check errno for further 00146 * information. 00147 */ 00148 TYPE *operator-> () const; 00149 00150 /** 00151 * Obtain a pointer to the calling thread's TYPE object. 00152 * If this ACE_TSS object hasn't been initialized, this method 00153 * will initialize it as a side-affect. If the calling thread has not 00154 * set a value, a default-constructed instance of TYPE is allocated and it 00155 * becomes the thread's instance. 00156 * 00157 * @return The calling thread's copy of the data. The returned pointer 00158 * may be 0 under odd error conditions; check errno for further 00159 * information. 00160 */ 00161 operator TYPE *(void) const; 00162 00163 //@} 00164 00165 /// Hook for construction parameters. 00166 virtual TYPE *make_TSS_TYPE (void) const; 00167 00168 // = Utility methods. 00169 00170 /// Dump the state of an object. 00171 void dump (void) const; 00172 00173 // ACE_ALLOC_HOOK_DECLARE; 00174 // Declare the dynamic allocation hooks. 00175 00176 protected: 00177 /// Actually implements the code that retrieves the object from 00178 /// thread-specific storage. 00179 TYPE *ts_get (void) const; 00180 00181 /// Factors out common code for initializing TSS. This must NOT be 00182 /// called with the lock held... 00183 int ts_init (void); 00184 00185 #if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))) 00186 /// This implementation only works for non-threading systems... 00187 TYPE *type_; 00188 #else 00189 /// Avoid race conditions during initialization. 00190 ACE_Thread_Mutex keylock_; 00191 00192 /// "First time in" flag. 00193 volatile bool once_; 00194 00195 /// Key for the thread-specific error data. 00196 ACE_thread_key_t key_; 00197 00198 /// "Destructor" that deletes internal TYPE * when thread exits. 00199 static void cleanup (void *ptr); 00200 00201 /// Obtains a plain value stored in the thread-specific storage. 00202 # if defined (ACE_HAS_THR_C_DEST) 00203 ACE_TSS_Adapter *ts_value (void) const; 00204 # else 00205 TYPE *ts_value (void) const; 00206 # endif /* ACE_HAS_THR_C_DEST */ 00207 00208 /// Stores a new plain value in the thread-specific storage. 00209 # if defined (ACE_HAS_THR_C_DEST) 00210 int ts_value (ACE_TSS_Adapter *new_tss_adapter) const; 00211 # else 00212 int ts_value (TYPE *new_ts_obj) const; 00213 # endif /* ACE_HAS_THR_C_DEST */ 00214 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */ 00215 // = Disallow copying... 00216 ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS<TYPE> &)) 00217 ACE_UNIMPLEMENTED_FUNC (ACE_TSS (const ACE_TSS<TYPE> &)) 00218 }; 00219 00220 /** 00221 * @class ACE_TSS_Type_Adapter 00222 * 00223 * @brief Adapter that allows built-in types to be used with ACE_TSS. 00224 * 00225 * Wraps a value of a built-in type, providing conversions to 00226 * and from the type. Example use with ACE_TSS: 00227 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i; 00228 * *i = 37; 00229 * ACE_OS::fprintf (stderr, "%d\n", *i); 00230 * Unfortunately, though, some compilers have trouble with the 00231 * implicit type conversions. This seems to work better: 00232 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i; 00233 * i->operator int & () = 37; 00234 * ACE_OS::fprintf (stderr, "%d\n", i->operator int ()); 00235 */ 00236 template <class TYPE> 00237 class ACE_TSS_Type_Adapter 00238 { 00239 public: 00240 /// Constructor. Inlined here so that it should _always_ be inlined. 00241 ACE_TSS_Type_Adapter (const TYPE value = 0): value_ (value) {} 00242 00243 /// TYPE conversion. Inlined here so that it should _always_ be 00244 /// inlined. 00245 operator TYPE () const { return value_; }; 00246 00247 /// TYPE & conversion. Inlined here so that it should _always_ be 00248 /// inlined. 00249 operator TYPE &() { return value_; }; 00250 00251 private: 00252 /// The wrapped value. 00253 TYPE value_; 00254 }; 00255 00256 ACE_END_VERSIONED_NAMESPACE_DECL 00257 00258 #if defined (__ACE_INLINE__) 00259 #include "ace/TSS_T.inl" 00260 #endif /* __ACE_INLINE__ */ 00261 00262 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) 00263 #include "ace/TSS_T.cpp" 00264 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ 00265 00266 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) 00267 #pragma implementation ("TSS_T.cpp") 00268 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ 00269 00270 #include /**/ "ace/post.h" 00271 #endif /* ACE_TSS_T_H */