diff --git a/include/boost/fiber/context.hpp b/include/boost/fiber/context.hpp index d8b812d7..76e58add 100644 --- a/include/boost/fiber/context.hpp +++ b/include/boost/fiber/context.hpp @@ -207,6 +207,35 @@ private: detail::spinlock splk_{}; fiber_properties * properties_{ nullptr }; +#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) + template< typename Fn, typename Tpl > + std::function< void( void*) > create_( Fn && fn__, Tpl && tpl__) { + return std::bind( + [this]( typename std::decay< Fn >::type & fn_, typename std::decay< Tpl >::type & tpl_, + boost::context::execution_context ctx, void * vp) mutable noexcept { + try { + data_t * dp = static_cast< data_t * >( vp); + if ( nullptr != dp->lk) { + dp->lk->unlock(); + } else if ( nullptr != dp->ctx) { + active_->set_ready_( dp->ctx); + } + auto fn = std::move( fn_); + auto tpl = std::move( tpl_); + boost::context::detail::apply( fn, tpl); + } catch ( fiber_interrupted const&) { + } + // terminate context + terminate(); + BOOST_ASSERT_MSG( false, "fiber already terminated"); + }, + std::forward< Fn >( fn__), + std::forward< Tpl >( tpl__), + boost::context::execution_context::current(), + std::placeholders::_1); + } +#endif + public: class id { private: @@ -280,6 +309,10 @@ public: Fn && fn, Args && ... args) : use_count_{ 1 }, // fiber instance or scheduler owner flags_{ flag_worker_context }, +#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) + ctx_{ std::allocator_arg, palloc, salloc, + create_( std::forward< Fn >( fn), std::make_tuple( std::forward< Args >( args) ... ) ) } +#else ctx_{ std::allocator_arg, palloc, salloc, // mutable: generated operator() is not const -> enables std::move( fn) // std::make_tuple: stores decayed copies of its args, implicitly unwraps std::reference_wrapper @@ -300,8 +333,9 @@ public: // terminate context terminate(); BOOST_ASSERT_MSG( false, "fiber already terminated"); - }} { - } + }} +#endif + {} virtual ~context(); @@ -451,7 +485,7 @@ struct context_initializer { }; template< typename StackAlloc, typename Fn, typename ... Args > -static auto make_worker_context( StackAlloc salloc, Fn && fn, Args && ... args) { +static intrusive_ptr< context > make_worker_context( StackAlloc salloc, Fn && fn, Args && ... args) { boost::context::stack_context sctx = salloc.allocate(); #if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN) // reserve space for control structure diff --git a/include/boost/fiber/operations.hpp b/include/boost/fiber/operations.hpp index e455b022..46c6a114 100644 --- a/include/boost/fiber/operations.hpp +++ b/include/boost/fiber/operations.hpp @@ -84,8 +84,8 @@ template< typename SchedAlgo, typename ... Args > void use_scheduling_algorithm( Args && ... args) noexcept { boost::fibers::context::active()->get_scheduler() ->set_sched_algo( - std::make_unique< SchedAlgo >( - std::forward< Args >( args) ... ) ); + std::unique_ptr< SchedAlgo >( + new SchedAlgo( std::forward< Args >( args) ... ) ) ); } }} diff --git a/src/context.cpp b/src/context.cpp index 3ea51323..3d5ef844 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -25,7 +25,7 @@ thread_local context * context::active_; -static auto make_dispatcher_context( scheduler * sched) { +static intrusive_ptr< context > make_dispatcher_context( scheduler * sched) { BOOST_ASSERT( nullptr != sched); default_stack salloc; // use default satck-size boost::context::stack_context sctx = salloc.allocate();