TSS_T.h

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

Generated on Thu Nov 9 09:42:08 2006 for ACE by doxygen 1.3.6