00001 // -*- C++ -*- 00002 00003 //========================================================================== 00004 /** 00005 * @file TSS_T.h 00006 * 00007 * TSS_T.h,v 4.8 2006/05/07 21:13:13 jeliazkov_i Exp 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 is a wrapper around the OS thread library 00054 * thread-specific functions. It uses the <C++ operator->> to 00055 * shield applications from the details of accessing 00056 * thread-specific storage. 00057 * 00058 * @note For maximal portability, <TYPE> cannot be a built-in type, 00059 * but instead should be a user-defined class (some compilers will 00060 * allow a built-in type, others won't). See template class 00061 * ACE_TSS_Type_Adapter, below, for adapting built-in types to work 00062 * with ACE_TSS. 00063 * 00064 * @note Beware when creating static instances of this type 00065 * (as with any other, btw). The unpredictable order of initialization 00066 * across different platforms may cause a situation where you'd use 00067 * the instance, before it is fully initialized. That's why typically 00068 * instances of this type are dynamicaly allocated. On the stack it is 00069 * typically allocated inside the ACE_Thread::svc() method which 00070 * limits its lifetime appropriately. 00071 * 00072 */ 00073 template <class TYPE> 00074 class ACE_TSS 00075 { 00076 public: 00077 // = Initialization and termination methods. 00078 00079 /** 00080 * If caller has passed us a non-NULL ts_obj *, then we'll just use 00081 * this to initialize the thread-specific value (but only for the 00082 * calling thread). Thus, subsequent calls to <operator->> in this 00083 * thread will return this value. This is useful since it enables 00084 * us to assign objects to thread-specific data that have 00085 * arbitrarily complex constructors. 00086 * 00087 */ 00088 ACE_TSS (TYPE *ts_obj = 0); 00089 00090 /// Deregister with thread-key administration. 00091 virtual ~ACE_TSS (void); 00092 00093 // = Accessors. 00094 00095 /** 00096 * Get the thread-specific object for the key associated with this 00097 * object. Returns 0 if the data has never been initialized, 00098 * otherwise returns a pointer to the data. 00099 */ 00100 TYPE *ts_object (void) const; 00101 00102 /// Set the thread-specific object for the key associated with this 00103 /// object. 00104 TYPE *ts_object (TYPE *); 00105 00106 /// Use a "smart pointer" to get the thread-specific object 00107 /// associated with the <key_>. 00108 TYPE *operator-> () const; 00109 00110 /// Return or create and return the calling threads TYPE object. 00111 operator TYPE *(void) const; 00112 00113 /// Hook for construction parameters. 00114 virtual TYPE *make_TSS_TYPE (void) const; 00115 00116 // = Utility methods. 00117 00118 /// Dump the state of an object. 00119 void dump (void) const; 00120 00121 // ACE_ALLOC_HOOK_DECLARE; 00122 // Declare the dynamic allocation hooks. 00123 00124 protected: 00125 /// Actually implements the code that retrieves the object from 00126 /// thread-specific storage. 00127 TYPE *ts_get (void) const; 00128 00129 /// Factors out common code for initializing TSS. This must NOT be 00130 /// called with the lock held... 00131 int ts_init (void); 00132 00133 #if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))) 00134 /// This implementation only works for non-threading systems... 00135 TYPE *type_; 00136 #else 00137 /// Avoid race conditions during initialization. 00138 ACE_Thread_Mutex keylock_; 00139 00140 /// "First time in" flag. 00141 int once_; 00142 00143 /// Key for the thread-specific error data. 00144 ACE_thread_key_t key_; 00145 00146 /// "Destructor" that deletes internal TYPE * when thread exits. 00147 static void cleanup (void *ptr); 00148 #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */ 00149 // = Disallow copying... 00150 ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS<TYPE> &)) 00151 ACE_UNIMPLEMENTED_FUNC (ACE_TSS (const ACE_TSS<TYPE> &)) 00152 }; 00153 00154 /** 00155 * @class ACE_TSS_Type_Adapter 00156 * 00157 * @brief Adapter that allows built-in types to be used with ACE_TSS. 00158 * 00159 * Wraps a value of a built-in type, providing conversions to 00160 * and from the type. Example use with ACE_TSS: 00161 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i; 00162 * *i = 37; 00163 * ACE_OS::fprintf (stderr, "%d\n", *i); 00164 * Unfortunately, though, some compilers have trouble with the 00165 * implicit type conversions. This seems to work better: 00166 * ACE_TSS<ACE_TSS_Type_Adapter<int> > i; 00167 * i->operator int & () = 37; 00168 * ACE_OS::fprintf (stderr, "%d\n", i->operator int ()); 00169 */ 00170 template <class TYPE> 00171 class ACE_TSS_Type_Adapter 00172 { 00173 public: 00174 /// Constructor. Inlined here so that it should _always_ be inlined. 00175 ACE_TSS_Type_Adapter (const TYPE value = 0): value_ (value) {} 00176 00177 /// TYPE conversion. Inlined here so that it should _always_ be 00178 /// inlined. 00179 operator TYPE () const { return value_; }; 00180 00181 /// TYPE & conversion. Inlined here so that it should _always_ be 00182 /// inlined. 00183 operator TYPE &() { return value_; }; 00184 00185 private: 00186 /// The wrapped value. 00187 TYPE value_; 00188 }; 00189 00190 ACE_END_VERSIONED_NAMESPACE_DECL 00191 00192 #if defined (__ACE_INLINE__) 00193 #include "ace/TSS_T.inl" 00194 #endif /* __ACE_INLINE__ */ 00195 00196 #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) 00197 #include "ace/TSS_T.cpp" 00198 #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ 00199 00200 #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) 00201 #pragma implementation ("TSS_T.cpp") 00202 #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ 00203 00204 #include /**/ "ace/post.h" 00205 #endif /* ACE_TSS_T_H */