text: // -*- C++ -*-
  
  //==========================================================================
  /**
   *  @file    TSS_T.h
   *
   *   Moved from Synch.h.
   *
   *  @author Douglas C. Schmidt <schmidt@cs.wustl.edu>
   */
  //==========================================================================
  
  #ifndef ACE_TSS_T_H
  #define ACE_TSS_T_H
  #include /**/ "ace/pre.h"
  
  #include "ace/Lock.h"
  
  #if !defined (ACE_LACKS_PRAGMA_ONCE)
  # pragma once
  #endif /* ACE_LACKS_PRAGMA_ONCE */
  
  // This should probably go somewhere else, but it's only used here and
  // in Thread_Manager.
  // Note there is no ACE_TSS_SET because one would typicaly do
  // 'ACE_TSS_GET()->xyz_ = value', so the macro would have been too
  // complicated.
  # if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION))
  #   define ACE_TSS_TYPE(T) ACE_TSS< T >
  #   define ACE_TSS_GET(I, T) ((I)->operator T * ())
  # else
  #   define ACE_TSS_TYPE(T) T
  #   define ACE_TSS_GET(I, T) (I)
  # endif /* ACE_HAS_THREADS && (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION) */
  
  #include "ace/Thread_Mutex.h"
  #include "ace/Copy_Disabled.h"
  
  ACE_BEGIN_VERSIONED_NAMESPACE_DECL
  
  #if defined (ACE_HAS_THR_C_DEST)
  class ACE_TSS_Adapter;
  #endif
  
  /**
   * @class ACE_TSS
   *
   * @brief Allows objects that are "physically" in thread specific
   * storage (i.e., private to a thread) to be accessed as though
   * they were "logically" global to a program.
   *
   * This class helps to maintain a separate copy of an object for each thread
   * that needs access to it. All threads access a single instance of ACE_TSS
   * to obtain a pointer to a thread-specific copy of a TYPE object. Using
   * a pointer to TYPE in TSS instead of TYPE itself is useful because,
   * in addition to avoiding copies on what may be a complex class, it allows
   * assignment of objects to thread-specific data that have arbitrarily
   * complex constructors.
   *
   * When the ACE_TSS object is destroyed, all threads's instances of the
   * data are deleted.
   *
   * Modern compilers have no problem using a built-in type for @c TYPE.
   * However, if you must use an older compiler that won't work with a built-in
   * type, the ACE_TSS_Type_Adapter class template, below, can be used for
   * adapting built-in types to work with ACE_TSS.
   *
   * @note Beware when creating static instances of this type
   * (as with any other, btw). The unpredictable order of initialization
   * across different platforms may cause a situation where one uses
   * the instance before it is fully initialized. That's why typically
   * instances of this type are dynamicaly allocated. On the stack it is
   * typically allocated inside the ACE_Thread::svc() method which
   * limits its lifetime appropriately.
   */
  template <class TYPE>
  class ACE_TSS : private ACE_Copy_Disabled
  {
  public:
    /**
     * Default constructor. Can also initialize this ACE_TSS instance,
     * readying it for use by the calling thread as well as all other
     * threads in the process. If the constructor does not initialize this
     * object, the first access to it will perform the initialization, which
     * could possibly (under odd error conditions) fail.
     *
     * @param ts_obj   If non-zero, this object is initialized for use by
     *                 all threads and @a ts_obj is used to set the
     *                 thread-specific value for the calling thread. Other
     *                 threads use the ts_object (TYPE *) method to set
     *                 a specific value.
     */
    ACE_TSS (TYPE *ts_obj = 0);
  
    /// Deregister this object from thread-specific storage administration.
    /// Will cause all threads' copies of TYPE to be destroyed.
    virtual ~ACE_TSS (void);
  
    /**
     * Set the thread-specific object for the calling thread.
     * If this object has not been initialized yet, this method performs the
     * initialization.
     *
     * @param new_ts_obj  The new value for the calling thread's copy of
     *                    this object.
     *
     * @return  The previous value of the calling thread's copy of this
     *          object; 0 if there was no previous value. This method also
     *          returns 0 on errors. To tell the difference between an error
     *          and a returned 0 pointer, it's recommended that one set errno
     *          to 0 prior to calling ts_object() and check for a new errno
     *          value if ts_object() returns 0.
     */
    TYPE *ts_object (TYPE *new_ts_obj);
  
    /** @name Accessors
     *
     * All accessors return a pointer to the calling thread's copy of the
     * TYPE data. The pointer may be 0 on error conditions or if the calling
     * thread's copy of the data has not yet been set. See specific method
     * descriptions for complete details.
     */
    //@{
    /**
     * Get the thread-specific object for this object.
     *
     * @return  0 if the object has never been initialized, otherwise returns
     *          the calling thread's copy of the data. The returned pointer
     *          may be 0 under odd error conditions; check errno for further
     *          information.
     */
    TYPE *ts_object (void) const;
  
    /**
     * Use a "smart pointer" to get the thread-specific data associated
     * with this object.
     * If this ACE_TSS object hasn't been initialized, this method
     * will initialize it as a side-affect. If the calling thread has not
     * set a value, a default-constructed instance of TYPE is allocated and it
     * becomes the thread's instance.
     *
     * @return  The calling thread's copy of the data. The returned pointer
     *          may be 0 under odd error conditions; check errno for further
     *          information.
     */
    TYPE *operator-> () const;
  
    /**
     * Obtain a pointer to the calling thread's TYPE object.
     * If this ACE_TSS object hasn't been initialized, this method
     * will initialize it as a side-affect. If the calling thread has not
     * set a value, a default-constructed instance of TYPE is allocated and it
     * becomes the thread's instance.
     *
     * @return  The calling thread's copy of the data. The returned pointer
     *          may be 0 under odd error conditions; check errno for further
     *          information.
     */
    operator TYPE *(void) const;
  
    //@}
  
    /// Hook for construction parameters.
    virtual TYPE *make_TSS_TYPE (void) const;
  
    // = Utility methods.
  
    /// Dump the state of an object.
    void dump (void) const;
  
    /// Declare the dynamic allocation hooks.
    ACE_ALLOC_HOOK_DECLARE;
  
  protected:
    /// Actually implements the code that retrieves the object from
    /// thread-specific storage.
    TYPE *ts_get (void) const;
  
    /// Factors out common code for initializing TSS.  This must NOT be
    /// called with the lock held...
    int ts_init (void);
  
  #if !(defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)))
    /// This implementation only works for non-threading systems...
    TYPE *type_;
  #else
    /// Avoid race conditions during initialization.
    ACE_Thread_Mutex keylock_;
  
    /// "First time in" flag.
    volatile bool once_;
  
    /// Key for the thread-specific error data.
    ACE_thread_key_t key_;
  
    /// "Destructor" that deletes internal TYPE * when thread exits.
    static void cleanup (void *ptr);
  
    /// Obtains a plain value stored in the thread-specific storage.
  # if defined (ACE_HAS_THR_C_DEST)
    ACE_TSS_Adapter *ts_value (void) const;
  # else
    TYPE *ts_value (void) const;
  # endif /* ACE_HAS_THR_C_DEST */
  
    /// Stores a new plain value in the thread-specific storage.
  # if defined (ACE_HAS_THR_C_DEST)
    int ts_value (ACE_TSS_Adapter *new_tss_adapter) const;
  # else
    int ts_value (TYPE *new_ts_obj) const;
  # endif /* ACE_HAS_THR_C_DEST */
  #endif /* defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) */
  };
  
  /**
   * @class ACE_TSS_Type_Adapter
   *
   * @brief Adapter that allows built-in types to be used with ACE_TSS.
   *
   * Wraps a value of a built-in type, providing conversions to
   * and from the type.  Example use with ACE_TSS:
   * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
   * *i = 37;
   * ACE_OS::fprintf (stderr, "%d\n", *i);
   * Unfortunately, though, some compilers have trouble with the
   * implicit type conversions.  This seems to work better:
   * ACE_TSS<ACE_TSS_Type_Adapter<int> > i;
   * i->operator int & () = 37;
   * ACE_OS::fprintf (stderr, "%d\n", i->operator int ());
   */
  template <class TYPE>
  class ACE_TSS_Type_Adapter
  {
  public:
    /// Constructor.  Inlined here so that it should _always_ be inlined.
    ACE_TSS_Type_Adapter (const TYPE value = 0): value_ (value) {}
  
    /// TYPE conversion.  Inlined here so that it should _always_ be
    /// inlined.
    operator TYPE () const { return value_; };
  
    /// TYPE & conversion.  Inlined here so that it should _always_ be
    /// inlined.
    operator TYPE &() { return value_; };
  
  private:
    /// The wrapped value.
    TYPE value_;
  };
  
  ACE_END_VERSIONED_NAMESPACE_DECL
  
  #if defined (__ACE_INLINE__)
  #include "ace/TSS_T.inl"
  #endif /* __ACE_INLINE__ */
  
  #if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
  #include "ace/TSS_T.cpp"
  #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
  
  #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
  #pragma implementation ("TSS_T.cpp")
  #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
  
  #include /**/ "ace/post.h"
  #endif /* ACE_TSS_T_H */
  