...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Thread local storage allows multi-threaded applications to have a separate
instance of a given data item for each thread. Where a single-threaded application
would use static or global data, this could lead to contention, deadlock or
data corruption in a multi-threaded application. One example is the C errno
variable, used for storing the error
code related to functions from the Standard C library. It is common practice
(and required by POSIX) for compilers that support multi-threaded applications
to provide a separate instance of errno
for each thread, in order to avoid different threads competing to read or update
the value.
Though compilers often provide this facility in the form of extensions to the
declaration syntax (such as __declspec(thread)
or
annotations on thread
static
or namespace-scope
variable declarations), such support is non-portable, and is often limited
in some way, such as only supporting POD types.
boost::thread_specific_ptr
boost::thread_specific_ptr
provides a portable mechanism
for thread-local storage that works on all compilers supported by Boost.Thread. Each instance of boost::thread_specific_ptr
represents a pointer to an object (such as errno
)
where each thread must have a distinct value. The value for the current thread
can be obtained using the get()
member function, or by using the *
and ->
pointer deference operators. Initially the pointer has a value of NULL
in each thread, but the value for the
current thread can be set using the reset()
member function.
If the value of the pointer for the current thread is changed using reset()
,
then the previous value is destroyed by calling the cleanup routine. Alternatively,
the stored value can be reset to NULL
and the prior value returned by calling the release()
member function, allowing the application
to take back responsibility for destroying the object.
When a thread exits, the objects associated with each boost::thread_specific_ptr
instance are destroyed. By default, the object pointed to by a pointer p
is destroyed by invoking delete p
,
but this can be overridden for a specific instance of boost::thread_specific_ptr
by providing a cleanup routine to the constructor. In this case, the object
is destroyed by invoking func(p)
where func
is the cleanup routine
supplied to the constructor. The cleanup functions are called in an unspecified
order. If a cleanup routine sets the value of associated with an instance of
boost::thread_specific_ptr
that has already been
cleaned up, that value is added to the cleanup list. Cleanup finishes when
there are no outstanding instances of boost::thread_specific_ptr
with values.
Note: on some platforms, cleanup of thread-specific data is not performed for
threads created with the platform's native API. On those platforms such cleanup
is only done for threads that are started with boost::thread
unless boost::on_thread_exit()
is called manually from that thread.
Boost.Thread uses the address of the thread_specific_ptr
instance as key of the thread specific pointers. This avoids to create/destroy
a key which will need a lock to protect from race conditions. This has a little
performance liability, as the access must be done using an associative container.
// #include <boost/thread/tss.hpp> namespace boost { template <typename T> class thread_specific_ptr { public: thread_specific_ptr(); explicit thread_specific_ptr(void (*cleanup_function)(T*)); ~thread_specific_ptr(); T* get() const; T* operator->() const; T& operator*() const; T* release(); void reset(T* new_value=0); }; }
delete this->get()
is well-formed.
Construct a thread_specific_ptr
object for storing a pointer to an object of type T
specific to each thread. The default delete
-based
cleanup function will be used to destroy any thread-local objects
when reset()
is called, or the thread exits.
boost::thread_resource_error
if an error
occurs.
cleanup_function(this->get())
does not throw any exceptions.
Construct a thread_specific_ptr
object for storing a pointer to an object of type T
specific to each thread. The supplied cleanup_function
will be used to destroy any thread-local objects when reset()
is called, or the thread exits.
boost::thread_resource_error
if an error
occurs.
All the thread specific instances associated to this thread_specific_ptr (except maybe the one associated to this thread) must be null.
Calls this->reset()
to clean up the associated value for the current thread, and destroys
*this
.
Nothing.
The requirement is due to the fact that in order to delete all these instances, the implementation should be forced to maintain a list of all the threads having an associated specific ptr, which is against the goal of thread specific data.
Note | |
---|---|
Care needs to be taken to ensure that any threads still running after
an instance of |
The pointer associated with the current thread.
Nothing.
Note | |
---|---|
The initial value associated with an instance of |
this->get()
Nothing.
this->get
is not NULL
.
*(this->get())
Nothing.
If this->get()!=new_value
and this->get()
is non-NULL
,
invoke delete this->get()
or cleanup_function(this->get())
as appropriate. Store new_value
as the pointer associated
with the current thread.
this->get()==new_value
boost::thread_resource_error
if an error
occurs.
Return this->get()
and store NULL
as
the pointer associated with the current thread without invoking the
cleanup function.
this->get()==0
Nothing.