2
0
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:
Oliver Kowalke
2014-10-01 21:40:12 +02:00
parent 70440591cf
commit 6a1257442b
7 changed files with 191 additions and 108 deletions

View File

@@ -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 >

View 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

View 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

View 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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)