mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-13 00:12:17 +00:00
re-factoring of thread_local_ptr<>
Conflicts: include/boost/fiber/detail/scheduler.hpp src/detail/scheduler.cpp src/fiber_manager.cpp
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
#include <boost/fiber/detail/fiber_base.hpp>
|
||||
#include <boost/fiber/fiber_manager.hpp>
|
||||
#include <boost/fiber/thread_local_ptr.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
@@ -32,117 +33,11 @@ namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
#if ! (defined(__APPLE__) && defined(BOOST_HAS_PTHREADS))
|
||||
|
||||
# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) || \
|
||||
(defined(__ICC) && defined(BOOST_WINDOWS))
|
||||
# define TLS_VAR_DECL(type) __declspec(thread) type
|
||||
# else
|
||||
# define TLS_VAR_DECL(type) __thread type
|
||||
# endif // if defined(_MSC_VER) || defined(__BORLANDC__) || ...
|
||||
|
||||
// generic thread_local_ptr
|
||||
template< typename T >
|
||||
class thread_local_ptr : private noncopyable
|
||||
{
|
||||
private:
|
||||
typedef void ( * cleanup_function)( T *);
|
||||
|
||||
static void default_cleanup( T * t)
|
||||
{ delete t; }
|
||||
|
||||
static TLS_VAR_DECL(T) * t_;
|
||||
|
||||
cleanup_function cf_;
|
||||
|
||||
public:
|
||||
thread_local_ptr() BOOST_NOEXCEPT :
|
||||
cf_( & thread_local_ptr::default_cleanup)
|
||||
{}
|
||||
|
||||
thread_local_ptr( cleanup_function cf) BOOST_NOEXCEPT :
|
||||
cf_( cf)
|
||||
{}
|
||||
|
||||
~thread_local_ptr()
|
||||
{ if ( 0 != cf_) cf_( t_); }
|
||||
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL();
|
||||
|
||||
T * get() const BOOST_NOEXCEPT
|
||||
{ return t_; }
|
||||
|
||||
bool operator!() const BOOST_NOEXCEPT
|
||||
{ return ! get(); }
|
||||
|
||||
bool operator==( thread_local_ptr const& other) BOOST_NOEXCEPT
|
||||
{ return this->get() == other.get(); }
|
||||
|
||||
bool operator!=( thread_local_ptr const& other) BOOST_NOEXCEPT
|
||||
{ return ! ( * this == other); }
|
||||
|
||||
void reset( T * t) BOOST_NOEXCEPT
|
||||
{ t_ = t; }
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
TLS_VAR_DECL(T) * thread_local_ptr< T >::t_ = 0;
|
||||
|
||||
#undef TLS_VAR_DECL
|
||||
|
||||
#else // Mac-specific thread_local_ptr
|
||||
template< typename T >
|
||||
class thread_local_ptr : private noncopyable
|
||||
{
|
||||
private:
|
||||
static void default_cleanup( void * ptr)
|
||||
{
|
||||
T * obj = static_cast< T * >( ptr);
|
||||
delete obj;
|
||||
}
|
||||
|
||||
::pthread_key_t key_;
|
||||
|
||||
public:
|
||||
/// By default, use a thread-exit cleanup function that deletes T*.
|
||||
thread_local_ptr() BOOST_NOEXCEPT
|
||||
{
|
||||
int ok = ::pthread_key_create( & key_, & thread_local_ptr::default_cleanup);
|
||||
BOOST_ASSERT( ok == 0);
|
||||
(void)ok;
|
||||
}
|
||||
|
||||
/// Allow caller to override cleanup function, 0 to suppress
|
||||
thread_local_ptr( cleanup_function cf) BOOST_NOEXCEPT
|
||||
{
|
||||
int ok = ::pthread_key_create( & key_, cf);
|
||||
BOOST_ASSERT( ok == 0);
|
||||
(void)ok;
|
||||
}
|
||||
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL();
|
||||
|
||||
T * get() const BOOST_NOEXCEPT
|
||||
{ return static_cast< T * >( ::pthread_getspecific( key_) ); }
|
||||
|
||||
bool operator!() const BOOST_NOEXCEPT
|
||||
{ return ! get(); }
|
||||
|
||||
bool operator==( thread_local_ptr const& other) BOOST_NOEXCEPT
|
||||
{ return this->get() == other.get(); }
|
||||
|
||||
bool operator!=( thread_local_ptr const& other) BOOST_NOEXCEPT
|
||||
{ return ! ( * this == other); }
|
||||
|
||||
void reset( T * ptr) BOOST_NOEXCEPT
|
||||
{ ::pthread_setspecific( key_, ptr); }
|
||||
};
|
||||
#endif // Mac-specific thread_local_ptr
|
||||
|
||||
class scheduler : private noncopyable
|
||||
{
|
||||
private:
|
||||
static thread_local_ptr< fiber_manager > instance_;
|
||||
//static thread_specific_ptr< fiber_manager > instance_;
|
||||
|
||||
public:
|
||||
template< typename F >
|
||||
|
||||
128
include/boost/fiber/posix/thread_local_ptr.hpp
Normal file
128
include/boost/fiber/posix/thread_local_ptr.hpp
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2013.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_FIBERS_THREAD_LOCAL_PTR_H
|
||||
#define BOOST_FIBERS_THREAD_LOCAL_PTR_H
|
||||
|
||||
#include <pthread.h> // pthread_key_create, pthread_[gs]etspecific
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/utility/explicit_operator_bool.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
# if ! (defined(__APPLE__) && defined(BOOST_HAS_PTHREADS))
|
||||
template< typename T >
|
||||
class thread_local_ptr : private noncopyable
|
||||
{
|
||||
private:
|
||||
static void cleanup_function( void * vp)
|
||||
{
|
||||
thread_local_ptr< T > * p = static_cast< thread_local_ptr< T > * >( vp);
|
||||
BOOST_ASSERT( 0 != p);
|
||||
delete p->t_;
|
||||
p->t_ = 0;
|
||||
}
|
||||
|
||||
static __thread T * t_;
|
||||
|
||||
pthread_key_t key_;
|
||||
|
||||
public:
|
||||
thread_local_ptr() BOOST_NOEXCEPT :
|
||||
key_()
|
||||
{ ::pthread_key_create( & key_, & thread_local_ptr::cleanup_function); }
|
||||
|
||||
~thread_local_ptr()
|
||||
{ if ( 0 != t_) cleanup_function( t_); } // required for single-threaded apps
|
||||
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL();
|
||||
|
||||
T * get() const BOOST_NOEXCEPT
|
||||
{ return t_; }
|
||||
|
||||
bool operator!() const BOOST_NOEXCEPT
|
||||
{ return ! get(); }
|
||||
|
||||
bool operator==( thread_local_ptr const& other) BOOST_NOEXCEPT
|
||||
{ return this->get() == other.get(); }
|
||||
|
||||
bool operator!=( thread_local_ptr const& other) BOOST_NOEXCEPT
|
||||
{ return ! ( * this == other); }
|
||||
|
||||
void reset( T * t) BOOST_NOEXCEPT
|
||||
{
|
||||
t_ = t;
|
||||
::pthread_setspecific( key_, this);
|
||||
}
|
||||
};
|
||||
template< typename T >
|
||||
__thread T * thread_local_ptr< T >::t_ = 0;
|
||||
# else
|
||||
template< typename T >
|
||||
class thread_local_ptr : private noncopyable
|
||||
{
|
||||
private:
|
||||
static void cleanup_function( void * vp)
|
||||
{
|
||||
thread_local_ptr< T > * p = static_cast< thread_local_ptr< T > * >( vp);
|
||||
BOOST_ASSERT( 0 != p);
|
||||
T * t = static_cast< T * >( ::pthread_getspecific( p->t_key_) );
|
||||
delete t;
|
||||
::pthread_setspecific( p->t_key_, 0);
|
||||
}
|
||||
|
||||
pthread_key_t this_key_;
|
||||
pthread_key_t t_key_;
|
||||
|
||||
public:
|
||||
thread_local_ptr() BOOST_NOEXCEPT :
|
||||
this_key_(), t_key_()
|
||||
{
|
||||
::pthread_key_create( & this_key_, & thread_local_ptr::cleanup_function);
|
||||
::pthread_key_create( & t_key_, 0);
|
||||
}
|
||||
|
||||
~thread_local_ptr()
|
||||
{ if ( 0 != t_) cleanup_function( t_); } // required for single-threaded apps
|
||||
|
||||
BOOST_EXPLICIT_OPERATOR_BOOL();
|
||||
|
||||
T * get() const BOOST_NOEXCEPT
|
||||
{ return static_cast< T * >( ::pthread_getspecific( t_key_) ); }
|
||||
|
||||
bool operator!() const BOOST_NOEXCEPT
|
||||
{ return ! get(); }
|
||||
|
||||
bool operator==( thread_local_ptr const& other) BOOST_NOEXCEPT
|
||||
{ return this->get() == other.get(); }
|
||||
|
||||
bool operator!=( thread_local_ptr const& other) BOOST_NOEXCEPT
|
||||
{ return ! ( * this == other); }
|
||||
|
||||
void reset( T * t) BOOST_NOEXCEPT
|
||||
{
|
||||
::pthread_setspecific( this_key_, this);
|
||||
::pthread_setspecific( t_key_, t);
|
||||
}
|
||||
};
|
||||
# endif
|
||||
|
||||
}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_THREAD_LOCAL_PTR_H
|
||||
14
include/boost/fiber/thread_local_ptr.hpp
Normal file
14
include/boost/fiber/thread_local_ptr.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2013.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
# if defined(BOOST_WINDOWS)
|
||||
#include <boost/fiber/windows/thread_local_ptr.hpp>
|
||||
# else
|
||||
#include <boost/fiber/posix/thread_local_ptr.hpp>
|
||||
# endif
|
||||
42
include/boost/fiber/windows/thread_local_ptr.hpp
Normal file
42
include/boost/fiber/windows/thread_local_ptr.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2013.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_FIBERS_THREAD_LOCAL_PTR_H
|
||||
#define BOOST_FIBERS_THREAD_LOCAL_PTR_H
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
//# pragma warning(disable:4251 4275)
|
||||
# endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
template< typename T >
|
||||
struct thread_local_ptr : public boost::thread_specific_ptr< T >
|
||||
{};
|
||||
|
||||
}}
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_THREAD_LOCAL_PTR_H
|
||||
@@ -18,6 +18,7 @@ namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
thread_local_ptr< fiber_manager > scheduler::instance_;
|
||||
//thread_specific_ptr< fiber_manager > scheduler::instance_;
|
||||
|
||||
void
|
||||
scheduler::replace( sched_algorithm * other)
|
||||
|
||||
@@ -62,9 +62,10 @@ worker_fiber::release()
|
||||
BOOST_FOREACH( worker_fiber * p, waiting)
|
||||
{ p->set_ready(); }
|
||||
|
||||
// release all fiber-specific-pointers
|
||||
// release fiber-specific-data
|
||||
BOOST_FOREACH( fss_data_t::value_type & data, fss_data_)
|
||||
{ data.second.do_cleanup(); }
|
||||
fss_data_.clear();
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -59,6 +59,8 @@ fiber_manager::~fiber_manager() BOOST_NOEXCEPT
|
||||
// if not referenced on other places
|
||||
while ( ! wqueue_.empty() )
|
||||
fm_run();
|
||||
active_fiber_ = 0;
|
||||
fprintf(stderr, "~fiber_manager()\n");
|
||||
}
|
||||
|
||||
void fm_resume_( detail::worker_fiber * f)
|
||||
|
||||
Reference in New Issue
Block a user