00001 // -*- C++ -*- 00002 00003 //========================================================================== 00004 /** 00005 * @file TSS_T.h 00006 * 00007 * $Id: TSS_T.h 74932 2006-10-21 18:51:54Z shuston $ 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 # if defined (ACE_HAS_BROKEN_CONVERSIONS) 00033 # define ACE_TSS_GET(I, T) (*(I)) 00034 # else 00035 # define ACE_TSS_GET(I, T) ((I)->operator T * ()) 00036 # endif /* ACE_HAS_BROKEN_CONVERSIONS */ 00037 # else 00038 # define ACE_TSS_TYPE(T) T 00039 # define ACE_TSS_GET(I, T) (I) 00040 # endif /* ACE_HAS_THREADS && (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION) */ 00041 00042 #include "ace/Thread_Mutex.h" 00043 00044 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 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 int 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 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */ 00201 // = Disallow copying... 00202 ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS<TYPE> &)) 00203 ACE_UNIMPLEMENTED_FUNC (ACE_TSS (const ACE_TSS<TYPE> &)) 00204 }; 00205 00206 /** 00207 * @class ACE_TSS_Type_Adapter 00208 * 00209 * @brief Adapter that allows built-in types to be used with ACE_TSS. 00210 * 00211 * Wraps a value of a built-in type, providing conversions to 00212 * and from the type. Example use with ACE_TSS: 00213 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i; 00214 * *i = 37; 00215 * ACE_OS::fprintf (stderr, "%d\n", *i); 00216 * Unfortunately, though, some compilers have trouble with the 00217 * implicit type conversions. This seems to work better: 00218 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i; 00219 * i->operator int & () = 37; 00220 * ACE_OS::fprintf (stderr, "%d\n", i->operator int ()); 00221 */ 00222 template <class TYPE> 00223 class ACE_TSS_Type_Adapter 00224 { 00225 public: 00226 /// Constructor. Inlined here so that it should _always_ be inlined. 00227 ACE_TSS_Type_Adapter (const TYPE value = 0): value_ (value) {} 00228 00229 /// TYPE conversion. Inlined here so that it should _always_ be 00230 /// inlined. 00231 operator TYPE () const { return value_; }; 00232 00233 /// TYPE & conversion. Inlined here so that it should _always_ be 00234 /// inlined. 00235 operator TYPE &() { return value_; }; 00236 00237 private: 00238 /// The wrapped value. 00239 TYPE value_; 00240 }; 00241 00242 ACE_END_VERSIONED_NAMESPACE_DECL 00243 00244 #if defined (__ACE_INLINE__) 00245 #include "ace/TSS_T.inl" 00246 #endif /* __ACE_INLINE__ */ 00247 00248 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) 00249 #include "ace/TSS_T.cpp" 00250 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ 00251 00252 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) 00253 #pragma implementation ("TSS_T.cpp") 00254 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ 00255 00256 #include /**/ "ace/post.h" 00257 #endif /* ACE_TSS_T_H */