From cb29688ff50fd20ec86c3e892dec0bcdfabb8b19 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Thu, 15 Jan 2015 18:32:45 +0100 Subject: [PATCH] fix destruction fcontext --- include/boost/context/execution_context.hpp | 143 ++++++++++---------- src/execution_context.cpp | 6 +- 2 files changed, 80 insertions(+), 69 deletions(-) diff --git a/include/boost/context/execution_context.hpp b/include/boost/context/execution_context.hpp index c8a5c1e..11c18d4 100644 --- a/include/boost/context/execution_context.hpp +++ b/include/boost/context/execution_context.hpp @@ -56,105 +56,98 @@ struct preallocated { class BOOST_CONTEXT_DECL execution_context { private: - struct base_context { + struct fcontext { std::size_t use_count; fcontext_t fctx; stack_context sctx; - base_context() noexcept : - use_count( 0), + // main-context + fcontext() noexcept : + use_count( 1), fctx( nullptr), sctx() { } - base_context( fcontext_t fctx_, stack_context const& sctx_) noexcept : + // worker-context + fcontext( fcontext_t fctx_, stack_context const& sctx_) noexcept : use_count( 0), fctx( fctx_), sctx( sctx_) { } - virtual ~base_context() noexcept { + virtual ~fcontext() noexcept { } - virtual void run() noexcept = 0; - virtual void deallocate() = 0; + virtual void deallocate() { + } - friend void intrusive_ptr_add_ref( base_context * ctx) { + virtual void run() noexcept { + } + + friend void intrusive_ptr_add_ref( fcontext * ctx) { ++ctx->use_count; } - friend void intrusive_ptr_release( base_context * ctx) { + friend void intrusive_ptr_release( fcontext * ctx) { BOOST_ASSERT( nullptr != ctx); if ( 0 == --ctx->use_count) { - ctx->deallocate(); + ctx->~fcontext(); } } }; template< typename Fn, typename StackAlloc > - class side_context : public base_context { + class worker_fcontext : public fcontext { private: StackAlloc salloc_; Fn fn_; + static void destroy( worker_fcontext * p) { + StackAlloc salloc( p->salloc_); + stack_context sctx( p->sctx); + p->~worker_fcontext(); + salloc.deallocate( sctx); + } + public: - explicit side_context( stack_context sctx, StackAlloc const& salloc, fcontext_t fctx, Fn && fn) noexcept : - base_context( fctx, sctx), + explicit worker_fcontext( stack_context sctx, StackAlloc const& salloc, fcontext_t fctx, Fn && fn) noexcept : + fcontext( fctx, sctx), salloc_( salloc), fn_( std::forward< Fn >( fn) ) { } void deallocate() override final { - salloc_.deallocate( sctx); - } - - void run() noexcept override final { - try { - fn_(); - } catch (...) { - std::terminate(); - } - } - }; - - struct main_context : public base_context { - void deallocate() override final { + destroy( this); } void run() noexcept override final { + fn_(); } }; static void entry_func( intptr_t p) noexcept { BOOST_ASSERT( 0 != p); - void * vp( reinterpret_cast< void * >( p) ); - BOOST_ASSERT( nullptr != vp); - - base_context * bp( static_cast< base_context * >( vp) ); + fcontext * bp( reinterpret_cast< fcontext * >( p) ); BOOST_ASSERT( nullptr != bp); bp->run(); } - typedef boost::intrusive_ptr< base_context > ptr_t; + typedef boost::intrusive_ptr< fcontext > ptr_t; - static thread_local ptr_t current_ctx_; + thread_local static fcontext main_ctx_; + thread_local static ptr_t current_ctx_; - boost::intrusive_ptr< base_context > ptr_; + boost::intrusive_ptr< fcontext > ptr_; #if defined(BOOST_USE_SEGMENTED_STACKS) - bool use_segmented_ = false; + bool use_segmented_ = false; #endif - static ptr_t create_main_context() { - static thread_local main_context mctx; // thread_local required? - return ptr_t( & mctx); - } - template< typename StackAlloc, typename Fn > - static ptr_t create_context( StackAlloc salloc, Fn && fn) { - typedef side_context< Fn, StackAlloc > func_t; + static fcontext * create_context( StackAlloc salloc, Fn && fn) { + typedef worker_fcontext< Fn, StackAlloc > func_t; stack_context sctx( salloc.allocate() ); // reserve space for control structure @@ -164,12 +157,12 @@ private: fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func); BOOST_ASSERT( nullptr != fctx); // placment new for control structure on fast-context stack - return ptr_t( new ( sp) func_t( sctx, salloc, fctx, std::forward< Fn >( fn) ) ); + return new ( sp) func_t( sctx, salloc, fctx, std::forward< Fn >( fn) ); } template< typename StackAlloc, typename Fn > - static ptr_t create_context( preallocated palloc, StackAlloc salloc, Fn && fn) { - typedef side_context< Fn, StackAlloc > func_t; + static fcontext * create_context( preallocated palloc, StackAlloc salloc, Fn && fn) { + typedef worker_fcontext< Fn, StackAlloc > func_t; // reserve space for control structure std::size_t size = palloc.size - sizeof( func_t); @@ -178,22 +171,36 @@ private: fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func); BOOST_ASSERT( nullptr != fctx); // placment new for control structure on fast-context stack - return ptr_t( new ( sp) func_t( palloc.sctx, salloc, fctx, std::forward< Fn >( fn) ) ); + return new ( sp) func_t( palloc.sctx, salloc, fctx, std::forward< Fn >( fn) ); } template< typename StackAlloc, typename Fn, typename ... Args > - static ptr_t create_side_context( StackAlloc salloc, - detail::fn_rref< Fn > fn, - detail::arg_rref< Args > ... args) { - return create_context( salloc, [=] () mutable { fn( args ...); }); + static fcontext * create_worker_fcontext( StackAlloc salloc, + detail::fn_rref< Fn > fn, + detail::arg_rref< Args > ... args) { + return create_context( salloc, + [=] () mutable { + try { + fn( args ...); + } catch (...) { + std::terminate(); + } + }); } template< typename StackAlloc, typename Fn, typename ... Args > - static ptr_t create_side_context( preallocated palloc, - StackAlloc salloc, - detail::fn_rref< Fn > fn, - detail::arg_rref< Args > ... args) { - return create_context( palloc, salloc, [=] () mutable { fn( args ...); }); + static fcontext * create_worker_fcontext( preallocated palloc, + StackAlloc salloc, + detail::fn_rref< Fn > fn, + detail::arg_rref< Args > ... args) { + return create_context( palloc, salloc, + [=] () mutable { + try { + fn( args ...); + } catch (...) { + std::terminate(); + } + }); } execution_context() : @@ -208,38 +215,38 @@ public: #if defined(BOOST_USE_SEGMENTED_STACKS) template< typename Fn, typename ... Args > explicit execution_context( segmented salloc, Fn && fn, Args && ... args) : - ptr_( create_side_context( salloc, - detail::fn_rref< Fn >( std::forward< Fn >( fn) ), - detail::arg_rref< Args >( std::forward< Args >( args) ) ... ) ), + ptr_( create_worker_fcontext( salloc, + detail::fn_rref< Fn >( std::forward< Fn >( fn) ), + detail::arg_rref< Args >( std::forward< Args >( args) ) ... ) ), use_segmented_( true) { } template< typename Fn, typename ... Args > explicit execution_context( preallocated palloc, segmented salloc, Fn && fn, Args && ... args) : - ptr_( create_side_context( palloc, salloc, - detail::fn_rref< Fn >( std::forward< Fn >( fn) ), - detail::arg_rref< Args >( std::forward< Args >( args) ) ... ) ), + ptr_( create_worker_fcontext( palloc, salloc, + detail::fn_rref< Fn >( std::forward< Fn >( fn) ), + detail::arg_rref< Args >( std::forward< Args >( args) ) ... ) ), use_segmented_( true) { } #endif template< typename StackAlloc, typename Fn, typename ... Args > explicit execution_context( StackAlloc salloc, Fn && fn, Args && ... args) : - ptr_( create_side_context( salloc, - detail::fn_rref< Fn >( std::forward< Fn >( fn) ), - detail::arg_rref< Args >( std::forward< Args >( args) ) ... ) ) { + ptr_( create_worker_fcontext( salloc, + detail::fn_rref< Fn >( std::forward< Fn >( fn) ), + detail::arg_rref< Args >( std::forward< Args >( args) ) ... ) ) { } template< typename StackAlloc, typename Fn, typename ... Args > explicit execution_context( preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) : - ptr_( create_side_context( palloc, salloc, - detail::fn_rref< Fn >( std::forward< Fn >( fn) ), - detail::arg_rref< Args >( std::forward< Args >( args) ) ... ) ) { + ptr_( create_worker_fcontext( palloc, salloc, + detail::fn_rref< Fn >( std::forward< Fn >( fn) ), + detail::arg_rref< Args >( std::forward< Args >( args) ) ... ) ) { } void jump_to( bool preserve_fpu = false) noexcept { BOOST_ASSERT( * this); - ptr_t tmp( current_ctx_); + fcontext * tmp( current_ctx_.get() ); current_ctx_ = ptr_; #if defined(BOOST_USE_SEGMENTED_STACKS) if ( use_segmented_) { diff --git a/src/execution_context.cpp b/src/execution_context.cpp index 19bbe79..1f656b2 100644 --- a/src/execution_context.cpp +++ b/src/execution_context.cpp @@ -17,9 +17,13 @@ namespace boost { namespace context { +thread_local +execution_context::fcontext +execution_context::main_ctx_; + thread_local execution_context::ptr_t -execution_context::current_ctx_ = execution_context::create_main_context(); +execution_context::current_ctx_ = & execution_context::main_ctx_; }}