server/dep/ACE_wrappers/ace/TSS_T.h
zerg b8d773091a [10874] Update ACE to v5.8.3
(based on zergtmn's repo commit 3a8c259)
(based on zergtmn's repo commit 946c1a8)

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
2010-12-14 17:37:42 +03:00

269 lines
9.1 KiB
C++

// -*- C++ -*-
//==========================================================================
/**
* @file TSS_T.h
*
* $Id: TSS_T.h 91703 2010-09-10 11:05:38Z msmit $
*
* 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;
// ACE_ALLOC_HOOK_DECLARE;
// Declare the dynamic allocation hooks.
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 */