Zero  0.1.0
Classes | Namespaces | Macros | Variables
tls.h File Reference
#include <pthread.h>
#include <new>

Go to the source code of this file.

Classes

class  tls_tricks::tls_manager
 A management class for non-POD thread-local storage. More...
 
struct  tls_tricks::tls_manager_schwarz
 Static struct to make sure tls_manager's global init() and fini() are called. More...
 
struct  tls_tricks::tls_blob< T >
 Wrapper for a type, used by TLS_STRUCT helper macro. More...
 

Namespaces

 tls_tricks
 A namespace for thread-local storage tricks.
 

Macros

#define TLS_STRUCT(Type, Name, InitFn)
 Helper macro for DECLARE_TLS. Do not use directly. More...
 
#define DECLARE_TLS(Type, Name)
 Cause non-POD TLS object of Type to be created and initialized. More...
 
#define DECLARE_TLS_SCHWARZ(Name)
 Cause a Schwarz counter to be declared (for use in header files). More...
 
#define DEFINE_TLS_SCHWARZ(Type, Name)
 Cause a Schwarz counter to be defined (for use in .cpp files). More...
 

Variables

static struct tls_manager_schwarz tls_tricks::tlsm_schwarz_one_and_only
 

Detailed Description

Cause macro definitions to show up in doxygen-generated pages

Macro Definition Documentation

§ DECLARE_TLS

#define DECLARE_TLS (   Type,
  Name 
)
Value:
TLS_STRUCT(Type, Name##_tls_wrapper, Name##_tls_wrapper) Name
#define TLS_STRUCT(Type, Name, InitFn)
Helper macro for DECLARE_TLS. Do not use directly.
Definition: tls.h:234

Cause non-POD TLS object of Type to be created and initialized.

This macro declares a static "smart pointer" named * Name_tls_wrapper to a thread-local variable of the given Type. When this static struct get initialized at static-init time, it registers with the tls manager its init and fini methods. Those methods invoke the init and fini methods of the item to which this "smart pointer" points, which is the actual TLS entity: a tls_tricks::tls_blobType.

§ DECLARE_TLS_SCHWARZ

#define DECLARE_TLS_SCHWARZ (   Name)
Value:
static struct Name##_tls_wrapper_schwarz { \
Name##_tls_wrapper_schwarz(); \
} Name##_schwarz

Cause a Schwarz counter to be declared (for use in header files).

Make a Swatchz counter (in a .h) to force initialization of the TLS defined in a .cpp by DEFINE_TLS_SCHWARZ. This is useful if there is a dependency between 2+ TLS variables so the correct one is initialized first. The only way you can control their order is to make sure their DECLARE_TLS_SCHWARZ macros are in the correct order b/c C++ guarantees static init order only for objects in the same translation unit. Note that the counter is really in the tls wrapper.

§ DEFINE_TLS_SCHWARZ

#define DEFINE_TLS_SCHWARZ (   Type,
  Name 
)
Value:
static TLS_STRUCT(Type, Name##_tls_wrapper, static void init_wrapper) Name; \
Name##_tls_wrapper_schwarz::Name##_tls_wrapper_schwarz() { \
Name##_tls_wrapper::init_wrapper(); \
}
#define TLS_STRUCT(Type, Name, InitFn)
Helper macro for DECLARE_TLS. Do not use directly.
Definition: tls.h:234

Cause a Schwarz counter to be defined (for use in .cpp files).

Define the TLS struct that DECLARE_TLS_SCHWARZ expects to initialize.

§ TLS_STRUCT

#define TLS_STRUCT (   Type,
  Name,
  InitFn 
)
Value:
struct Name { \
typedef tls_tricks::tls_blob< Type > Wrapper; \
Type &operator*() { return *get(); } \
Type* operator->() { return get(); } \
operator Type*() { return get(); } \
static Wrapper* get_wrapper() { \
static __thread Wrapper val; \
return &val; \
} \
static Type* get() { return get_wrapper()->get(); } \
static void init() { get_wrapper()->init(); } \
static void fini() { get_wrapper()->fini(); } \
InitFn() { \
static bool initialized = false; \
if(initialized) \
return; \
initialized = true; \
} \
}
Wrapper for a type, used by TLS_STRUCT helper macro.
Definition: tls.h:151
static void register_tls(void(*init)(), void(*fini)())
Definition: tls.cpp:93
decimal operator*(int a, decimal const &b)
Definition: decimal.h:151

Helper macro for DECLARE_TLS. Do not use directly.

A helper macro for DECLARE_TLS.

Attention
Do not use this macro directly.

Creates a "smart pointer" structure with the given Name; the pointer is to an object of the given Type. Actually, it's a pointer to a tls_blob, which is a bunch of untyped bytes, but they get initialized via placement new when a thread starts and "destructed" when the thread goes away. Passing in the InitFn allows us to register a non-trivial constructor, i.e., it allows us to use non-POD types in thread-local storage. This only lets us use a default constructor, but the compiler's idea of trivial is more strict than just having a default constructor.