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 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 */

Generated on Tue Feb 2 17:18:43 2010 for ACE by  doxygen 1.4.7