From 6a1257442bb82e9082a55cacc2c6ebe02b4aa540 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Wed, 1 Oct 2014 21:40:12 +0200 Subject: [PATCH] re-factoring of thread_local_ptr<> Conflicts: include/boost/fiber/detail/scheduler.hpp src/detail/scheduler.cpp src/fiber_manager.cpp --- include/boost/fiber/detail/scheduler.hpp | 109 +-------------- .../boost/fiber/posix/thread_local_ptr.hpp | 128 ++++++++++++++++++ include/boost/fiber/thread_local_ptr.hpp | 14 ++ .../boost/fiber/windows/thread_local_ptr.hpp | 42 ++++++ src/detail/scheduler.cpp | 1 + src/detail/worker_fiber.cpp | 3 +- src/fiber_manager.cpp | 2 + 7 files changed, 191 insertions(+), 108 deletions(-) create mode 100644 include/boost/fiber/posix/thread_local_ptr.hpp create mode 100644 include/boost/fiber/thread_local_ptr.hpp create mode 100644 include/boost/fiber/windows/thread_local_ptr.hpp diff --git a/include/boost/fiber/detail/scheduler.hpp b/include/boost/fiber/detail/scheduler.hpp index ee8a0611..f64e9a2e 100644 --- a/include/boost/fiber/detail/scheduler.hpp +++ b/include/boost/fiber/detail/scheduler.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #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 > diff --git a/include/boost/fiber/posix/thread_local_ptr.hpp b/include/boost/fiber/posix/thread_local_ptr.hpp new file mode 100644 index 00000000..de26e917 --- /dev/null +++ b/include/boost/fiber/posix/thread_local_ptr.hpp @@ -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_key_create, pthread_[gs]etspecific + +#include +#include +#include + +#include + +#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 diff --git a/include/boost/fiber/thread_local_ptr.hpp b/include/boost/fiber/thread_local_ptr.hpp new file mode 100644 index 00000000..7b387631 --- /dev/null +++ b/include/boost/fiber/thread_local_ptr.hpp @@ -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 + +# if defined(BOOST_WINDOWS) +#include +# else +#include +# endif diff --git a/include/boost/fiber/windows/thread_local_ptr.hpp b/include/boost/fiber/windows/thread_local_ptr.hpp new file mode 100644 index 00000000..0bae6c66 --- /dev/null +++ b/include/boost/fiber/windows/thread_local_ptr.hpp @@ -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 +#include +#include + +#include + +#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 diff --git a/src/detail/scheduler.cpp b/src/detail/scheduler.cpp index 4c36e0fd..f69eaab9 100644 --- a/src/detail/scheduler.cpp +++ b/src/detail/scheduler.cpp @@ -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) diff --git a/src/detail/worker_fiber.cpp b/src/detail/worker_fiber.cpp index c7fa9f5f..02de34ca 100644 --- a/src/detail/worker_fiber.cpp +++ b/src/detail/worker_fiber.cpp @@ -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 diff --git a/src/fiber_manager.cpp b/src/fiber_manager.cpp index dfa234e6..6cf3601a 100644 --- a/src/fiber_manager.cpp +++ b/src/fiber_manager.cpp @@ -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)