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