TSS_T.h

Go to the documentation of this file.
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 */

Generated on Sun Jan 27 12:05:42 2008 for ACE by doxygen 1.3.6