1 2 // Copyright Oliver Kowalke 2013. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // based on tss.hpp from boost.thread 8 9 #ifndef BOOST_FIBERS_FSS_H 10 #define BOOST_FIBERS_FSS_H 11 12 #include <boost/config.hpp> 13 14 #include <boost/fiber/context.hpp> 15 #include <boost/fiber/detail/fss.hpp> 16 17 #ifdef BOOST_HAS_ABI_HEADERS 18 # include BOOST_ABI_PREFIX 19 #endif 20 21 namespace boost { 22 namespace fibers { 23 24 template< typename T > 25 class fiber_specific_ptr { 26 private: 27 struct default_cleanup_function : public detail::fss_cleanup_function { operator ()boost::fibers::fiber_specific_ptr::default_cleanup_function28 void operator()( void * data) noexcept override { 29 delete static_cast< T * >( data); 30 } 31 }; 32 33 struct custom_cleanup_function : public detail::fss_cleanup_function { 34 void (*fn)(T*); 35 custom_cleanup_functionboost::fibers::fiber_specific_ptr::custom_cleanup_function36 explicit custom_cleanup_function( void(*fn_)(T*) ) noexcept : 37 fn{ fn_ } { 38 } 39 operator ()boost::fibers::fiber_specific_ptr::custom_cleanup_function40 void operator()( void * data) override { 41 if ( BOOST_LIKELY( nullptr != fn) ) { 42 fn( static_cast< T * >( data) ); 43 } 44 } 45 }; 46 47 detail::fss_cleanup_function::ptr_t cleanup_fn_; 48 49 public: 50 using element_type = T; 51 fiber_specific_ptr()52 fiber_specific_ptr() : 53 cleanup_fn_{ new default_cleanup_function() } { 54 } 55 fiber_specific_ptr(void (* fn)(T *))56 explicit fiber_specific_ptr( void(*fn)(T*) ) : 57 cleanup_fn_{ new custom_cleanup_function( fn) } { 58 } 59 ~fiber_specific_ptr()60 ~fiber_specific_ptr() { 61 context * active_ctx = context::active(); 62 if ( nullptr != active_ctx) { 63 active_ctx->set_fss_data( 64 this, cleanup_fn_, nullptr, true); 65 } 66 } 67 68 fiber_specific_ptr( fiber_specific_ptr const&) = delete; 69 fiber_specific_ptr & operator=( fiber_specific_ptr const&) = delete; 70 get() const71 T * get() const noexcept { 72 BOOST_ASSERT( context::active() ); 73 void * vp = context::active()->get_fss_data( this); 74 return static_cast< T * >( vp); 75 } 76 operator ->() const77 T * operator->() const noexcept { 78 return get(); 79 } 80 operator *() const81 T & operator*() const noexcept { 82 return * get(); 83 } 84 release()85 T * release() { 86 T * tmp = get(); 87 context::active()->set_fss_data( 88 this, cleanup_fn_, nullptr, false); 89 return tmp; 90 } 91 reset(T * t)92 void reset( T * t) { 93 T * c = get(); 94 if ( BOOST_LIKELY( c != t) ) { 95 context::active()->set_fss_data( 96 this, cleanup_fn_, t, true); 97 } 98 } 99 }; 100 101 }} 102 103 #ifdef BOOST_HAS_ABI_HEADERS 104 # include BOOST_ABI_SUFFIX 105 #endif 106 107 #endif // BOOST_FIBERS_FSS_H 108