?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/context.zip
???????
PK ��!\̒e� pooled_fixedsize_stack.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_POOLED_pooled_fixedsize_H #define BOOST_CONTEXT_POOLED_pooled_fixedsize_H #include <atomic> #include <cstddef> #include <cstdlib> #include <new> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/intrusive_ptr.hpp> #include <boost/pool/pool.hpp> #include <boost/context/detail/config.hpp> #include <boost/context/stack_context.hpp> #include <boost/context/stack_traits.hpp> #if defined(BOOST_CONTEXT_USE_MAP_STACK) extern "C" { #include <sys/mman.h> #include <stdlib.h> } #endif #if defined(BOOST_USE_VALGRIND) #include <valgrind/valgrind.h> #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { #if defined(BOOST_CONTEXT_USE_MAP_STACK) namespace detail { template< typename traitsT > struct map_stack_allocator { typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; static char * malloc( const size_type bytes) { void * block; if ( ::posix_memalign( &block, traitsT::page_size(), bytes) != 0) { return 0; } if ( mmap( block, bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_STACK, -1, 0) == MAP_FAILED) { std::free( block); return 0; } return reinterpret_cast< char * >( block); } static void free( char * const block) { std::free( block); } }; } #endif template< typename traitsT > class basic_pooled_fixedsize_stack { private: class storage { private: std::atomic< std::size_t > use_count_; std::size_t stack_size_; #if defined(BOOST_CONTEXT_USE_MAP_STACK) boost::pool< detail::map_stack_allocator< traitsT > > storage_; #else boost::pool< boost::default_user_allocator_malloc_free > storage_; #endif public: storage( std::size_t stack_size, std::size_t next_size, std::size_t max_size) : use_count_( 0), stack_size_( stack_size), storage_( stack_size, next_size, max_size) { BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size_) ); } stack_context allocate() { void * vp = storage_.malloc(); if ( ! vp) { throw std::bad_alloc(); } stack_context sctx; sctx.size = stack_size_; sctx.sp = static_cast< char * >( vp) + sctx.size; #if defined(BOOST_USE_VALGRIND) sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp); #endif return sctx; } void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT( sctx.sp); BOOST_ASSERT( traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size) ); #if defined(BOOST_USE_VALGRIND) VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id); #endif void * vp = static_cast< char * >( sctx.sp) - sctx.size; storage_.free( vp); } friend void intrusive_ptr_add_ref( storage * s) noexcept { ++s->use_count_; } friend void intrusive_ptr_release( storage * s) noexcept { if ( 0 == --s->use_count_) { delete s; } } }; intrusive_ptr< storage > storage_; public: typedef traitsT traits_type; basic_pooled_fixedsize_stack( std::size_t stack_size = traits_type::default_size(), std::size_t next_size = 32, std::size_t max_size = 0) BOOST_NOEXCEPT_OR_NOTHROW : storage_( new storage( stack_size, next_size, max_size) ) { } stack_context allocate() { return storage_->allocate(); } void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW { storage_->deallocate( sctx); } }; typedef basic_pooled_fixedsize_stack< stack_traits > pooled_fixedsize_stack; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_POOLED_pooled_fixedsize_H PK ��!\���� � continuation.hppnu �[��� // Copyright Oliver Kowalke 2017. // 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) #if defined(BOOST_USE_UCONTEXT) #include <boost/context/continuation_ucontext.hpp> #elif defined(BOOST_USE_WINFIB) #include <boost/context/continuation_winfib.hpp> #else #include <boost/context/continuation_fcontext.hpp> #endif PK ��!\=�^� � fiber.hppnu �[��� // Copyright Oliver Kowalke 2017. // 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) #if defined(BOOST_USE_UCONTEXT) #include <boost/context/fiber_ucontext.hpp> #elif defined(BOOST_USE_WINFIB) #include <boost/context/fiber_winfib.hpp> #else #include <boost/context/fiber_fcontext.hpp> #endif PK ��!\���]5. 5. continuation_fcontext.hppnu �[��� // Copyright Oliver Kowalke 2017. // 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_CONTEXT_CONTINUATION_H #define BOOST_CONTEXT_CONTINUATION_H #include <boost/context/detail/config.hpp> #include <algorithm> #include <cstddef> #include <cstdint> #include <cstdlib> #include <exception> #include <functional> #include <memory> #include <ostream> #include <tuple> #include <utility> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/intrusive_ptr.hpp> #if defined(BOOST_NO_CXX14_STD_EXCHANGE) #include <boost/context/detail/exchange.hpp> #endif #if defined(BOOST_NO_CXX17_STD_INVOKE) #include <boost/context/detail/invoke.hpp> #endif #include <boost/context/detail/disable_overload.hpp> #include <boost/context/detail/exception.hpp> #include <boost/context/detail/fcontext.hpp> #include <boost/context/detail/tuple.hpp> #include <boost/context/fixedsize_stack.hpp> #include <boost/context/flags.hpp> #include <boost/context/preallocated.hpp> #include <boost/context/segmented_stack.hpp> #include <boost/context/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4702) #endif namespace boost { namespace context { namespace detail { inline transfer_t context_unwind( transfer_t t) { throw forced_unwind( t.fctx); return { nullptr, nullptr }; } template< typename Rec > transfer_t context_exit( transfer_t t) noexcept { Rec * rec = static_cast< Rec * >( t.data); // destroy context stack rec->deallocate(); return { nullptr, nullptr }; } template< typename Rec > void context_entry( transfer_t t) noexcept { // transfer control structure to the context-stack Rec * rec = static_cast< Rec * >( t.data); BOOST_ASSERT( nullptr != t.fctx); BOOST_ASSERT( nullptr != rec); try { // jump back to `create_context()` t = jump_fcontext( t.fctx, nullptr); // start executing t.fctx = rec->run( t.fctx); } catch ( forced_unwind const& ex) { t = { ex.fctx, nullptr }; #ifndef BOOST_ASSERT_IS_VOID const_cast< forced_unwind & >( ex).caught = true; #endif } BOOST_ASSERT( nullptr != t.fctx); // destroy context-stack of `this`context on next context ontop_fcontext( t.fctx, rec, context_exit< Rec >); BOOST_ASSERT_MSG( false, "context already terminated"); } template< typename Ctx, typename Fn > transfer_t context_ontop( transfer_t t) { auto p = static_cast< std::tuple< Fn > * >( t.data); BOOST_ASSERT( nullptr != p); typename std::decay< Fn >::type fn = std::get< 0 >( * p); t.data = nullptr; Ctx c{ t.fctx }; // execute function, pass continuation via reference c = fn( std::move( c) ); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return { exchange( c.fctx_, nullptr), nullptr }; #else return { std::exchange( c.fctx_, nullptr), nullptr }; #endif } template< typename Ctx, typename StackAlloc, typename Fn > class record { private: stack_context sctx_; typename std::decay< StackAlloc >::type salloc_; typename std::decay< Fn >::type fn_; static void destroy( record * p) noexcept { typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_); stack_context sctx = p->sctx_; // deallocate record p->~record(); // destroy stack with stack allocator salloc.deallocate( sctx); } public: record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept : sctx_( sctx), salloc_( std::forward< StackAlloc >( salloc)), fn_( std::forward< Fn >( fn) ) { } record( record const&) = delete; record & operator=( record const&) = delete; void deallocate() noexcept { destroy( this); } fcontext_t run( fcontext_t fctx) { Ctx c{ fctx }; // invoke context-function #if defined(BOOST_NO_CXX17_STD_INVOKE) c = boost::context::detail::invoke( fn_, std::move( c) ); #else c = std::invoke( fn_, std::move( c) ); #endif #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.fctx_, nullptr); #else return std::exchange( c.fctx_, nullptr); #endif } }; template< typename Record, typename StackAlloc, typename Fn > fcontext_t create_context1( StackAlloc && salloc, Fn && fn) { auto sctx = salloc.allocate(); // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( Record) ) ) & ~static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack Record * record = new ( storage) Record{ sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // 64byte gab between control structure and stack top // should be 16byte aligned void * stack_top = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) ); void * stack_bottom = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) ); // create fast-context const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom); const fcontext_t fctx = make_fcontext( stack_top, size, & context_entry< Record >); BOOST_ASSERT( nullptr != fctx); // transfer control structure to context-stack return jump_fcontext( fctx, record).fctx; } template< typename Record, typename StackAlloc, typename Fn > fcontext_t create_context2( preallocated palloc, StackAlloc && salloc, Fn && fn) { // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( Record) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context-stack Record * record = new ( storage) Record{ palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // 64byte gab between control structure and stack top void * stack_top = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) ); void * stack_bottom = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) ); // create fast-context const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom); const fcontext_t fctx = make_fcontext( stack_top, size, & context_entry< Record >); BOOST_ASSERT( nullptr != fctx); // transfer control structure to context-stack return jump_fcontext( fctx, record).fctx; } } class continuation { private: template< typename Ctx, typename StackAlloc, typename Fn > friend class detail::record; template< typename Ctx, typename Fn > friend detail::transfer_t detail::context_ontop( detail::transfer_t); template< typename StackAlloc, typename Fn > friend continuation callcc( std::allocator_arg_t, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend continuation callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&); detail::fcontext_t fctx_{ nullptr }; continuation( detail::fcontext_t fctx) noexcept : fctx_{ fctx } { } public: continuation() noexcept = default; ~continuation() { if ( BOOST_UNLIKELY( nullptr != fctx_) ) { detail::ontop_fcontext( #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::exchange( fctx_, nullptr), #else std::exchange( fctx_, nullptr), #endif nullptr, detail::context_unwind); } } continuation( continuation && other) noexcept { swap( other); } continuation & operator=( continuation && other) noexcept { if ( BOOST_LIKELY( this != & other) ) { continuation tmp = std::move( other); swap( tmp); } return * this; } continuation( continuation const& other) noexcept = delete; continuation & operator=( continuation const& other) noexcept = delete; continuation resume() & { return std::move( * this).resume(); } continuation resume() && { BOOST_ASSERT( nullptr != fctx_); return { detail::jump_fcontext( #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::exchange( fctx_, nullptr), #else std::exchange( fctx_, nullptr), #endif nullptr).fctx }; } template< typename Fn > continuation resume_with( Fn && fn) & { return std::move( * this).resume_with( std::forward< Fn >( fn) ); } template< typename Fn > continuation resume_with( Fn && fn) && { BOOST_ASSERT( nullptr != fctx_); auto p = std::make_tuple( std::forward< Fn >( fn) ); return { detail::ontop_fcontext( #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::exchange( fctx_, nullptr), #else std::exchange( fctx_, nullptr), #endif & p, detail::context_ontop< continuation, Fn >).fctx }; } explicit operator bool() const noexcept { return nullptr != fctx_; } bool operator!() const noexcept { return nullptr == fctx_; } bool operator<( continuation const& other) const noexcept { return fctx_ < other.fctx_; } template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) { if ( nullptr != other.fctx_) { return os << other.fctx_; } else { return os << "{not-a-context}"; } } void swap( continuation & other) noexcept { std::swap( fctx_, other.fctx_); } }; template< typename Fn, typename = detail::disable_overload< continuation, Fn > > continuation callcc( Fn && fn) { return callcc( std::allocator_arg, fixedsize_stack(), std::forward< Fn >( fn) ); } template< typename StackAlloc, typename Fn > continuation callcc( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) { using Record = detail::record< continuation, StackAlloc, Fn >; return continuation{ detail::create_context1< Record >( std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume(); } template< typename StackAlloc, typename Fn > continuation callcc( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) { using Record = detail::record< continuation, StackAlloc, Fn >; return continuation{ detail::create_context2< Record >( palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume(); } #if defined(BOOST_USE_SEGMENTED_STACKS) template< typename Fn > continuation callcc( std::allocator_arg_t, segmented_stack, Fn &&); template< typename StackAlloc, typename Fn > continuation callcc( std::allocator_arg_t, preallocated, segmented_stack, Fn &&); #endif inline void swap( continuation & l, continuation & r) noexcept { l.swap( r); } }} #if defined(BOOST_MSVC) # pragma warning(pop) #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_CONTINUATION_H PK ��!\��V8; 8; fiber_winfib.hppnu �[��� // Copyright Oliver Kowalke 2017. // 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_CONTEXT_FIBER_H #define BOOST_CONTEXT_FIBER_H #include <windows.h> #include <boost/context/detail/config.hpp> #include <algorithm> #include <cstddef> #include <cstdint> #include <cstdlib> #include <cstring> #include <functional> #include <memory> #include <ostream> #include <system_error> #include <tuple> #include <utility> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/context/detail/disable_overload.hpp> #if defined(BOOST_NO_CXX14_STD_EXCHANGE) #include <boost/context/detail/exchange.hpp> #endif #if defined(BOOST_NO_CXX17_STD_INVOKE) #include <boost/context/detail/invoke.hpp> #endif #include <boost/context/fixedsize_stack.hpp> #include <boost/context/flags.hpp> #include <boost/context/preallocated.hpp> #include <boost/context/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4702) #endif namespace boost { namespace context { namespace detail { // tampoline function // entered if the execution context // is resumed for the first time template< typename Record > static VOID WINAPI fiber_entry_func( LPVOID data) noexcept { Record * record = static_cast< Record * >( data); BOOST_ASSERT( nullptr != record); // start execution of toplevel context-function record->run(); } struct BOOST_CONTEXT_DECL fiber_activation_record { LPVOID fiber{ nullptr }; stack_context sctx{}; bool main_ctx{ true }; fiber_activation_record * from{ nullptr }; std::function< fiber_activation_record*(fiber_activation_record*&) > ontop{}; bool terminated{ false }; bool force_unwind{ false }; static fiber_activation_record *& current() noexcept; // used for toplevel-context // (e.g. main context, thread-entry context) fiber_activation_record() noexcept { #if ( _WIN32_WINNT > 0x0600) if ( ::IsThreadAFiber() ) { fiber = ::GetCurrentFiber(); } else { fiber = ::ConvertThreadToFiber( nullptr); } #else fiber = ::ConvertThreadToFiber( nullptr); if ( BOOST_UNLIKELY( nullptr == fiber) ) { BOOST_ASSERT( ERROR_ALREADY_FIBER == ::GetLastError()); fiber = ::GetCurrentFiber(); BOOST_ASSERT( nullptr != fiber); BOOST_ASSERT( reinterpret_cast< LPVOID >( 0x1E00) != fiber); } #endif } fiber_activation_record( stack_context sctx_) noexcept : sctx{ sctx_ }, main_ctx{ false } { } virtual ~fiber_activation_record() { if ( BOOST_UNLIKELY( main_ctx) ) { ::ConvertFiberToThread(); } else { ::DeleteFiber( fiber); } } fiber_activation_record( fiber_activation_record const&) = delete; fiber_activation_record & operator=( fiber_activation_record const&) = delete; bool is_main_context() const noexcept { return main_ctx; } fiber_activation_record * resume() { from = current(); // store `this` in static, thread local pointer // `this` will become the active (running) context current() = this; // context switch from parent context to `this`-context // context switch ::SwitchToFiber( fiber); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return detail::exchange( current()->from, nullptr); #else return std::exchange( current()->from, nullptr); #endif } template< typename Ctx, typename Fn > fiber_activation_record * resume_with( Fn && fn) { from = current(); // store `this` in static, thread local pointer // `this` will become the active (running) context // returned by fiber::current() current() = this; #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) current()->ontop = std::bind( [](typename std::decay< Fn >::type & fn, fiber_activation_record *& ptr){ Ctx c{ ptr }; c = fn( std::move( c) ); if ( ! c) { ptr = nullptr; } #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.ptr_, nullptr); #else return std::exchange( c.ptr_, nullptr); #endif }, std::forward< Fn >( fn), std::placeholders::_1); #else current()->ontop = [fn=std::forward<Fn>(fn)](fiber_activation_record *& ptr){ Ctx c{ ptr }; c = fn( std::move( c) ); if ( ! c) { ptr = nullptr; } #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.ptr_, nullptr); #else return std::exchange( c.ptr_, nullptr); #endif }; #endif // context switch ::SwitchToFiber( fiber); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return detail::exchange( current()->from, nullptr); #else return std::exchange( current()->from, nullptr); #endif } virtual void deallocate() noexcept { } }; struct BOOST_CONTEXT_DECL fiber_activation_record_initializer { fiber_activation_record_initializer() noexcept; ~fiber_activation_record_initializer(); }; struct forced_unwind { fiber_activation_record * from{ nullptr }; #ifndef BOOST_ASSERT_IS_VOID bool caught{ false }; #endif explicit forced_unwind( fiber_activation_record * from_) : from{ from_ } { } #ifndef BOOST_ASSERT_IS_VOID ~forced_unwind() { BOOST_ASSERT( caught); } #endif }; template< typename Ctx, typename StackAlloc, typename Fn > class fiber_capture_record : public fiber_activation_record { private: typename std::decay< StackAlloc >::type salloc_; typename std::decay< Fn >::type fn_; static void destroy( fiber_capture_record * p) noexcept { typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_); stack_context sctx = p->sctx; // deallocate activation record p->~fiber_capture_record(); // destroy stack with stack allocator salloc.deallocate( sctx); } public: fiber_capture_record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept : fiber_activation_record( sctx), salloc_( std::forward< StackAlloc >( salloc)), fn_( std::forward< Fn >( fn) ) { } void deallocate() noexcept override final { BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) ); destroy( this); } void run() { Ctx c{ from }; try { // invoke context-function #if defined(BOOST_NO_CXX17_STD_INVOKE) c = boost::context::detail::invoke( fn_, std::move( c) ); #else c = std::invoke( fn_, std::move( c) ); #endif } catch ( forced_unwind const& ex) { c = Ctx{ ex.from }; #ifndef BOOST_ASSERT_IS_VOID const_cast< forced_unwind & >( ex).caught = true; #endif } // this context has finished its task from = nullptr; ontop = nullptr; terminated = true; force_unwind = false; std::move( c).resume(); BOOST_ASSERT_MSG( false, "fiber already terminated"); } }; template< typename Ctx, typename StackAlloc, typename Fn > static fiber_activation_record * create_fiber1( StackAlloc && salloc, Fn && fn) { typedef fiber_capture_record< Ctx, StackAlloc, Fn > capture_t; auto sctx = salloc.allocate(); BOOST_ASSERT( ( sizeof( capture_t) ) < sctx.size); // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack capture_t * record = new ( storage) capture_t{ sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // create user-context record->fiber = ::CreateFiber( sctx.size, & detail::fiber_entry_func< capture_t >, record); return record; } template< typename Ctx, typename StackAlloc, typename Fn > static fiber_activation_record * create_fiber2( preallocated palloc, StackAlloc && salloc, Fn && fn) { typedef fiber_capture_record< Ctx, StackAlloc, Fn > capture_t; BOOST_ASSERT( ( sizeof( capture_t) ) < palloc.size); // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack capture_t * record = new ( storage) capture_t{ palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // create user-context record->fiber = ::CreateFiber( palloc.sctx.size, & detail::fiber_entry_func< capture_t >, record); return record; } } class BOOST_CONTEXT_DECL fiber { private: friend struct detail::fiber_activation_record; template< typename Ctx, typename StackAlloc, typename Fn > friend class detail::fiber_capture_record; template< typename Ctx, typename StackAlloc, typename Fn > friend detail::fiber_activation_record * detail::create_fiber1( StackAlloc &&, Fn &&); template< typename Ctx, typename StackAlloc, typename Fn > friend detail::fiber_activation_record * detail::create_fiber2( preallocated, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend fiber callcc( std::allocator_arg_t, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend fiber callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&); detail::fiber_activation_record * ptr_{ nullptr }; fiber( detail::fiber_activation_record * ptr) noexcept : ptr_{ ptr } { } public: fiber() = default; template< typename Fn, typename = detail::disable_overload< fiber, Fn > > fiber( Fn && fn) : fiber{ std::allocator_arg, fixedsize_stack(), std::forward< Fn >( fn) } { } template< typename StackAlloc, typename Fn > fiber( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) : ptr_{ detail::create_fiber1< fiber >( std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } {; } template< typename StackAlloc, typename Fn > fiber( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) : ptr_{ detail::create_fiber2< fiber >( palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } { } ~fiber() { if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) { if ( BOOST_LIKELY( ! ptr_->terminated) ) { ptr_->force_unwind = true; ptr_->resume(); BOOST_ASSERT( ptr_->terminated); } ptr_->deallocate(); } } fiber( fiber const&) = delete; fiber & operator=( fiber const&) = delete; fiber( fiber && other) noexcept { swap( other); } fiber & operator=( fiber && other) noexcept { if ( BOOST_LIKELY( this != & other) ) { fiber tmp = std::move( other); swap( tmp); } return * this; } fiber resume() && { BOOST_ASSERT( nullptr != ptr_); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::fiber_activation_record * ptr = detail::exchange( ptr_, nullptr)->resume(); #else detail::fiber_activation_record * ptr = std::exchange( ptr_, nullptr)->resume(); #endif if ( BOOST_UNLIKELY( detail::fiber_activation_record::current()->force_unwind) ) { throw detail::forced_unwind{ ptr}; } else if ( BOOST_UNLIKELY( nullptr != detail::fiber_activation_record::current()->ontop) ) { ptr = detail::fiber_activation_record::current()->ontop( ptr); detail::fiber_activation_record::current()->ontop = nullptr; } return { ptr }; } template< typename Fn > fiber resume_with( Fn && fn) && { BOOST_ASSERT( nullptr != ptr_); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::fiber_activation_record * ptr = detail::exchange( ptr_, nullptr)->resume_with< fiber >( std::forward< Fn >( fn) ); #else detail::fiber_activation_record * ptr = std::exchange( ptr_, nullptr)->resume_with< fiber >( std::forward< Fn >( fn) ); #endif if ( BOOST_UNLIKELY( detail::fiber_activation_record::current()->force_unwind) ) { throw detail::forced_unwind{ ptr}; } else if ( BOOST_UNLIKELY( nullptr != detail::fiber_activation_record::current()->ontop) ) { ptr = detail::fiber_activation_record::current()->ontop( ptr); detail::fiber_activation_record::current()->ontop = nullptr; } return { ptr }; } explicit operator bool() const noexcept { return nullptr != ptr_ && ! ptr_->terminated; } bool operator!() const noexcept { return nullptr == ptr_ || ptr_->terminated; } bool operator<( fiber const& other) const noexcept { return ptr_ < other.ptr_; } #if !defined(BOOST_EMBTC) template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) { if ( nullptr != other.ptr_) { return os << other.ptr_; } else { return os << "{not-a-context}"; } } #else template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other); #endif void swap( fiber & other) noexcept { std::swap( ptr_, other.ptr_); } }; #if defined(BOOST_EMBTC) template< typename charT, class traitsT > inline std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) { if ( nullptr != other.ptr_) { return os << other.ptr_; } else { return os << "{not-a-context}"; } } #endif inline void swap( fiber & l, fiber & r) noexcept { l.swap( r); } typedef fiber fiber_context; }} #if defined(BOOST_MSVC) # pragma warning(pop) #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_FIBER_H PK ��!\f A�- �- fiber_fcontext.hppnu �[��� // Copyright Oliver Kowalke 2017. // 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_CONTEXT_FIBER_H #define BOOST_CONTEXT_FIBER_H #include <boost/context/detail/config.hpp> #include <algorithm> #include <cstddef> #include <cstdint> #include <cstdlib> #include <exception> #include <functional> #include <memory> #include <ostream> #include <tuple> #include <utility> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/intrusive_ptr.hpp> #if defined(BOOST_NO_CXX14_STD_EXCHANGE) #include <boost/context/detail/exchange.hpp> #endif #if defined(BOOST_NO_CXX17_STD_INVOKE) #include <boost/context/detail/invoke.hpp> #endif #include <boost/context/detail/disable_overload.hpp> #include <boost/context/detail/exception.hpp> #include <boost/context/detail/fcontext.hpp> #include <boost/context/detail/tuple.hpp> #include <boost/context/fixedsize_stack.hpp> #include <boost/context/flags.hpp> #include <boost/context/preallocated.hpp> #include <boost/context/segmented_stack.hpp> #include <boost/context/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4702) #endif namespace boost { namespace context { namespace detail { inline transfer_t fiber_unwind( transfer_t t) { throw forced_unwind( t.fctx); return { nullptr, nullptr }; } template< typename Rec > transfer_t fiber_exit( transfer_t t) noexcept { Rec * rec = static_cast< Rec * >( t.data); // destroy context stack rec->deallocate(); return { nullptr, nullptr }; } template< typename Rec > void fiber_entry( transfer_t t) noexcept { // transfer control structure to the context-stack Rec * rec = static_cast< Rec * >( t.data); BOOST_ASSERT( nullptr != t.fctx); BOOST_ASSERT( nullptr != rec); try { // jump back to `create_context()` t = jump_fcontext( t.fctx, nullptr); // start executing t.fctx = rec->run( t.fctx); } catch ( forced_unwind const& ex) { t = { ex.fctx, nullptr }; #ifndef BOOST_ASSERT_IS_VOID const_cast< forced_unwind & >( ex).caught = true; #endif } BOOST_ASSERT( nullptr != t.fctx); // destroy context-stack of `this`context on next context ontop_fcontext( t.fctx, rec, fiber_exit< Rec >); BOOST_ASSERT_MSG( false, "context already terminated"); } template< typename Ctx, typename Fn > transfer_t fiber_ontop( transfer_t t) { BOOST_ASSERT( nullptr != t.data); auto p = *static_cast< Fn * >( t.data); t.data = nullptr; // execute function, pass fiber via reference Ctx c = p( Ctx{ t.fctx } ); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return { exchange( c.fctx_, nullptr), nullptr }; #else return { std::exchange( c.fctx_, nullptr), nullptr }; #endif } template< typename Ctx, typename StackAlloc, typename Fn > class fiber_record { private: stack_context sctx_; typename std::decay< StackAlloc >::type salloc_; typename std::decay< Fn >::type fn_; static void destroy( fiber_record * p) noexcept { typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_); stack_context sctx = p->sctx_; // deallocate fiber_record p->~fiber_record(); // destroy stack with stack allocator salloc.deallocate( sctx); } public: fiber_record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept : sctx_( sctx), salloc_( std::forward< StackAlloc >( salloc)), fn_( std::forward< Fn >( fn) ) { } fiber_record( fiber_record const&) = delete; fiber_record & operator=( fiber_record const&) = delete; void deallocate() noexcept { destroy( this); } fcontext_t run( fcontext_t fctx) { // invoke context-function #if defined(BOOST_NO_CXX17_STD_INVOKE) Ctx c = boost::context::detail::invoke( fn_, Ctx{ fctx } ); #else Ctx c = std::invoke( fn_, Ctx{ fctx } ); #endif #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.fctx_, nullptr); #else return std::exchange( c.fctx_, nullptr); #endif } }; template< typename Record, typename StackAlloc, typename Fn > fcontext_t create_fiber1( StackAlloc && salloc, Fn && fn) { auto sctx = salloc.allocate(); // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( Record) ) ) & ~static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack Record * record = new ( storage) Record{ sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // 64byte gab between control structure and stack top // should be 16byte aligned void * stack_top = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) ); void * stack_bottom = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) ); // create fast-context const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom); const fcontext_t fctx = make_fcontext( stack_top, size, & fiber_entry< Record >); BOOST_ASSERT( nullptr != fctx); // transfer control structure to context-stack return jump_fcontext( fctx, record).fctx; } template< typename Record, typename StackAlloc, typename Fn > fcontext_t create_fiber2( preallocated palloc, StackAlloc && salloc, Fn && fn) { // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( Record) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context-stack Record * record = new ( storage) Record{ palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // 64byte gab between control structure and stack top void * stack_top = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( storage) - static_cast< uintptr_t >( 64) ); void * stack_bottom = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) ); // create fast-context const std::size_t size = reinterpret_cast< uintptr_t >( stack_top) - reinterpret_cast< uintptr_t >( stack_bottom); const fcontext_t fctx = make_fcontext( stack_top, size, & fiber_entry< Record >); BOOST_ASSERT( nullptr != fctx); // transfer control structure to context-stack return jump_fcontext( fctx, record).fctx; } } class fiber { private: template< typename Ctx, typename StackAlloc, typename Fn > friend class detail::fiber_record; template< typename Ctx, typename Fn > friend detail::transfer_t detail::fiber_ontop( detail::transfer_t); template< typename StackAlloc, typename Fn > friend fiber callcc( std::allocator_arg_t, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend fiber callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&); detail::fcontext_t fctx_{ nullptr }; fiber( detail::fcontext_t fctx) noexcept : fctx_{ fctx } { } public: fiber() noexcept = default; template< typename Fn, typename = detail::disable_overload< fiber, Fn > > fiber( Fn && fn) : fiber{ std::allocator_arg, fixedsize_stack(), std::forward< Fn >( fn) } { } template< typename StackAlloc, typename Fn > fiber( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) : fctx_{ detail::create_fiber1< detail::fiber_record< fiber, StackAlloc, Fn > >( std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } { } template< typename StackAlloc, typename Fn > fiber( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) : fctx_{ detail::create_fiber2< detail::fiber_record< fiber, StackAlloc, Fn > >( palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } { } #if defined(BOOST_USE_SEGMENTED_STACKS) template< typename Fn > fiber( std::allocator_arg_t, segmented_stack, Fn &&); template< typename StackAlloc, typename Fn > fiber( std::allocator_arg_t, preallocated, segmented_stack, Fn &&); #endif ~fiber() { if ( BOOST_UNLIKELY( nullptr != fctx_) ) { detail::ontop_fcontext( #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::exchange( fctx_, nullptr), #else std::exchange( fctx_, nullptr), #endif nullptr, detail::fiber_unwind); } } fiber( fiber && other) noexcept { swap( other); } fiber & operator=( fiber && other) noexcept { if ( BOOST_LIKELY( this != & other) ) { fiber tmp = std::move( other); swap( tmp); } return * this; } fiber( fiber const& other) noexcept = delete; fiber & operator=( fiber const& other) noexcept = delete; fiber resume() && { BOOST_ASSERT( nullptr != fctx_); return { detail::jump_fcontext( #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::exchange( fctx_, nullptr), #else std::exchange( fctx_, nullptr), #endif nullptr).fctx }; } template< typename Fn > fiber resume_with( Fn && fn) && { BOOST_ASSERT( nullptr != fctx_); auto p = std::forward< Fn >( fn); return { detail::ontop_fcontext( #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::exchange( fctx_, nullptr), #else std::exchange( fctx_, nullptr), #endif & p, detail::fiber_ontop< fiber, decltype(p) >).fctx }; } explicit operator bool() const noexcept { return nullptr != fctx_; } bool operator!() const noexcept { return nullptr == fctx_; } bool operator<( fiber const& other) const noexcept { return fctx_ < other.fctx_; } #if !defined(BOOST_EMBTC) template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) { if ( nullptr != other.fctx_) { return os << other.fctx_; } else { return os << "{not-a-context}"; } } #else template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other); #endif void swap( fiber & other) noexcept { std::swap( fctx_, other.fctx_); } }; #if defined(BOOST_EMBTC) template< typename charT, class traitsT > inline std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) { if ( nullptr != other.fctx_) { return os << other.fctx_; } else { return os << "{not-a-context}"; } } #endif inline void swap( fiber & l, fiber & r) noexcept { l.swap( r); } typedef fiber fiber_context; }} #if defined(BOOST_MSVC) # pragma warning(pop) #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_FIBER_H PK ��!\ό� � stack_traits.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_STACK_TRAITS_H #define BOOST_CONTEXT_STACK_TRAITS_H #include <cstddef> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { struct BOOST_CONTEXT_DECL stack_traits { static bool is_unbounded() BOOST_NOEXCEPT_OR_NOTHROW; static std::size_t page_size() BOOST_NOEXCEPT_OR_NOTHROW; static std::size_t default_size() BOOST_NOEXCEPT_OR_NOTHROW; static std::size_t minimum_size() BOOST_NOEXCEPT_OR_NOTHROW; static std::size_t maximum_size() BOOST_NOEXCEPT_OR_NOTHROW; }; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_STACK_TRAITS_H PK ��!\�#0�G �G fiber_ucontext.hppnu �[��� // Copyright Oliver Kowalke 2017. // 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_CONTEXT_FIBER_H #define BOOST_CONTEXT_FIBER_H #include <boost/predef.h> #if BOOST_OS_MACOS #define _XOPEN_SOURCE 600 #endif extern "C" { #include <ucontext.h> } #include <boost/context/detail/config.hpp> #include <algorithm> #include <cstddef> #include <cstdint> #include <cstdlib> #include <cstring> #include <functional> #include <memory> #include <ostream> #include <system_error> #include <tuple> #include <utility> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/context/detail/disable_overload.hpp> #if defined(BOOST_NO_CXX14_STD_EXCHANGE) #include <boost/context/detail/exchange.hpp> #endif #include <boost/context/detail/externc.hpp> #if defined(BOOST_NO_CXX17_STD_INVOKE) #include <boost/context/detail/invoke.hpp> #endif #include <boost/context/fixedsize_stack.hpp> #include <boost/context/flags.hpp> #include <boost/context/preallocated.hpp> #if defined(BOOST_USE_SEGMENTED_STACKS) #include <boost/context/segmented_stack.hpp> #endif #include <boost/context/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { // tampoline function // entered if the execution context // is resumed for the first time template< typename Record > static void fiber_entry_func( void * data) noexcept { Record * record = static_cast< Record * >( data); BOOST_ASSERT( nullptr != record); // start execution of toplevel context-function record->run(); } struct BOOST_CONTEXT_DECL fiber_activation_record { ucontext_t uctx{}; stack_context sctx{}; bool main_ctx{ true }; fiber_activation_record * from{ nullptr }; std::function< fiber_activation_record*(fiber_activation_record*&) > ontop{}; bool terminated{ false }; bool force_unwind{ false }; #if defined(BOOST_USE_ASAN) void * fake_stack{ nullptr }; void * stack_bottom{ nullptr }; std::size_t stack_size{ 0 }; #endif static fiber_activation_record *& current() noexcept; // used for toplevel-context // (e.g. main context, thread-entry context) fiber_activation_record() { if ( BOOST_UNLIKELY( 0 != ::getcontext( & uctx) ) ) { throw std::system_error( std::error_code( errno, std::system_category() ), "getcontext() failed"); } } fiber_activation_record( stack_context sctx_) noexcept : sctx( sctx_ ), main_ctx( false ) { } virtual ~fiber_activation_record() { } fiber_activation_record( fiber_activation_record const&) = delete; fiber_activation_record & operator=( fiber_activation_record const&) = delete; bool is_main_context() const noexcept { return main_ctx; } fiber_activation_record * resume() { from = current(); // store `this` in static, thread local pointer // `this` will become the active (running) context current() = this; #if defined(BOOST_USE_SEGMENTED_STACKS) // adjust segmented stack properties __splitstack_getcontext( from->sctx.segments_ctx); __splitstack_setcontext( sctx.segments_ctx); #endif #if defined(BOOST_USE_ASAN) if ( terminated) { __sanitizer_start_switch_fiber( nullptr, stack_bottom, stack_size); } else { __sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size); } #endif // context switch from parent context to `this`-context ::swapcontext( & from->uctx, & uctx); #if defined(BOOST_USE_ASAN) __sanitizer_finish_switch_fiber( current()->fake_stack, (const void **) & current()->from->stack_bottom, & current()->from->stack_size); #endif #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( current()->from, nullptr); #else return std::exchange( current()->from, nullptr); #endif } template< typename Ctx, typename Fn > fiber_activation_record * resume_with( Fn && fn) { from = current(); // store `this` in static, thread local pointer // `this` will become the active (running) context // returned by fiber::current() current() = this; #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) current()->ontop = std::bind( [](typename std::decay< Fn >::type & fn, fiber_activation_record *& ptr){ Ctx c{ ptr }; c = fn( std::move( c) ); if ( ! c) { ptr = nullptr; } #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.ptr_, nullptr); #else return std::exchange( c.ptr_, nullptr); #endif }, std::forward< Fn >( fn), std::placeholders::_1); #else current()->ontop = [fn=std::forward<Fn>(fn)](fiber_activation_record *& ptr){ Ctx c{ ptr }; c = fn( std::move( c) ); if ( ! c) { ptr = nullptr; } #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.ptr_, nullptr); #else return std::exchange( c.ptr_, nullptr); #endif }; #endif #if defined(BOOST_USE_SEGMENTED_STACKS) // adjust segmented stack properties __splitstack_getcontext( from->sctx.segments_ctx); __splitstack_setcontext( sctx.segments_ctx); #endif #if defined(BOOST_USE_ASAN) __sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size); #endif // context switch from parent context to `this`-context ::swapcontext( & from->uctx, & uctx); #if defined(BOOST_USE_ASAN) __sanitizer_finish_switch_fiber( current()->fake_stack, (const void **) & current()->from->stack_bottom, & current()->from->stack_size); #endif #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( current()->from, nullptr); #else return std::exchange( current()->from, nullptr); #endif } virtual void deallocate() noexcept { } }; struct BOOST_CONTEXT_DECL fiber_activation_record_initializer { fiber_activation_record_initializer() noexcept; ~fiber_activation_record_initializer(); }; struct forced_unwind { fiber_activation_record * from{ nullptr }; #ifndef BOOST_ASSERT_IS_VOID bool caught{ false }; #endif forced_unwind( fiber_activation_record * from_) noexcept : from{ from_ } { } #ifndef BOOST_ASSERT_IS_VOID ~forced_unwind() { BOOST_ASSERT( caught); } #endif }; template< typename Ctx, typename StackAlloc, typename Fn > class fiber_capture_record : public fiber_activation_record { private: typename std::decay< StackAlloc >::type salloc_; typename std::decay< Fn >::type fn_; static void destroy( fiber_capture_record * p) noexcept { typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_); stack_context sctx = p->sctx; // deallocate activation record p->~fiber_capture_record(); // destroy stack with stack allocator salloc.deallocate( sctx); } public: fiber_capture_record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept : fiber_activation_record{ sctx }, salloc_{ std::forward< StackAlloc >( salloc) }, fn_( std::forward< Fn >( fn) ) { } void deallocate() noexcept override final { BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) ); destroy( this); } void run() { #if defined(BOOST_USE_ASAN) __sanitizer_finish_switch_fiber( fake_stack, (const void **) & from->stack_bottom, & from->stack_size); #endif Ctx c{ from }; try { // invoke context-function #if defined(BOOST_NO_CXX17_STD_INVOKE) c = boost::context::detail::invoke( fn_, std::move( c) ); #else c = std::invoke( fn_, std::move( c) ); #endif } catch ( forced_unwind const& ex) { c = Ctx{ ex.from }; #ifndef BOOST_ASSERT_IS_VOID const_cast< forced_unwind & >( ex).caught = true; #endif } // this context has finished its task from = nullptr; ontop = nullptr; terminated = true; force_unwind = false; std::move( c).resume(); BOOST_ASSERT_MSG( false, "fiber already terminated"); } }; template< typename Ctx, typename StackAlloc, typename Fn > static fiber_activation_record * create_fiber1( StackAlloc && salloc, Fn && fn) { typedef fiber_capture_record< Ctx, StackAlloc, Fn > capture_t; auto sctx = salloc.allocate(); // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack capture_t * record = new ( storage) capture_t{ sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // stack bottom void * stack_bottom = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) ); // create user-context if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) { record->~capture_t(); salloc.deallocate( sctx); throw std::system_error( std::error_code( errno, std::system_category() ), "getcontext() failed"); } record->uctx.uc_stack.ss_sp = stack_bottom; // 64byte gap between control structure and stack top record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) - reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64); record->uctx.uc_link = nullptr; ::makecontext( & record->uctx, ( void (*)() ) & fiber_entry_func< capture_t >, 1, record); #if defined(BOOST_USE_ASAN) record->stack_bottom = record->uctx.uc_stack.ss_sp; record->stack_size = record->uctx.uc_stack.ss_size; #endif return record; } template< typename Ctx, typename StackAlloc, typename Fn > static fiber_activation_record * create_fiber2( preallocated palloc, StackAlloc && salloc, Fn && fn) { typedef fiber_capture_record< Ctx, StackAlloc, Fn > capture_t; // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack capture_t * record = new ( storage) capture_t{ palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // stack bottom void * stack_bottom = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) ); // create user-context if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) { record->~capture_t(); salloc.deallocate( palloc.sctx); throw std::system_error( std::error_code( errno, std::system_category() ), "getcontext() failed"); } record->uctx.uc_stack.ss_sp = stack_bottom; // 64byte gap between control structure and stack top record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) - reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64); record->uctx.uc_link = nullptr; ::makecontext( & record->uctx, ( void (*)() ) & fiber_entry_func< capture_t >, 1, record); #if defined(BOOST_USE_ASAN) record->stack_bottom = record->uctx.uc_stack.ss_sp; record->stack_size = record->uctx.uc_stack.ss_size; #endif return record; } } class BOOST_CONTEXT_DECL fiber { private: friend struct detail::fiber_activation_record; template< typename Ctx, typename StackAlloc, typename Fn > friend class detail::fiber_capture_record; template< typename Ctx, typename StackAlloc, typename Fn > friend detail::fiber_activation_record * detail::create_fiber1( StackAlloc &&, Fn &&); template< typename Ctx, typename StackAlloc, typename Fn > friend detail::fiber_activation_record * detail::create_fiber2( preallocated, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend fiber callcc( std::allocator_arg_t, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend fiber callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&); detail::fiber_activation_record * ptr_{ nullptr }; fiber( detail::fiber_activation_record * ptr) noexcept : ptr_{ ptr } { } public: fiber() = default; template< typename Fn, typename = detail::disable_overload< fiber, Fn > > fiber( Fn && fn) : fiber{ std::allocator_arg, #if defined(BOOST_USE_SEGMENTED_STACKS) segmented_stack(), #else fixedsize_stack(), #endif std::forward< Fn >( fn) } { } template< typename StackAlloc, typename Fn > fiber( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) : ptr_{ detail::create_fiber1< fiber >( std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } { } template< typename StackAlloc, typename Fn > fiber( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) : ptr_{ detail::create_fiber2< fiber >( palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } { } ~fiber() { if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) { if ( BOOST_LIKELY( ! ptr_->terminated) ) { ptr_->force_unwind = true; ptr_->resume(); BOOST_ASSERT( ptr_->terminated); } ptr_->deallocate(); } } fiber( fiber const&) = delete; fiber & operator=( fiber const&) = delete; fiber( fiber && other) noexcept { swap( other); } fiber & operator=( fiber && other) noexcept { if ( BOOST_LIKELY( this != & other) ) { fiber tmp = std::move( other); swap( tmp); } return * this; } fiber resume() && { BOOST_ASSERT( nullptr != ptr_); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::fiber_activation_record * ptr = detail::exchange( ptr_, nullptr)->resume(); #else detail::fiber_activation_record * ptr = std::exchange( ptr_, nullptr)->resume(); #endif if ( BOOST_UNLIKELY( detail::fiber_activation_record::current()->force_unwind) ) { throw detail::forced_unwind{ ptr}; } else if ( BOOST_UNLIKELY( nullptr != detail::fiber_activation_record::current()->ontop) ) { ptr = detail::fiber_activation_record::current()->ontop( ptr); detail::fiber_activation_record::current()->ontop = nullptr; } return { ptr }; } template< typename Fn > fiber resume_with( Fn && fn) && { BOOST_ASSERT( nullptr != ptr_); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::fiber_activation_record * ptr = detail::exchange( ptr_, nullptr)->resume_with< fiber >( std::forward< Fn >( fn) ); #else detail::fiber_activation_record * ptr = std::exchange( ptr_, nullptr)->resume_with< fiber >( std::forward< Fn >( fn) ); #endif if ( BOOST_UNLIKELY( detail::fiber_activation_record::current()->force_unwind) ) { throw detail::forced_unwind{ ptr}; } else if ( BOOST_UNLIKELY( nullptr != detail::fiber_activation_record::current()->ontop) ) { ptr = detail::fiber_activation_record::current()->ontop( ptr); detail::fiber_activation_record::current()->ontop = nullptr; } return { ptr }; } explicit operator bool() const noexcept { return nullptr != ptr_ && ! ptr_->terminated; } bool operator!() const noexcept { return nullptr == ptr_ || ptr_->terminated; } bool operator<( fiber const& other) const noexcept { return ptr_ < other.ptr_; } #if !defined(BOOST_EMBTC) template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) { if ( nullptr != other.ptr_) { return os << other.ptr_; } else { return os << "{not-a-context}"; } } #else template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other); #endif void swap( fiber & other) noexcept { std::swap( ptr_, other.ptr_); } }; #if defined(BOOST_EMBTC) template< typename charT, class traitsT > inline std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, fiber const& other) { if ( nullptr != other.ptr_) { return os << other.ptr_; } else { return os << "{not-a-context}"; } } #endif inline void swap( fiber & l, fiber & r) noexcept { l.swap( r); } typedef fiber fiber_context; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_FIBER_H PK ��!\͗2�; �; continuation_winfib.hppnu �[��� // Copyright Oliver Kowalke 2017. // 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_CONTEXT_CONTINUATION_H #define BOOST_CONTEXT_CONTINUATION_H #include <windows.h> #include <boost/context/detail/config.hpp> #include <algorithm> #include <cstddef> #include <cstdint> #include <cstdlib> #include <cstring> #include <functional> #include <memory> #include <ostream> #include <system_error> #include <tuple> #include <utility> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/context/detail/disable_overload.hpp> #if defined(BOOST_NO_CXX14_STD_EXCHANGE) #include <boost/context/detail/exchange.hpp> #endif #if defined(BOOST_NO_CXX17_STD_INVOKE) #include <boost/context/detail/invoke.hpp> #endif #include <boost/context/fixedsize_stack.hpp> #include <boost/context/flags.hpp> #include <boost/context/preallocated.hpp> #include <boost/context/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4702) #endif namespace boost { namespace context { namespace detail { // tampoline function // entered if the execution context // is resumed for the first time template< typename Record > static VOID WINAPI entry_func( LPVOID data) noexcept { Record * record = static_cast< Record * >( data); BOOST_ASSERT( nullptr != record); // start execution of toplevel context-function record->run(); } struct BOOST_CONTEXT_DECL activation_record { LPVOID fiber{ nullptr }; stack_context sctx{}; bool main_ctx{ true }; activation_record * from{ nullptr }; std::function< activation_record*(activation_record*&) > ontop{}; bool terminated{ false }; bool force_unwind{ false }; static activation_record *& current() noexcept; // used for toplevel-context // (e.g. main context, thread-entry context) activation_record() noexcept { #if ( _WIN32_WINNT > 0x0600) if ( ::IsThreadAFiber() ) { fiber = ::GetCurrentFiber(); } else { fiber = ::ConvertThreadToFiber( nullptr); } #else fiber = ::ConvertThreadToFiber( nullptr); if ( BOOST_UNLIKELY( nullptr == fiber) ) { DWORD err = ::GetLastError(); BOOST_ASSERT( ERROR_ALREADY_FIBER == err); fiber = ::GetCurrentFiber(); BOOST_ASSERT( nullptr != fiber); BOOST_ASSERT( reinterpret_cast< LPVOID >( 0x1E00) != fiber); } #endif } activation_record( stack_context sctx_) noexcept : sctx{ sctx_ }, main_ctx{ false } { } virtual ~activation_record() { if ( BOOST_UNLIKELY( main_ctx) ) { ::ConvertFiberToThread(); } else { ::DeleteFiber( fiber); } } activation_record( activation_record const&) = delete; activation_record & operator=( activation_record const&) = delete; bool is_main_context() const noexcept { return main_ctx; } activation_record * resume() { from = current(); // store `this` in static, thread local pointer // `this` will become the active (running) context current() = this; // context switch from parent context to `this`-context // context switch ::SwitchToFiber( fiber); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return detail::exchange( current()->from, nullptr); #else return std::exchange( current()->from, nullptr); #endif } template< typename Ctx, typename Fn > activation_record * resume_with( Fn && fn) { from = current(); // store `this` in static, thread local pointer // `this` will become the active (running) context // returned by continuation::current() current() = this; #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) current()->ontop = std::bind( [](typename std::decay< Fn >::type & fn, activation_record *& ptr){ Ctx c{ ptr }; c = fn( std::move( c) ); if ( ! c) { ptr = nullptr; } #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.ptr_, nullptr); #else return std::exchange( c.ptr_, nullptr); #endif }, std::forward< Fn >( fn), std::placeholders::_1); #else current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){ Ctx c{ ptr }; c = fn( std::move( c) ); if ( ! c) { ptr = nullptr; } #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.ptr_, nullptr); #else return std::exchange( c.ptr_, nullptr); #endif }; #endif // context switch ::SwitchToFiber( fiber); #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return detail::exchange( current()->from, nullptr); #else return std::exchange( current()->from, nullptr); #endif } virtual void deallocate() noexcept { } }; struct BOOST_CONTEXT_DECL activation_record_initializer { activation_record_initializer() noexcept; ~activation_record_initializer(); }; struct forced_unwind { activation_record * from{ nullptr }; #ifndef BOOST_ASSERT_IS_VOID bool caught{ false }; #endif explicit forced_unwind( activation_record * from_) : from{ from_ } { } #ifndef BOOST_ASSERT_IS_VOID ~forced_unwind() { BOOST_ASSERT( caught); } #endif }; template< typename Ctx, typename StackAlloc, typename Fn > class capture_record : public activation_record { private: typename std::decay< StackAlloc >::type salloc_; typename std::decay< Fn >::type fn_; static void destroy( capture_record * p) noexcept { typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_); stack_context sctx = p->sctx; // deallocate activation record p->~capture_record(); // destroy stack with stack allocator salloc.deallocate( sctx); } public: capture_record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept : activation_record( sctx), salloc_( std::forward< StackAlloc >( salloc)), fn_( std::forward< Fn >( fn) ) { } void deallocate() noexcept override final { BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) ); destroy( this); } void run() { Ctx c{ from }; try { // invoke context-function #if defined(BOOST_NO_CXX17_STD_INVOKE) c = boost::context::detail::invoke( fn_, std::move( c) ); #else c = std::invoke( fn_, std::move( c) ); #endif } catch ( forced_unwind const& ex) { c = Ctx{ ex.from }; #ifndef BOOST_ASSERT_IS_VOID const_cast< forced_unwind & >( ex).caught = true; #endif } // this context has finished its task from = nullptr; ontop = nullptr; terminated = true; force_unwind = false; c.resume(); BOOST_ASSERT_MSG( false, "continuation already terminated"); } }; template< typename Ctx, typename StackAlloc, typename Fn > static activation_record * create_context1( StackAlloc && salloc, Fn && fn) { typedef capture_record< Ctx, StackAlloc, Fn > capture_t; auto sctx = salloc.allocate(); BOOST_ASSERT( ( sizeof( capture_t) ) < sctx.size); // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack capture_t * record = new ( storage) capture_t{ sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // create user-context record->fiber = ::CreateFiber( sctx.size, & detail::entry_func< capture_t >, record); return record; } template< typename Ctx, typename StackAlloc, typename Fn > static activation_record * create_context2( preallocated palloc, StackAlloc && salloc, Fn && fn) { typedef capture_record< Ctx, StackAlloc, Fn > capture_t; BOOST_ASSERT( ( sizeof( capture_t) ) < palloc.size); // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack capture_t * record = new ( storage) capture_t{ palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // create user-context record->fiber = ::CreateFiber( palloc.sctx.size, & detail::entry_func< capture_t >, record); return record; } } class BOOST_CONTEXT_DECL continuation { private: friend struct detail::activation_record; template< typename Ctx, typename StackAlloc, typename Fn > friend class detail::capture_record; template< typename Ctx, typename StackAlloc, typename Fn > friend detail::activation_record * detail::create_context1( StackAlloc &&, Fn &&); template< typename Ctx, typename StackAlloc, typename Fn > friend detail::activation_record * detail::create_context2( preallocated, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend continuation callcc( std::allocator_arg_t, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend continuation callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&); detail::activation_record * ptr_{ nullptr }; continuation( detail::activation_record * ptr) noexcept : ptr_{ ptr } { } public: continuation() = default; ~continuation() { if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) { if ( BOOST_LIKELY( ! ptr_->terminated) ) { ptr_->force_unwind = true; ptr_->resume(); BOOST_ASSERT( ptr_->terminated); } ptr_->deallocate(); } } continuation( continuation const&) = delete; continuation & operator=( continuation const&) = delete; continuation( continuation && other) noexcept { swap( other); } continuation & operator=( continuation && other) noexcept { if ( BOOST_LIKELY( this != & other) ) { continuation tmp = std::move( other); swap( tmp); } return * this; } continuation resume() & { return std::move( * this).resume(); } continuation resume() && { #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume(); #else detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume(); #endif if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) { throw detail::forced_unwind{ ptr}; } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) { ptr = detail::activation_record::current()->ontop( ptr); detail::activation_record::current()->ontop = nullptr; } return { ptr }; } template< typename Fn > continuation resume_with( Fn && fn) & { return std::move( * this).resume_with( std::forward< Fn >( fn) ); } template< typename Fn > continuation resume_with( Fn && fn) && { #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) ); #else detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) ); #endif if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) { throw detail::forced_unwind{ ptr}; } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) { ptr = detail::activation_record::current()->ontop( ptr); detail::activation_record::current()->ontop = nullptr; } return { ptr }; } explicit operator bool() const noexcept { return nullptr != ptr_ && ! ptr_->terminated; } bool operator!() const noexcept { return nullptr == ptr_ || ptr_->terminated; } bool operator<( continuation const& other) const noexcept { return ptr_ < other.ptr_; } #if !defined(BOOST_EMBTC) template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) { if ( nullptr != other.ptr_) { return os << other.ptr_; } else { return os << "{not-a-context}"; } } #else template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other); #endif void swap( continuation & other) noexcept { std::swap( ptr_, other.ptr_); } }; #if defined(BOOST_EMBTC) template< typename charT, class traitsT > inline std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) { if ( nullptr != other.ptr_) { return os << other.ptr_; } else { return os << "{not-a-context}"; } } #endif template< typename Fn, typename = detail::disable_overload< continuation, Fn > > continuation callcc( Fn && fn) { return callcc( std::allocator_arg, fixedsize_stack(), std::forward< Fn >( fn) ); } template< typename StackAlloc, typename Fn > continuation callcc( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) { return continuation{ detail::create_context1< continuation >( std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume(); } template< typename StackAlloc, typename Fn > continuation callcc( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) { return continuation{ detail::create_context2< continuation >( palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume(); } inline void swap( continuation & l, continuation & r) noexcept { l.swap( r); } }} #if defined(BOOST_MSVC) # pragma warning(pop) #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_CONTINUATION_H PK ��!\�t � � posix/segmented_stack.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_SEGMENTED_H #define BOOST_CONTEXT_SEGMENTED_H #include <cstddef> #include <new> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #include <boost/context/stack_context.hpp> #include <boost/context/stack_traits.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif // forward declaration for splitstack-functions defined in libgcc extern "C" { void *__splitstack_makecontext( std::size_t, void * [BOOST_CONTEXT_SEGMENTS], std::size_t *); void __splitstack_releasecontext( void * [BOOST_CONTEXT_SEGMENTS]); void __splitstack_resetcontext( void * [BOOST_CONTEXT_SEGMENTS]); void __splitstack_block_signals_context( void * [BOOST_CONTEXT_SEGMENTS], int * new_value, int * old_value); } namespace boost { namespace context { template< typename traitsT > class basic_segmented_stack { private: std::size_t size_; public: typedef traitsT traits_type; basic_segmented_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW : size_( size) { } stack_context allocate() { stack_context sctx; void * vp = __splitstack_makecontext( size_, sctx.segments_ctx, & sctx.size); if ( ! vp) throw std::bad_alloc(); // sctx.size is already filled by __splitstack_makecontext sctx.sp = static_cast< char * >( vp) + sctx.size; int off = 0; __splitstack_block_signals_context( sctx.segments_ctx, & off, 0); return sctx; } void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW { __splitstack_releasecontext( sctx.segments_ctx); } }; typedef basic_segmented_stack< stack_traits > segmented_stack; # if defined(BOOST_USE_SEGMENTED_STACKS) typedef segmented_stack default_stack; # endif }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_SEGMENTED_H PK ��!\ԑR�� � # posix/protected_fixedsize_stack.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_PROTECTED_FIXEDSIZE_H #define BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H extern "C" { #include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> } #include <cmath> #include <cstddef> #include <new> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/core/ignore_unused.hpp> #include <boost/context/detail/config.hpp> #include <boost/context/stack_context.hpp> #include <boost/context/stack_traits.hpp> #if defined(BOOST_USE_VALGRIND) #include <valgrind/valgrind.h> #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { template< typename traitsT > class basic_protected_fixedsize_stack { private: std::size_t size_; public: typedef traitsT traits_type; basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW : size_( size) { } stack_context allocate() { // calculate how many pages are required const std::size_t pages( static_cast< std::size_t >( std::ceil( static_cast< float >( size_) / traits_type::page_size() ) ) ); // add one page at bottom that will be used as guard-page const std::size_t size__ = ( pages + 1) * traits_type::page_size(); #if defined(BOOST_CONTEXT_USE_MAP_STACK) void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0); #elif defined(MAP_ANON) void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); #else void * vp = ::mmap( 0, size__, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); #endif if ( MAP_FAILED == vp) throw std::bad_alloc(); // conforming to POSIX.1-2001 const int result( ::mprotect( vp, traits_type::page_size(), PROT_NONE) ); boost::ignore_unused(result); BOOST_ASSERT( 0 == result); stack_context sctx; sctx.size = size__; sctx.sp = static_cast< char * >( vp) + sctx.size; #if defined(BOOST_USE_VALGRIND) sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp); #endif return sctx; } void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT( sctx.sp); #if defined(BOOST_USE_VALGRIND) VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id); #endif void * vp = static_cast< char * >( sctx.sp) - sctx.size; // conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L) ::munmap( vp, sctx.size); } }; typedef basic_protected_fixedsize_stack< stack_traits > protected_fixedsize_stack; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H PK ��!\�.�,F F flags.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_FLAGS_H #define BOOST_CONTEXT_FLAGS_H # include <boost/config.hpp> # ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX # endif namespace boost { namespace context { struct exec_ontop_arg_t {}; const exec_ontop_arg_t exec_ontop_arg{}; }} # ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX # endif #endif // BOOST_CONTEXT_FLAGS_H PK ��!\�,�� detail/invoke.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_DETAIL_INVOKE_H #define BOOST_CONTEXT_DETAIL_INVOKE_H #include <functional> #include <type_traits> #include <utility> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { template< typename Fn, typename ... Args > typename std::enable_if< std::is_member_pointer< typename std::decay< Fn >::type >::value, typename std::result_of< Fn &&( Args && ... ) >::type >::type invoke( Fn && fn, Args && ... args) { return std::mem_fn( fn)( std::forward< Args >( args) ... ); } template< typename Fn, typename ... Args > typename std::enable_if< ! std::is_member_pointer< typename std::decay< Fn >::type >::value, typename std::result_of< Fn &&( Args && ... ) >::type >::type invoke( Fn && fn, Args && ... args) { return std::forward< Fn >( fn)( std::forward< Args >( args) ... ); } }}} #ifdef BOOST_HAS_ABI_HEADERS #include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_DETAIL_INVOKE_H PK ��!\Ĺ��� � detail/externc.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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> #include <boost/context/detail/config.hpp> #if defined(BOOST_USE_ASAN) extern "C" { void __sanitizer_start_switch_fiber( void **, const void *, size_t); void __sanitizer_finish_switch_fiber( void *, const void **, size_t *); } #endif #if defined(BOOST_USE_SEGMENTED_STACKS) extern "C" { void __splitstack_getcontext( void * [BOOST_CONTEXT_SEGMENTS]); void __splitstack_setcontext( void * [BOOST_CONTEXT_SEGMENTS]); } #endif PK ��!\(�ބ� � detail/exchange.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_DETAIL_EXCHANGE_H #define BOOST_CONTEXT_DETAIL_EXCHANGE_H #include <algorithm> #include <utility> #include <boost/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { template< typename T, typename U = T > T exchange( T & t, U && nv) { T ov = std::move( t); t = std::forward< U >( nv); return ov; } }}} #ifdef BOOST_HAS_ABI_HEADERS #include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_DETAIL_EXCHANGE_H PK ��!\k�:�� � detail/prefetch.hppnu �[��� // Copyright Oliver Kowalke 2017. // 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_CONTEXT_DETAIL_PREFETCH_H #define BOOST_CONTEXT_DETAIL_PREFETCH_H #include <cstddef> #include <cstdint> #include <boost/config.hpp> #include <boost/predef.h> #include <boost/context/detail/config.hpp> #if BOOST_COMP_INTEL || BOOST_COMP_INTEL_EMULATED #include <immintrin.h> #endif #if BOOST_COMP_MSVC && !defined(_M_ARM) && !defined(_M_ARM64) #include <mmintrin.h> #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { #if BOOST_COMP_GNUC || BOOST_COMP_CLANG #define BOOST_HAS_PREFETCH 1 BOOST_FORCEINLINE void prefetch( void * addr) { // L1 cache : hint == 1 __builtin_prefetch( addr, 1, 1); } #elif BOOST_COMP_INTEL || BOOST_COMP_INTEL_EMULATED #define BOOST_HAS_PREFETCH 1 BOOST_FORCEINLINE void prefetch( void * addr) { // L1 cache : hint == _MM_HINT_T0 _mm_prefetch( (const char *)addr, _MM_HINT_T0); } #elif BOOST_COMP_MSVC && !defined(_M_ARM) && !defined(_M_ARM64) #define BOOST_HAS_PREFETCH 1 BOOST_FORCEINLINE void prefetch( void * addr) { // L1 cache : hint == _MM_HINT_T0 _mm_prefetch( (const char *)addr, _MM_HINT_T0); } #endif inline void prefetch_range( void * addr, std::size_t len) { #if defined(BOOST_HAS_PREFETCH) void * vp = addr; void * end = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( addr) + static_cast< uintptr_t >( len) ); while ( vp < end) { prefetch( vp); vp = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( vp) + static_cast< uintptr_t >( prefetch_stride) ); } #endif } #undef BOOST_HAS_PREFETCH }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_DETAIL_PREFETCH_H PK ��!\��F�G G detail/apply.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_DETAIL_APPLY_H #define BOOST_CONTEXT_DETAIL_APPLY_H #include <functional> #include <tuple> #include <type_traits> #include <utility> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #if defined(BOOST_NO_CXX17_STD_INVOKE) #include <boost/context/detail/invoke.hpp> #endif #include <boost/context/detail/index_sequence.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4100) #endif namespace boost { namespace context { namespace detail { template< typename Fn, typename Tpl, std::size_t ... I > auto apply_impl( Fn && fn, Tpl && tpl, index_sequence< I ... >) #if defined(BOOST_NO_CXX17_STD_INVOKE) -> decltype( boost::context::detail::invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ) ) #else -> decltype( std::invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ) ) #endif { #if defined(BOOST_NO_CXX17_STD_INVOKE) return boost::context::detail::invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ); #else return std::invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ); #endif } template< typename Fn, typename Tpl > auto apply( Fn && fn, Tpl && tpl) -> decltype( apply_impl( std::forward< Fn >( fn), std::forward< Tpl >( tpl), make_index_sequence< std::tuple_size< typename std::decay< Tpl >::type >::value >{}) ) { return apply_impl( std::forward< Fn >( fn), std::forward< Tpl >( tpl), make_index_sequence< std::tuple_size< typename std::decay< Tpl >::type >::value >{}); } }}} #if defined(BOOST_MSVC) # pragma warning(pop) #endif #ifdef BOOST_HAS_ABI_HEADERS #include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_DETAIL_APPLY_H PK ��!\-�� detail/config.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_DETAIL_CONFIG_H #define BOOST_CONTEXT_DETAIL_CONFIG_H // required for SD-6 compile-time integer sequences #include <utility> #include <boost/config.hpp> #include <boost/detail/workaround.hpp> #ifdef BOOST_CONTEXT_DECL # undef BOOST_CONTEXT_DECL #endif #if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTEXT_DYN_LINK) ) && ! defined(BOOST_CONTEXT_STATIC_LINK) # if defined(BOOST_CONTEXT_SOURCE) # define BOOST_CONTEXT_DECL BOOST_SYMBOL_EXPORT # define BOOST_CONTEXT_BUILD_DLL # else # define BOOST_CONTEXT_DECL BOOST_SYMBOL_IMPORT # endif #endif #if ! defined(BOOST_CONTEXT_DECL) # define BOOST_CONTEXT_DECL #endif #if ! defined(BOOST_CONTEXT_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_CONTEXT_NO_LIB) # define BOOST_LIB_NAME boost_context # if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTEXT_DYN_LINK) # define BOOST_DYN_LINK # endif # include <boost/config/auto_link.hpp> #endif #undef BOOST_CONTEXT_CALLDECL #if (defined(i386) || defined(__i386__) || defined(__i386) \ || defined(__i486__) || defined(__i586__) || defined(__i686__) \ || defined(__X86__) || defined(_X86_) || defined(__THW_INTEL__) \ || defined(__I86__) || defined(__INTEL__) || defined(__IA32__) \ || defined(_M_IX86) || defined(_I86_)) && defined(BOOST_WINDOWS) # define BOOST_CONTEXT_CALLDECL __cdecl #else # define BOOST_CONTEXT_CALLDECL #endif #if defined(BOOST_USE_SEGMENTED_STACKS) # if ! ( (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) ) ) || \ (defined(__clang__) && (__clang_major__ > 2 || ( __clang_major__ == 2 && __clang_minor__ > 3) ) ) ) # error "compiler does not support segmented_stack stacks" # endif # define BOOST_CONTEXT_SEGMENTS 10 #endif #define BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE // use rd6 macros for std::integer_sequence #if defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304 # undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE #endif // workaroud: MSVC 14 does not provide macros to test for compile-time integer sequence #if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013 # undef BOOST_CONTEXT_NO_INDEX_SEQUENCE #endif // workaround: Xcode clang feature detection #if ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304 # if _LIBCPP_STD_VER > 11 # undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE # endif #endif // workaroud: MSVC 14 does support constexpr #if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013 # undef BOOST_NO_CXX11_CONSTEXPR #endif #undef BOOST_CONTEXT_NO_CXX11 #if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) || \ defined(BOOST_NO_CXX11_CONSTEXPR) || \ defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || \ defined(BOOST_NO_CXX11_FINAL) || \ defined(BOOST_NO_CXX11_HDR_TUPLE) || \ defined(BOOST_NO_CXX11_NOEXCEPT) || \ defined(BOOST_NO_CXX11_NULLPTR) || \ defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || \ defined(BOOST_NO_CXX11_UNIFIED_INITIALISATION_SYNTAX) || \ defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \ defined(BOOST_NO_HDR_ATOMIC) || \ defined(BOOST_NO_HDR_TUPLE) # define BOOST_CONTEXT_NO_CXX11 #endif #if ! defined(BOOST_EXECUTION_CONTEXT) # if defined(BOOST_USE_SEGMENTED_STACKS) # define BOOST_EXECUTION_CONTEXT 1 # else # define BOOST_EXECUTION_CONTEXT 2 # endif #endif #if ! defined(BOOST_NO_CXX11_CONSTEXPR) // modern architectures have cachelines with 64byte length // ARM Cortex-A15 32/64byte, Cortex-A9 16/32/64bytes // MIPS 74K: 32byte, 4KEc: 16byte // ist should be safe to use 64byte for all static constexpr std::size_t cache_alignment{ 64 }; static constexpr std::size_t cacheline_length{ 64 }; // lookahead size for prefetching static constexpr std::size_t prefetch_stride{ 4 * cacheline_length }; #endif #if defined(__GLIBCPP__) || defined(__GLIBCXX__) // GNU libstdc++ 3 # define BOOST_CONTEXT_HAS_CXXABI_H #endif #if defined( BOOST_CONTEXT_HAS_CXXABI_H ) # include <cxxabi.h> #endif #if defined(__OpenBSD__) // stacks need mmap(2) with MAP_STACK # define BOOST_CONTEXT_USE_MAP_STACK #endif #endif // BOOST_CONTEXT_DETAIL_CONFIG_H PK ��!\=�� � detail/exception.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_DETAIL_EXCEPTION_H #define BOOST_CONTEXT_DETAIL_EXCEPTION_H #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/context/detail/fcontext.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { struct forced_unwind { fcontext_t fctx{ nullptr }; #ifndef BOOST_ASSERT_IS_VOID bool caught{ false }; #endif forced_unwind() = default; forced_unwind( fcontext_t fctx_) : fctx( fctx_) { } #ifndef BOOST_ASSERT_IS_VOID ~forced_unwind() { BOOST_ASSERT( caught); } #endif }; }}} #ifdef BOOST_HAS_ABI_HEADERS #include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_DETAIL_EXCEPTION_H PK ��!\��5Ë � detail/fcontext.hppnu �[��� // Copyright Oliver Kowalke 2009. // 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_CONTEXT_DETAIL_FCONTEXT_H #define BOOST_CONTEXT_DETAIL_FCONTEXT_H #include <boost/config.hpp> #include <boost/cstdint.hpp> #include <boost/context/detail/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { typedef void* fcontext_t; struct transfer_t { fcontext_t fctx; void * data; }; extern "C" BOOST_CONTEXT_DECL transfer_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t const to, void * vp); extern "C" BOOST_CONTEXT_DECL fcontext_t BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( transfer_t) ); // based on an idea of Giovanni Derreta extern "C" BOOST_CONTEXT_DECL transfer_t BOOST_CONTEXT_CALLDECL ontop_fcontext( fcontext_t const to, void * vp, transfer_t (* fn)( transfer_t) ); }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_DETAIL_FCONTEXT_H PK ��!\&��� � detail/index_sequence.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_DETAIL_INDEX_SEQUENCE_H #define BOOST_CONTEXT_DETAIL_INDEX_SEQUENCE_H #include <cstddef> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { #if ! defined(BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE) template< std::size_t ... I > using index_sequence = std::index_sequence< I ... >; template< std::size_t I > using make_index_sequence = std::make_index_sequence< I >; template< typename ... T > using index_sequence_for = std::index_sequence_for< T ... >; #else //http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence template< std::size_t ... I > struct index_sequence { using type = index_sequence; using value_type = std::size_t; static constexpr std::size_t size() { return sizeof ... (I); } }; template< typename Seq1, typename Seq2 > struct concat_sequence; template< std::size_t ... I1, std::size_t ... I2 > struct concat_sequence< index_sequence< I1 ... >, index_sequence< I2 ... > > : public index_sequence< I1 ..., (sizeof ... (I1)+I2) ... > { }; template< std::size_t I > struct make_index_sequence : public concat_sequence< typename make_index_sequence< I/2 >::type, typename make_index_sequence< I-I/2 >::type > { }; template<> struct make_index_sequence< 0 > : public index_sequence<> { }; template<> struct make_index_sequence< 1 > : public index_sequence< 0 > { }; template< typename ... T > using index_sequence_for = make_index_sequence< sizeof ... (T) >; #endif }}} #ifdef BOOST_HAS_ABI_HEADERS #include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_DETAIL_INDEX_SEQUENCE_H PK ��!\�sA�} } detail/tuple.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_DETAIL_TUPLE_H #define BOOST_CONTEXT_DETAIL_TUPLE_H #include <tuple> #include <utility> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #include <boost/context/detail/index_sequence.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { template< typename ... S, typename ... T, std::size_t ... I > void head_impl( std::tuple< S ... > & s, std::tuple< T ... > & t, index_sequence< I ... >) { t = std::tuple< T ... >{ std::get< I >( s) ... }; } template< typename ... S, typename ... T, std::size_t ... I > void head_impl( std::tuple< S ... > && s, std::tuple< T ... > & t, index_sequence< I ... >) { t = std::tuple< T ... >{ std::get< I >( std::move( s) ) ... }; } template< typename ... S, std::size_t ... I1, typename ... T, std::size_t ... I2 > void tail_impl( std::tuple< S ... > & s, index_sequence< I1 ... >, std::tuple< T ... > & t, index_sequence< I2 ... >) { constexpr std::size_t Idx = (sizeof...(I1)) - (sizeof...(I2)); t = std::tuple< T ... >{ std::get< (Idx + I2) >( s) ... }; } template< typename ... S, std::size_t ... I1, typename ... T, std::size_t ... I2 > void tail_impl( std::tuple< S ... > && s, index_sequence< I1 ... >, std::tuple< T ... > & t, index_sequence< I2 ... >) { constexpr std::size_t Idx = (sizeof...(I1)) - (sizeof...(I2)); t = std::tuple< T ... >{ std::get< (Idx + I2) >( std::move( s) ) ... }; } template< typename ... T > class tuple_head; template< typename ... T > class tuple_head< std::tuple< T ... > > { private: std::tuple< T ... > & t_; public: tuple_head( std::tuple< T ... > & t) noexcept : t_( t) { } template< typename ... S > void operator=( std::tuple< S ... > & s) { static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size"); head_impl( s, t_, index_sequence_for< T ... >{} ); } template< typename ... S > void operator=( std::tuple< S ... > && s) { static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size"); head_impl( std::move( s), t_, index_sequence_for< T ... >{} ); } }; template< typename ... T > class tuple_tail; template< typename ... T > class tuple_tail< std::tuple< T ... > > { private: std::tuple< T ... > & t_; public: tuple_tail( std::tuple< T ... > & t) noexcept : t_( t) { } template< typename ... S > void operator=( std::tuple< S ... > & s) { static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size"); tail_impl( s, index_sequence_for< S ... >{}, t_, index_sequence_for< T ... >{} ); } template< typename ... S > void operator=( std::tuple< S ... > && s) { static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size"); tail_impl( std::move( s), index_sequence_for< S ... >{}, t_, index_sequence_for< T ... >{} ); } }; template< typename ... T > detail::tuple_head< std::tuple< T ... > > head( std::tuple< T ... > & tpl) { return tuple_head< std::tuple< T ... > >{ tpl }; } template< typename ... T > detail::tuple_tail< std::tuple< T ... > > tail( std::tuple< T ... > & tpl) { return tuple_tail< std::tuple< T ... > >{ tpl }; } }}} #ifdef BOOST_HAS_ABI_HEADERS #include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_DETAIL_TUPLE_H PK ��!\0��� � detail/disable_overload.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_DETAIL_DISABLE_OVERLOAD_H #define BOOST_CONTEXT_DETAIL_DISABLE_OVERLOAD_H #include <type_traits> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { // http://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/ template< typename X, typename Y > using disable_overload = typename std::enable_if< ! std::is_base_of< X, typename std::decay< Y >::type >::value >::type; }}} #ifdef BOOST_HAS_ABI_HEADERS #include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_DETAIL_DISABLE_OVERLOAD_H PK ��!\Ȭ\�$ $ % windows/protected_fixedsize_stack.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_PROTECTED_FIXEDSIZE_H #define BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H extern "C" { #include <windows.h> } #include <cmath> #include <cstddef> #include <new> #include <boost/config.hpp> #include <boost/core/ignore_unused.hpp> #include <boost/context/detail/config.hpp> #include <boost/context/stack_context.hpp> #include <boost/context/stack_traits.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { template< typename traitsT > class basic_protected_fixedsize_stack { private: std::size_t size_; public: typedef traitsT traits_type; basic_protected_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW : size_( size) { } stack_context allocate() { // calculate how many pages are required const std::size_t pages( static_cast< std::size_t >( std::ceil( static_cast< float >( size_) / traits_type::page_size() ) ) ); // add one page at bottom that will be used as guard-page const std::size_t size__ = ( pages + 1) * traits_type::page_size(); void * vp = ::VirtualAlloc( 0, size__, MEM_COMMIT, PAGE_READWRITE); if ( ! vp) throw std::bad_alloc(); DWORD old_options; const BOOL result = ::VirtualProtect( vp, traits_type::page_size(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options); boost::ignore_unused(result); BOOST_ASSERT( FALSE != result); stack_context sctx; sctx.size = size__; sctx.sp = static_cast< char * >( vp) + sctx.size; return sctx; } void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT( sctx.sp); void * vp = static_cast< char * >( sctx.sp) - sctx.size; ::VirtualFree( vp, 0, MEM_RELEASE); } }; typedef basic_protected_fixedsize_stack< stack_traits > protected_fixedsize_stack; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_PROTECTED_FIXEDSIZE_H PK ��!\@ug| | segmented_stack.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_USE_SEGMENTED_STACKS) # if ! defined(BOOST_WINDOWS) # include <boost/context/posix/segmented_stack.hpp> # endif #endif PK ��!\٣7(�G �G continuation_ucontext.hppnu �[��� // Copyright Oliver Kowalke 2017. // 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_CONTEXT_CONTINUATION_H #define BOOST_CONTEXT_CONTINUATION_H #include <boost/predef.h> #if BOOST_OS_MACOS #define _XOPEN_SOURCE 600 #endif extern "C" { #include <ucontext.h> } #include <boost/context/detail/config.hpp> #include <algorithm> #include <cstddef> #include <cstdint> #include <cstdlib> #include <cstring> #include <functional> #include <memory> #include <ostream> #include <system_error> #include <tuple> #include <utility> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/context/detail/disable_overload.hpp> #if defined(BOOST_NO_CXX14_STD_EXCHANGE) #include <boost/context/detail/exchange.hpp> #endif #include <boost/context/detail/externc.hpp> #if defined(BOOST_NO_CXX17_STD_INVOKE) #include <boost/context/detail/invoke.hpp> #endif #include <boost/context/fixedsize_stack.hpp> #include <boost/context/flags.hpp> #include <boost/context/preallocated.hpp> #if defined(BOOST_USE_SEGMENTED_STACKS) #include <boost/context/segmented_stack.hpp> #endif #include <boost/context/stack_context.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { namespace detail { // tampoline function // entered if the execution context // is resumed for the first time template< typename Record > static void entry_func( void * data) noexcept { Record * record = static_cast< Record * >( data); BOOST_ASSERT( nullptr != record); // start execution of toplevel context-function record->run(); } struct BOOST_CONTEXT_DECL activation_record { ucontext_t uctx{}; stack_context sctx{}; bool main_ctx{ true }; activation_record * from{ nullptr }; std::function< activation_record*(activation_record*&) > ontop{}; bool terminated{ false }; bool force_unwind{ false }; #if defined(BOOST_USE_ASAN) void * fake_stack{ nullptr }; void * stack_bottom{ nullptr }; std::size_t stack_size{ 0 }; #endif static activation_record *& current() noexcept; // used for toplevel-context // (e.g. main context, thread-entry context) activation_record() { if ( BOOST_UNLIKELY( 0 != ::getcontext( & uctx) ) ) { throw std::system_error( std::error_code( errno, std::system_category() ), "getcontext() failed"); } } activation_record( stack_context sctx_) noexcept : sctx( sctx_ ), main_ctx( false ) { } virtual ~activation_record() { } activation_record( activation_record const&) = delete; activation_record & operator=( activation_record const&) = delete; bool is_main_context() const noexcept { return main_ctx; } activation_record * resume() { from = current(); // store `this` in static, thread local pointer // `this` will become the active (running) context current() = this; #if defined(BOOST_USE_SEGMENTED_STACKS) // adjust segmented stack properties __splitstack_getcontext( from->sctx.segments_ctx); __splitstack_setcontext( sctx.segments_ctx); #endif #if defined(BOOST_USE_ASAN) if ( terminated) { __sanitizer_start_switch_fiber( nullptr, stack_bottom, stack_size); } else { __sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size); } #endif // context switch from parent context to `this`-context ::swapcontext( & from->uctx, & uctx); #if defined(BOOST_USE_ASAN) __sanitizer_finish_switch_fiber( current()->fake_stack, (const void **) & current()->from->stack_bottom, & current()->from->stack_size); #endif #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( current()->from, nullptr); #else return std::exchange( current()->from, nullptr); #endif } template< typename Ctx, typename Fn > activation_record * resume_with( Fn && fn) { from = current(); // store `this` in static, thread local pointer // `this` will become the active (running) context // returned by continuation::current() current() = this; #if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) current()->ontop = std::bind( [](typename std::decay< Fn >::type & fn, activation_record *& ptr){ Ctx c{ ptr }; c = fn( std::move( c) ); if ( ! c) { ptr = nullptr; } #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.ptr_, nullptr); #else return std::exchange( c.ptr_, nullptr); #endif }, std::forward< Fn >( fn), std::placeholders::_1); #else current()->ontop = [fn=std::forward<Fn>(fn)](activation_record *& ptr){ Ctx c{ ptr }; c = fn( std::move( c) ); if ( ! c) { ptr = nullptr; } #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( c.ptr_, nullptr); #else return std::exchange( c.ptr_, nullptr); #endif }; #endif #if defined(BOOST_USE_SEGMENTED_STACKS) // adjust segmented stack properties __splitstack_getcontext( from->sctx.segments_ctx); __splitstack_setcontext( sctx.segments_ctx); #endif #if defined(BOOST_USE_ASAN) __sanitizer_start_switch_fiber( & from->fake_stack, stack_bottom, stack_size); #endif // context switch from parent context to `this`-context ::swapcontext( & from->uctx, & uctx); #if defined(BOOST_USE_ASAN) __sanitizer_finish_switch_fiber( current()->fake_stack, (const void **) & current()->from->stack_bottom, & current()->from->stack_size); #endif #if defined(BOOST_NO_CXX14_STD_EXCHANGE) return exchange( current()->from, nullptr); #else return std::exchange( current()->from, nullptr); #endif } virtual void deallocate() noexcept { } }; struct BOOST_CONTEXT_DECL activation_record_initializer { activation_record_initializer() noexcept; ~activation_record_initializer(); }; struct forced_unwind { activation_record * from{ nullptr }; #ifndef BOOST_ASSERT_IS_VOID bool caught{ false }; #endif forced_unwind( activation_record * from_) noexcept : from{ from_ } { } #ifndef BOOST_ASSERT_IS_VOID ~forced_unwind() { BOOST_ASSERT( caught); } #endif }; template< typename Ctx, typename StackAlloc, typename Fn > class capture_record : public activation_record { private: typename std::decay< StackAlloc >::type salloc_; typename std::decay< Fn >::type fn_; static void destroy( capture_record * p) noexcept { typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_); stack_context sctx = p->sctx; // deallocate activation record p->~capture_record(); // destroy stack with stack allocator salloc.deallocate( sctx); } public: capture_record( stack_context sctx, StackAlloc && salloc, Fn && fn) noexcept : activation_record{ sctx }, salloc_{ std::forward< StackAlloc >( salloc) }, fn_( std::forward< Fn >( fn) ) { } void deallocate() noexcept override final { BOOST_ASSERT( main_ctx || ( ! main_ctx && terminated) ); destroy( this); } void run() { #if defined(BOOST_USE_ASAN) __sanitizer_finish_switch_fiber( fake_stack, (const void **) & from->stack_bottom, & from->stack_size); #endif Ctx c{ from }; try { // invoke context-function #if defined(BOOST_NO_CXX17_STD_INVOKE) c = boost::context::detail::invoke( fn_, std::move( c) ); #else c = std::invoke( fn_, std::move( c) ); #endif } catch ( forced_unwind const& ex) { c = Ctx{ ex.from }; #ifndef BOOST_ASSERT_IS_VOID const_cast< forced_unwind & >( ex).caught = true; #endif } // this context has finished its task from = nullptr; ontop = nullptr; terminated = true; force_unwind = false; c.resume(); BOOST_ASSERT_MSG( false, "continuation already terminated"); } }; template< typename Ctx, typename StackAlloc, typename Fn > static activation_record * create_context1( StackAlloc && salloc, Fn && fn) { typedef capture_record< Ctx, StackAlloc, Fn > capture_t; auto sctx = salloc.allocate(); // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack capture_t * record = new ( storage) capture_t{ sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // stack bottom void * stack_bottom = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( sctx.sp) - static_cast< uintptr_t >( sctx.size) ); // create user-context if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) { record->~capture_t(); salloc.deallocate( sctx); throw std::system_error( std::error_code( errno, std::system_category() ), "getcontext() failed"); } record->uctx.uc_stack.ss_sp = stack_bottom; // 64byte gap between control structure and stack top record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) - reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64); record->uctx.uc_link = nullptr; ::makecontext( & record->uctx, ( void (*)() ) & entry_func< capture_t >, 1, record); #if defined(BOOST_USE_ASAN) record->stack_bottom = record->uctx.uc_stack.ss_sp; record->stack_size = record->uctx.uc_stack.ss_size; #endif return record; } template< typename Ctx, typename StackAlloc, typename Fn > static activation_record * create_context2( preallocated palloc, StackAlloc && salloc, Fn && fn) { typedef capture_record< Ctx, StackAlloc, Fn > capture_t; // reserve space for control structure void * storage = reinterpret_cast< void * >( ( reinterpret_cast< uintptr_t >( palloc.sp) - static_cast< uintptr_t >( sizeof( capture_t) ) ) & ~ static_cast< uintptr_t >( 0xff) ); // placment new for control structure on context stack capture_t * record = new ( storage) capture_t{ palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) }; // stack bottom void * stack_bottom = reinterpret_cast< void * >( reinterpret_cast< uintptr_t >( palloc.sctx.sp) - static_cast< uintptr_t >( palloc.sctx.size) ); // create user-context if ( BOOST_UNLIKELY( 0 != ::getcontext( & record->uctx) ) ) { record->~capture_t(); salloc.deallocate( palloc.sctx); throw std::system_error( std::error_code( errno, std::system_category() ), "getcontext() failed"); } record->uctx.uc_stack.ss_sp = stack_bottom; // 64byte gap between control structure and stack top record->uctx.uc_stack.ss_size = reinterpret_cast< uintptr_t >( storage) - reinterpret_cast< uintptr_t >( stack_bottom) - static_cast< uintptr_t >( 64); record->uctx.uc_link = nullptr; ::makecontext( & record->uctx, ( void (*)() ) & entry_func< capture_t >, 1, record); #if defined(BOOST_USE_ASAN) record->stack_bottom = record->uctx.uc_stack.ss_sp; record->stack_size = record->uctx.uc_stack.ss_size; #endif return record; } } class BOOST_CONTEXT_DECL continuation { private: friend struct detail::activation_record; template< typename Ctx, typename StackAlloc, typename Fn > friend class detail::capture_record; template< typename Ctx, typename StackAlloc, typename Fn > friend detail::activation_record * detail::create_context1( StackAlloc &&, Fn &&); template< typename Ctx, typename StackAlloc, typename Fn > friend detail::activation_record * detail::create_context2( preallocated, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend continuation callcc( std::allocator_arg_t, StackAlloc &&, Fn &&); template< typename StackAlloc, typename Fn > friend continuation callcc( std::allocator_arg_t, preallocated, StackAlloc &&, Fn &&); detail::activation_record * ptr_{ nullptr }; continuation( detail::activation_record * ptr) noexcept : ptr_{ ptr } { } public: continuation() = default; ~continuation() { if ( BOOST_UNLIKELY( nullptr != ptr_) && ! ptr_->main_ctx) { if ( BOOST_LIKELY( ! ptr_->terminated) ) { ptr_->force_unwind = true; ptr_->resume(); BOOST_ASSERT( ptr_->terminated); } ptr_->deallocate(); } } continuation( continuation const&) = delete; continuation & operator=( continuation const&) = delete; continuation( continuation && other) noexcept { swap( other); } continuation & operator=( continuation && other) noexcept { if ( BOOST_LIKELY( this != & other) ) { continuation tmp = std::move( other); swap( tmp); } return * this; } continuation resume() & { return std::move( * this).resume(); } continuation resume() && { #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume(); #else detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume(); #endif if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) { throw detail::forced_unwind{ ptr}; } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) { ptr = detail::activation_record::current()->ontop( ptr); detail::activation_record::current()->ontop = nullptr; } return { ptr }; } template< typename Fn > continuation resume_with( Fn && fn) & { return std::move( * this).resume_with( std::forward< Fn >( fn) ); } template< typename Fn > continuation resume_with( Fn && fn) && { #if defined(BOOST_NO_CXX14_STD_EXCHANGE) detail::activation_record * ptr = detail::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) ); #else detail::activation_record * ptr = std::exchange( ptr_, nullptr)->resume_with< continuation >( std::forward< Fn >( fn) ); #endif if ( BOOST_UNLIKELY( detail::activation_record::current()->force_unwind) ) { throw detail::forced_unwind{ ptr}; } else if ( BOOST_UNLIKELY( nullptr != detail::activation_record::current()->ontop) ) { ptr = detail::activation_record::current()->ontop( ptr); detail::activation_record::current()->ontop = nullptr; } return { ptr }; } explicit operator bool() const noexcept { return nullptr != ptr_ && ! ptr_->terminated; } bool operator!() const noexcept { return nullptr == ptr_ || ptr_->terminated; } bool operator<( continuation const& other) const noexcept { return ptr_ < other.ptr_; } #if !defined(BOOST_EMBTC) template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) { if ( nullptr != other.ptr_) { return os << other.ptr_; } else { return os << "{not-a-context}"; } } #else template< typename charT, class traitsT > friend std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other); #endif void swap( continuation & other) noexcept { std::swap( ptr_, other.ptr_); } }; #if defined(BOOST_EMBTC) template< typename charT, class traitsT > inline std::basic_ostream< charT, traitsT > & operator<<( std::basic_ostream< charT, traitsT > & os, continuation const& other) { if ( nullptr != other.ptr_) { return os << other.ptr_; } else { return os << "{not-a-context}"; } } #endif template< typename Fn, typename = detail::disable_overload< continuation, Fn > > continuation callcc( Fn && fn) { return callcc( std::allocator_arg, #if defined(BOOST_USE_SEGMENTED_STACKS) segmented_stack(), #else fixedsize_stack(), #endif std::forward< Fn >( fn) ); } template< typename StackAlloc, typename Fn > continuation callcc( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) { return continuation{ detail::create_context1< continuation >( std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume(); } template< typename StackAlloc, typename Fn > continuation callcc( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) { return continuation{ detail::create_context2< continuation >( palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) }.resume(); } inline void swap( continuation & l, continuation & r) noexcept { l.swap( r); } }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_CONTINUATION_H PK ��!\�ʁI< < preallocated.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_PREALLOCATED_H #define BOOST_CONTEXT_PREALLOCATED_H #include <cstddef> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { struct preallocated { void * sp; std::size_t size; stack_context sctx; preallocated( void * sp_, std::size_t size_, stack_context sctx_) noexcept : sp( sp_), size( size_), sctx( sctx_) { } }; }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_PREALLOCATED_H PK ��!\� h=� � stack_context.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_STACK_CONTEXT_H #define BOOST_CONTEXT_STACK_CONTEXT_H #include <cstddef> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { #if ! defined(BOOST_CONTEXT_NO_CXX11) struct BOOST_CONTEXT_DECL stack_context { # if defined(BOOST_USE_SEGMENTED_STACKS) typedef void * segments_context[BOOST_CONTEXT_SEGMENTS]; # endif std::size_t size{ 0 }; void * sp{ nullptr }; # if defined(BOOST_USE_SEGMENTED_STACKS) segments_context segments_ctx{}; # endif # if defined(BOOST_USE_VALGRIND) unsigned valgrind_stack_id{ 0 }; # endif }; #else struct BOOST_CONTEXT_DECL stack_context { # if defined(BOOST_USE_SEGMENTED_STACKS) typedef void * segments_context[BOOST_CONTEXT_SEGMENTS]; # endif std::size_t size; void * sp; # if defined(BOOST_USE_SEGMENTED_STACKS) segments_context segments_ctx; # endif # if defined(BOOST_USE_VALGRIND) unsigned valgrind_stack_id; # endif stack_context() : size( 0), sp( 0) # if defined(BOOST_USE_SEGMENTED_STACKS) , segments_ctx() # endif # if defined(BOOST_USE_VALGRIND) , valgrind_stack_id( 0) # endif {} }; #endif }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_STACK_CONTEXT_H PK ��!\37\ fixedsize_stack.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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_CONTEXT_FIXEDSIZE_H #define BOOST_CONTEXT_FIXEDSIZE_H #include <cstddef> #include <cstdlib> #include <new> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/context/detail/config.hpp> #include <boost/context/stack_context.hpp> #include <boost/context/stack_traits.hpp> #if defined(BOOST_CONTEXT_USE_MAP_STACK) extern "C" { #include <sys/mman.h> } #endif #if defined(BOOST_USE_VALGRIND) #include <valgrind/valgrind.h> #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace context { template< typename traitsT > class basic_fixedsize_stack { private: std::size_t size_; public: typedef traitsT traits_type; basic_fixedsize_stack( std::size_t size = traits_type::default_size() ) BOOST_NOEXCEPT_OR_NOTHROW : size_( size) { } stack_context allocate() { #if defined(BOOST_CONTEXT_USE_MAP_STACK) void * vp = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0); if ( vp == MAP_FAILED) { throw std::bad_alloc(); } #else void * vp = std::malloc( size_); if ( ! vp) { throw std::bad_alloc(); } #endif stack_context sctx; sctx.size = size_; sctx.sp = static_cast< char * >( vp) + sctx.size; #if defined(BOOST_USE_VALGRIND) sctx.valgrind_stack_id = VALGRIND_STACK_REGISTER( sctx.sp, vp); #endif return sctx; } void deallocate( stack_context & sctx) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT( sctx.sp); #if defined(BOOST_USE_VALGRIND) VALGRIND_STACK_DEREGISTER( sctx.valgrind_stack_id); #endif void * vp = static_cast< char * >( sctx.sp) - sctx.size; #if defined(BOOST_CONTEXT_USE_MAP_STACK) ::munmap( vp, sctx.size); #else std::free( vp); #endif } }; typedef basic_fixedsize_stack< stack_traits > fixedsize_stack; # if ! defined(BOOST_USE_SEGMENTED_STACKS) typedef fixedsize_stack default_stack; # endif }} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_CONTEXT_FIXEDSIZE_H PK ��!\X�Ǿ� � protected_fixedsize_stack.hppnu �[��� // Copyright Oliver Kowalke 2014. // 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/context/windows/protected_fixedsize_stack.hpp> #else # include <boost/context/posix/protected_fixedsize_stack.hpp> #endif PK �%"\�[��L �L default.hppnu �[��� /////////////////////////////////////////////////////////////////////////////// /// \file default.hpp /// Definintion of default_context, a default evaluation context for /// proto::eval() that uses Boost.Typeof to deduce return types /// of the built-in operators. // // Copyright 2008 Eric Niebler. 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_PROTO_CONTEXT_DEFAULT_HPP_EAN_01_08_2007 #define BOOST_PROTO_CONTEXT_DEFAULT_HPP_EAN_01_08_2007 #include <boost/config.hpp> #include <boost/preprocessor/arithmetic/add.hpp> #include <boost/preprocessor/arithmetic/sub.hpp> #include <boost/preprocessor/iteration/iterate.hpp> #include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/repetition/enum_shifted.hpp> #include <boost/utility/result_of.hpp> #include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_function.hpp> #include <boost/type_traits/remove_reference.hpp> #include <boost/type_traits/is_member_pointer.hpp> #include <boost/type_traits/is_member_object_pointer.hpp> #include <boost/type_traits/is_member_function_pointer.hpp> #include <boost/proto/proto_fwd.hpp> #include <boost/proto/tags.hpp> #include <boost/proto/eval.hpp> #include <boost/proto/traits.hpp> // for proto::child_c() #include <boost/proto/detail/decltype.hpp> namespace boost { namespace proto { /// INTERNAL ONLY /// #define UNREF(x) typename boost::remove_reference<x>::type namespace context { template< typename Expr , typename Context , typename Tag // = typename Expr::proto_tag , long Arity // = Expr::proto_arity_c > struct default_eval {}; template<typename Expr, typename Context> struct default_eval<Expr, Context, tag::terminal, 0> { typedef typename proto::result_of::value<Expr &>::type result_type; result_type operator ()(Expr &expr, Context &) const { return proto::value(expr); } }; /// INTERNAL ONLY /// #define BOOST_PROTO_UNARY_DEFAULT_EVAL(OP, TAG, MAKE) \ template<typename Expr, typename Context> \ struct default_eval<Expr, Context, TAG, 1> \ { \ private: \ typedef typename proto::result_of::child_c<Expr, 0>::type e0; \ typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; \ public: \ BOOST_PROTO_DECLTYPE_(OP proto::detail::MAKE<r0>(), result_type) \ result_type operator ()(Expr &expr, Context &ctx) const \ { \ return OP proto::eval(proto::child_c<0>(expr), ctx); \ } \ }; \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_BINARY_DEFAULT_EVAL(OP, TAG, LMAKE, RMAKE) \ template<typename Expr, typename Context> \ struct default_eval<Expr, Context, TAG, 2> \ { \ private: \ typedef typename proto::result_of::child_c<Expr, 0>::type e0; \ typedef typename proto::result_of::child_c<Expr, 1>::type e1; \ typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; \ typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1; \ public: \ BOOST_PROTO_DECLTYPE_( \ proto::detail::LMAKE<r0>() OP proto::detail::RMAKE<r1>() \ , result_type \ ) \ result_type operator ()(Expr &expr, Context &ctx) const \ { \ return proto::eval( \ proto::child_c<0>(expr), ctx) OP proto::eval(proto::child_c<1>(expr) \ , ctx \ ); \ } \ }; \ /**/ BOOST_PROTO_UNARY_DEFAULT_EVAL(+, proto::tag::unary_plus, make) BOOST_PROTO_UNARY_DEFAULT_EVAL(-, proto::tag::negate, make) BOOST_PROTO_UNARY_DEFAULT_EVAL(*, proto::tag::dereference, make) BOOST_PROTO_UNARY_DEFAULT_EVAL(~, proto::tag::complement, make) BOOST_PROTO_UNARY_DEFAULT_EVAL(&, proto::tag::address_of, make) BOOST_PROTO_UNARY_DEFAULT_EVAL(!, proto::tag::logical_not, make) BOOST_PROTO_UNARY_DEFAULT_EVAL(++, proto::tag::pre_inc, make_mutable) BOOST_PROTO_UNARY_DEFAULT_EVAL(--, proto::tag::pre_dec, make_mutable) BOOST_PROTO_BINARY_DEFAULT_EVAL(<<, proto::tag::shift_left, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(>>, proto::tag::shift_right, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(*, proto::tag::multiplies, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(/, proto::tag::divides, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(%, proto::tag::modulus, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(+, proto::tag::plus, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(-, proto::tag::minus, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(<, proto::tag::less, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(>, proto::tag::greater, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(<=, proto::tag::less_equal, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(>=, proto::tag::greater_equal, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(==, proto::tag::equal_to, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(!=, proto::tag::not_equal_to, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(||, proto::tag::logical_or, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(&&, proto::tag::logical_and, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(&, proto::tag::bitwise_and, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(|, proto::tag::bitwise_or, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(^, proto::tag::bitwise_xor, make, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(=, proto::tag::assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(<<=, proto::tag::shift_left_assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(>>=, proto::tag::shift_right_assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(*=, proto::tag::multiplies_assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(/=, proto::tag::divides_assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(%=, proto::tag::modulus_assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(+=, proto::tag::plus_assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(-=, proto::tag::minus_assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(&=, proto::tag::bitwise_and_assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(|=, proto::tag::bitwise_or_assign, make_mutable, make) BOOST_PROTO_BINARY_DEFAULT_EVAL(^=, proto::tag::bitwise_xor_assign, make_mutable, make) #undef BOOST_PROTO_UNARY_DEFAULT_EVAL #undef BOOST_PROTO_BINARY_DEFAULT_EVAL /// INTERNAL ONLY template<typename Expr, typename Context> struct is_member_function_eval : is_member_function_pointer< typename detail::uncvref< typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c<Expr, 1>::type >::type , Context >::type >::type > {}; /// INTERNAL ONLY template<typename Expr, typename Context, bool IsMemFunCall> struct memfun_eval { private: typedef typename result_of::child_c<Expr, 0>::type e0; typedef typename result_of::child_c<Expr, 1>::type e1; typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1; public: typedef typename detail::mem_ptr_fun<r0, r1>::result_type result_type; result_type operator ()(Expr &expr, Context &ctx) const { return detail::mem_ptr_fun<r0, r1>()( proto::eval(proto::child_c<0>(expr), ctx) , proto::eval(proto::child_c<1>(expr), ctx) ); } }; /// INTERNAL ONLY template<typename Expr, typename Context> struct memfun_eval<Expr, Context, true> { private: typedef typename result_of::child_c<Expr, 0>::type e0; typedef typename result_of::child_c<Expr, 1>::type e1; typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1; public: typedef detail::memfun<r0, r1> result_type; result_type const operator ()(Expr &expr, Context &ctx) const { return detail::memfun<r0, r1>( proto::eval(proto::child_c<0>(expr), ctx) , proto::eval(proto::child_c<1>(expr), ctx) ); } }; template<typename Expr, typename Context> struct default_eval<Expr, Context, tag::mem_ptr, 2> : memfun_eval<Expr, Context, is_member_function_eval<Expr, Context>::value> {}; // Handle post-increment specially. template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::post_inc, 1> { private: typedef typename proto::result_of::child_c<Expr, 0>::type e0; typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; public: BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable<r0>() ++, result_type) result_type operator ()(Expr &expr, Context &ctx) const { return proto::eval(proto::child_c<0>(expr), ctx) ++; } }; // Handle post-decrement specially. template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::post_dec, 1> { private: typedef typename proto::result_of::child_c<Expr, 0>::type e0; typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; public: BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable<r0>() --, result_type) result_type operator ()(Expr &expr, Context &ctx) const { return proto::eval(proto::child_c<0>(expr), ctx) --; } }; // Handle subscript specially. template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::subscript, 2> { private: typedef typename proto::result_of::child_c<Expr, 0>::type e0; typedef typename proto::result_of::child_c<Expr, 1>::type e1; typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1; public: BOOST_PROTO_DECLTYPE_(proto::detail::make_subscriptable<r0>()[proto::detail::make<r1>()], result_type) result_type operator ()(Expr &expr, Context &ctx) const { return proto::eval(proto::child_c<0>(expr), ctx)[proto::eval(proto::child_c<1>(expr), ctx)]; } }; // Handle if_else_ specially. template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::if_else_, 3> { private: typedef typename proto::result_of::child_c<Expr, 0>::type e0; typedef typename proto::result_of::child_c<Expr, 1>::type e1; typedef typename proto::result_of::child_c<Expr, 2>::type e2; typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1; typedef typename proto::result_of::eval<UNREF(e2), Context>::type r2; public: BOOST_PROTO_DECLTYPE_( proto::detail::make<r0>() ? proto::detail::make<r1>() : proto::detail::make<r2>() , result_type ) result_type operator ()(Expr &expr, Context &ctx) const { return proto::eval(proto::child_c<0>(expr), ctx) ? proto::eval(proto::child_c<1>(expr), ctx) : proto::eval(proto::child_c<2>(expr), ctx); } }; // Handle comma specially. template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::comma, 2> { private: typedef typename proto::result_of::child_c<Expr, 0>::type e0; typedef typename proto::result_of::child_c<Expr, 1>::type e1; typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1; public: typedef typename proto::detail::comma_result<r0, r1>::type result_type; result_type operator ()(Expr &expr, Context &ctx) const { return proto::eval(proto::child_c<0>(expr), ctx), proto::eval(proto::child_c<1>(expr), ctx); } }; // Handle function specially #define BOOST_PROTO_DEFAULT_EVAL_TYPE(Z, N, DATA) \ typename proto::result_of::eval< \ typename remove_reference< \ typename proto::result_of::child_c<DATA, N>::type \ >::type \ , Context \ >::type \ /**/ #define BOOST_PROTO_DEFAULT_EVAL(Z, N, DATA) \ proto::eval(proto::child_c<N>(DATA), context) \ /**/ template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 1> { typedef typename proto::detail::result_of_fixup< BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 0, Expr) >::type function_type; typedef typename BOOST_PROTO_RESULT_OF<function_type()>::type result_type; result_type operator ()(Expr &expr, Context &context) const { return BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)(); } }; template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 2> { typedef typename proto::detail::result_of_fixup< BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 0, Expr) >::type function_type; typedef typename detail::result_of_< function_type(BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 1, Expr)) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke( expr , context , is_member_function_pointer<function_type>() , is_member_object_pointer<function_type>() ); } private: result_type invoke(Expr &expr, Context &context, mpl::false_, mpl::false_) const { return BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)(BOOST_PROTO_DEFAULT_EVAL(~, 1, expr)); } result_type invoke(Expr &expr, Context &context, mpl::true_, mpl::false_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (BOOST_PROTO_DEFAULT_EVAL(~, 1, expr))) ->* BOOST_PROTO_DEFAULT_EVAL(~, 0, expr) )(); } result_type invoke(Expr &expr, Context &context, mpl::false_, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (BOOST_PROTO_DEFAULT_EVAL(~, 1, expr))) ->* BOOST_PROTO_DEFAULT_EVAL(~, 0, expr) ); } }; // Additional specialization are generated by the preprocessor #include <boost/proto/context/detail/default_eval.hpp> #undef BOOST_PROTO_DEFAULT_EVAL_TYPE #undef BOOST_PROTO_DEFAULT_EVAL /// default_context /// struct default_context { /// default_context::eval /// template<typename Expr, typename ThisContext = default_context const> struct eval : default_eval<Expr, ThisContext> {}; }; } // namespace context }} // namespace boost::proto #undef UNREF #endif PK �%"\G �(+ + null.hppnu �[��� /////////////////////////////////////////////////////////////////////////////// /// \file null.hpp /// Definintion of null_context\<\>, an evaluation context for /// proto::eval() that simply evaluates each child expression, doesn't /// combine the results at all, and returns void. // // Copyright 2008 Eric Niebler. 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_PROTO_CONTEXT_NULL_HPP_EAN_06_24_2007 #define BOOST_PROTO_CONTEXT_NULL_HPP_EAN_06_24_2007 #include <boost/preprocessor/iteration/iterate.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/proto/proto_fwd.hpp> #include <boost/proto/eval.hpp> #include <boost/proto/traits.hpp> namespace boost { namespace proto { namespace context { template< typename Expr , typename Context , long Arity // = Expr::proto_arity_c > struct null_eval {}; template<typename Expr, typename Context> struct null_eval<Expr, Context, 0> { typedef void result_type; void operator()(Expr &, Context &) const {} }; // Additional specializations generated by the preprocessor #include <boost/proto/context/detail/null_eval.hpp> /// null_context /// struct null_context { /// null_context::eval /// template<typename Expr, typename ThisContext = null_context const> struct eval : null_eval<Expr, ThisContext> {}; }; }}} #endif PK �%"\��`3�W �W % detail/preprocessed/callable_eval.hppnu �[��� /////////////////////////////////////////////////////////////////////////////// /// \file callable_eval.hpp /// Contains specializations of the callable_eval\<\> class template. // // Copyright 2008 Eric Niebler. 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) namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 1> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 1> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) ); } }; } namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 2> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) , proto::child_c< 1>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 2> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename proto::result_of::child_c< Expr const &, 1>::type child1; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 , child1 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) , proto::child_c< 1>( expr) ); } }; } namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 3> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) , proto::child_c< 1>( sexpr_) , proto::child_c< 2>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 3> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename proto::result_of::child_c< Expr const &, 1>::type child1; typedef typename proto::result_of::child_c< Expr const &, 2>::type child2; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 , child1 , child2 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) , proto::child_c< 1>( expr) , proto::child_c< 2>( expr) ); } }; } namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 4> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) , proto::child_c< 1>( sexpr_) , proto::child_c< 2>( sexpr_) , proto::child_c< 3>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 4> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename proto::result_of::child_c< Expr const &, 1>::type child1; typedef typename proto::result_of::child_c< Expr const &, 2>::type child2; typedef typename proto::result_of::child_c< Expr const &, 3>::type child3; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 , child1 , child2 , child3 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) , proto::child_c< 1>( expr) , proto::child_c< 2>( expr) , proto::child_c< 3>( expr) ); } }; } namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 5> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) , proto::child_c< 1>( sexpr_) , proto::child_c< 2>( sexpr_) , proto::child_c< 3>( sexpr_) , proto::child_c< 4>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 5> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename proto::result_of::child_c< Expr const &, 1>::type child1; typedef typename proto::result_of::child_c< Expr const &, 2>::type child2; typedef typename proto::result_of::child_c< Expr const &, 3>::type child3; typedef typename proto::result_of::child_c< Expr const &, 4>::type child4; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 , child1 , child2 , child3 , child4 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) , proto::child_c< 1>( expr) , proto::child_c< 2>( expr) , proto::child_c< 3>( expr) , proto::child_c< 4>( expr) ); } }; } namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 6> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) , proto::child_c< 1>( sexpr_) , proto::child_c< 2>( sexpr_) , proto::child_c< 3>( sexpr_) , proto::child_c< 4>( sexpr_) , proto::child_c< 5>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 6> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename proto::result_of::child_c< Expr const &, 1>::type child1; typedef typename proto::result_of::child_c< Expr const &, 2>::type child2; typedef typename proto::result_of::child_c< Expr const &, 3>::type child3; typedef typename proto::result_of::child_c< Expr const &, 4>::type child4; typedef typename proto::result_of::child_c< Expr const &, 5>::type child5; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 , child1 , child2 , child3 , child4 , child5 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) , proto::child_c< 1>( expr) , proto::child_c< 2>( expr) , proto::child_c< 3>( expr) , proto::child_c< 4>( expr) , proto::child_c< 5>( expr) ); } }; } namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 7> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) , proto::child_c< 1>( sexpr_) , proto::child_c< 2>( sexpr_) , proto::child_c< 3>( sexpr_) , proto::child_c< 4>( sexpr_) , proto::child_c< 5>( sexpr_) , proto::child_c< 6>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 7> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename proto::result_of::child_c< Expr const &, 1>::type child1; typedef typename proto::result_of::child_c< Expr const &, 2>::type child2; typedef typename proto::result_of::child_c< Expr const &, 3>::type child3; typedef typename proto::result_of::child_c< Expr const &, 4>::type child4; typedef typename proto::result_of::child_c< Expr const &, 5>::type child5; typedef typename proto::result_of::child_c< Expr const &, 6>::type child6; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 , child1 , child2 , child3 , child4 , child5 , child6 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) , proto::child_c< 1>( expr) , proto::child_c< 2>( expr) , proto::child_c< 3>( expr) , proto::child_c< 4>( expr) , proto::child_c< 5>( expr) , proto::child_c< 6>( expr) ); } }; } namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 8> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) , proto::child_c< 1>( sexpr_) , proto::child_c< 2>( sexpr_) , proto::child_c< 3>( sexpr_) , proto::child_c< 4>( sexpr_) , proto::child_c< 5>( sexpr_) , proto::child_c< 6>( sexpr_) , proto::child_c< 7>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 8> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename proto::result_of::child_c< Expr const &, 1>::type child1; typedef typename proto::result_of::child_c< Expr const &, 2>::type child2; typedef typename proto::result_of::child_c< Expr const &, 3>::type child3; typedef typename proto::result_of::child_c< Expr const &, 4>::type child4; typedef typename proto::result_of::child_c< Expr const &, 5>::type child5; typedef typename proto::result_of::child_c< Expr const &, 6>::type child6; typedef typename proto::result_of::child_c< Expr const &, 7>::type child7; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 , child1 , child2 , child3 , child4 , child5 , child6 , child7 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) , proto::child_c< 1>( expr) , proto::child_c< 2>( expr) , proto::child_c< 3>( expr) , proto::child_c< 4>( expr) , proto::child_c< 5>( expr) , proto::child_c< 6>( expr) , proto::child_c< 7>( expr) ); } }; } namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 9> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) , proto::child_c< 1>( sexpr_) , proto::child_c< 2>( sexpr_) , proto::child_c< 3>( sexpr_) , proto::child_c< 4>( sexpr_) , proto::child_c< 5>( sexpr_) , proto::child_c< 6>( sexpr_) , proto::child_c< 7>( sexpr_) , proto::child_c< 8>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 9> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename proto::result_of::child_c< Expr const &, 1>::type child1; typedef typename proto::result_of::child_c< Expr const &, 2>::type child2; typedef typename proto::result_of::child_c< Expr const &, 3>::type child3; typedef typename proto::result_of::child_c< Expr const &, 4>::type child4; typedef typename proto::result_of::child_c< Expr const &, 5>::type child5; typedef typename proto::result_of::child_c< Expr const &, 6>::type child6; typedef typename proto::result_of::child_c< Expr const &, 7>::type child7; typedef typename proto::result_of::child_c< Expr const &, 8>::type child8; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 , child1 , child2 , child3 , child4 , child5 , child6 , child7 , child8 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) , proto::child_c< 1>( expr) , proto::child_c< 2>( expr) , proto::child_c< 3>( expr) , proto::child_c< 4>( expr) , proto::child_c< 5>( expr) , proto::child_c< 6>( expr) , proto::child_c< 7>( expr) , proto::child_c< 8>( expr) ); } }; } namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 10> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ , proto::child_c< 0>( sexpr_) , proto::child_c< 1>( sexpr_) , proto::child_c< 2>( sexpr_) , proto::child_c< 3>( sexpr_) , proto::child_c< 4>( sexpr_) , proto::child_c< 5>( sexpr_) , proto::child_c< 6>( sexpr_) , proto::child_c< 7>( sexpr_) , proto::child_c< 8>( sexpr_) , proto::child_c< 9>( sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { template<typename Expr, typename Context> struct callable_eval<Expr, Context, 10> { typedef typename proto::result_of::child_c< Expr const &, 0>::type child0; typedef typename proto::result_of::child_c< Expr const &, 1>::type child1; typedef typename proto::result_of::child_c< Expr const &, 2>::type child2; typedef typename proto::result_of::child_c< Expr const &, 3>::type child3; typedef typename proto::result_of::child_c< Expr const &, 4>::type child4; typedef typename proto::result_of::child_c< Expr const &, 5>::type child5; typedef typename proto::result_of::child_c< Expr const &, 6>::type child6; typedef typename proto::result_of::child_c< Expr const &, 7>::type child7; typedef typename proto::result_of::child_c< Expr const &, 8>::type child8; typedef typename proto::result_of::child_c< Expr const &, 9>::type child9; typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag , child0 , child1 , child2 , child3 , child4 , child5 , child6 , child7 , child8 , child9 ) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() , proto::child_c< 0>( expr) , proto::child_c< 1>( expr) , proto::child_c< 2>( expr) , proto::child_c< 3>( expr) , proto::child_c< 4>( expr) , proto::child_c< 5>( expr) , proto::child_c< 6>( expr) , proto::child_c< 7>( expr) , proto::child_c< 8>( expr) , proto::child_c< 9>( expr) ); } }; } PK �%"\_yf�S S $ detail/preprocessed/default_eval.hppnu �[��� /////////////////////////////////////////////////////////////////////////////// /// \file default_eval.hpp /// Contains specializations of the default_eval\<\> class template. // // Copyright 2008 Eric Niebler. 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) template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 3> { typedef typename proto::detail::result_of_fixup< typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 0>::type >::type , Context >::type >::type function_type; typedef typename BOOST_PROTO_RESULT_OF< function_type(typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 1>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 2>::type >::type , Context >::type) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke(expr, context, is_member_function_pointer<function_type>()); } private: result_type invoke(Expr &expr, Context &context, mpl::false_) const { return proto::eval(proto::child_c< 0>( expr), context)( proto::eval(proto::child_c< 1>( expr), context) , proto::eval(proto::child_c< 2>( expr), context) ); } result_type invoke(Expr &expr, Context &context, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (proto::eval(proto::child_c< 1>( expr), context))) ->* proto::eval(proto::child_c< 0>( expr), context) )(proto::eval(proto::child_c< 2>( expr), context)); } }; template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 4> { typedef typename proto::detail::result_of_fixup< typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 0>::type >::type , Context >::type >::type function_type; typedef typename BOOST_PROTO_RESULT_OF< function_type(typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 1>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 2>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 3>::type >::type , Context >::type) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke(expr, context, is_member_function_pointer<function_type>()); } private: result_type invoke(Expr &expr, Context &context, mpl::false_) const { return proto::eval(proto::child_c< 0>( expr), context)( proto::eval(proto::child_c< 1>( expr), context) , proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) ); } result_type invoke(Expr &expr, Context &context, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (proto::eval(proto::child_c< 1>( expr), context))) ->* proto::eval(proto::child_c< 0>( expr), context) )(proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context)); } }; template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 5> { typedef typename proto::detail::result_of_fixup< typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 0>::type >::type , Context >::type >::type function_type; typedef typename BOOST_PROTO_RESULT_OF< function_type(typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 1>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 2>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 3>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 4>::type >::type , Context >::type) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke(expr, context, is_member_function_pointer<function_type>()); } private: result_type invoke(Expr &expr, Context &context, mpl::false_) const { return proto::eval(proto::child_c< 0>( expr), context)( proto::eval(proto::child_c< 1>( expr), context) , proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) ); } result_type invoke(Expr &expr, Context &context, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (proto::eval(proto::child_c< 1>( expr), context))) ->* proto::eval(proto::child_c< 0>( expr), context) )(proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context)); } }; template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 6> { typedef typename proto::detail::result_of_fixup< typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 0>::type >::type , Context >::type >::type function_type; typedef typename BOOST_PROTO_RESULT_OF< function_type(typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 1>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 2>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 3>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 4>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 5>::type >::type , Context >::type) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke(expr, context, is_member_function_pointer<function_type>()); } private: result_type invoke(Expr &expr, Context &context, mpl::false_) const { return proto::eval(proto::child_c< 0>( expr), context)( proto::eval(proto::child_c< 1>( expr), context) , proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context) ); } result_type invoke(Expr &expr, Context &context, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (proto::eval(proto::child_c< 1>( expr), context))) ->* proto::eval(proto::child_c< 0>( expr), context) )(proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context)); } }; template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 7> { typedef typename proto::detail::result_of_fixup< typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 0>::type >::type , Context >::type >::type function_type; typedef typename BOOST_PROTO_RESULT_OF< function_type(typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 1>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 2>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 3>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 4>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 5>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 6>::type >::type , Context >::type) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke(expr, context, is_member_function_pointer<function_type>()); } private: result_type invoke(Expr &expr, Context &context, mpl::false_) const { return proto::eval(proto::child_c< 0>( expr), context)( proto::eval(proto::child_c< 1>( expr), context) , proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context) , proto::eval(proto::child_c< 6>( expr), context) ); } result_type invoke(Expr &expr, Context &context, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (proto::eval(proto::child_c< 1>( expr), context))) ->* proto::eval(proto::child_c< 0>( expr), context) )(proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context) , proto::eval(proto::child_c< 6>( expr), context)); } }; template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 8> { typedef typename proto::detail::result_of_fixup< typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 0>::type >::type , Context >::type >::type function_type; typedef typename BOOST_PROTO_RESULT_OF< function_type(typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 1>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 2>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 3>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 4>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 5>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 6>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 7>::type >::type , Context >::type) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke(expr, context, is_member_function_pointer<function_type>()); } private: result_type invoke(Expr &expr, Context &context, mpl::false_) const { return proto::eval(proto::child_c< 0>( expr), context)( proto::eval(proto::child_c< 1>( expr), context) , proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context) , proto::eval(proto::child_c< 6>( expr), context) , proto::eval(proto::child_c< 7>( expr), context) ); } result_type invoke(Expr &expr, Context &context, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (proto::eval(proto::child_c< 1>( expr), context))) ->* proto::eval(proto::child_c< 0>( expr), context) )(proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context) , proto::eval(proto::child_c< 6>( expr), context) , proto::eval(proto::child_c< 7>( expr), context)); } }; template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 9> { typedef typename proto::detail::result_of_fixup< typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 0>::type >::type , Context >::type >::type function_type; typedef typename BOOST_PROTO_RESULT_OF< function_type(typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 1>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 2>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 3>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 4>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 5>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 6>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 7>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 8>::type >::type , Context >::type) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke(expr, context, is_member_function_pointer<function_type>()); } private: result_type invoke(Expr &expr, Context &context, mpl::false_) const { return proto::eval(proto::child_c< 0>( expr), context)( proto::eval(proto::child_c< 1>( expr), context) , proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context) , proto::eval(proto::child_c< 6>( expr), context) , proto::eval(proto::child_c< 7>( expr), context) , proto::eval(proto::child_c< 8>( expr), context) ); } result_type invoke(Expr &expr, Context &context, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (proto::eval(proto::child_c< 1>( expr), context))) ->* proto::eval(proto::child_c< 0>( expr), context) )(proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context) , proto::eval(proto::child_c< 6>( expr), context) , proto::eval(proto::child_c< 7>( expr), context) , proto::eval(proto::child_c< 8>( expr), context)); } }; template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, 10> { typedef typename proto::detail::result_of_fixup< typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 0>::type >::type , Context >::type >::type function_type; typedef typename BOOST_PROTO_RESULT_OF< function_type(typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 1>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 2>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 3>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 4>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 5>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 6>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 7>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 8>::type >::type , Context >::type , typename proto::result_of::eval< typename remove_reference< typename proto::result_of::child_c< Expr, 9>::type >::type , Context >::type) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke(expr, context, is_member_function_pointer<function_type>()); } private: result_type invoke(Expr &expr, Context &context, mpl::false_) const { return proto::eval(proto::child_c< 0>( expr), context)( proto::eval(proto::child_c< 1>( expr), context) , proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context) , proto::eval(proto::child_c< 6>( expr), context) , proto::eval(proto::child_c< 7>( expr), context) , proto::eval(proto::child_c< 8>( expr), context) , proto::eval(proto::child_c< 9>( expr), context) ); } result_type invoke(Expr &expr, Context &context, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (proto::eval(proto::child_c< 1>( expr), context))) ->* proto::eval(proto::child_c< 0>( expr), context) )(proto::eval(proto::child_c< 2>( expr), context) , proto::eval(proto::child_c< 3>( expr), context) , proto::eval(proto::child_c< 4>( expr), context) , proto::eval(proto::child_c< 5>( expr), context) , proto::eval(proto::child_c< 6>( expr), context) , proto::eval(proto::child_c< 7>( expr), context) , proto::eval(proto::child_c< 8>( expr), context) , proto::eval(proto::child_c< 9>( expr), context)); } }; PK �%"\�!�� � ! detail/preprocessed/null_eval.hppnu �[��� /////////////////////////////////////////////////////////////////////////////// /// \file null_eval.hpp /// Contains specializations of the null_eval\<\> class template. // // Copyright 2008 Eric Niebler. 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) template<typename Expr, typename Context> struct null_eval<Expr, Context, 1> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); } }; template<typename Expr, typename Context> struct null_eval<Expr, Context, 2> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); proto::eval(proto::child_c< 1>(expr), ctx); } }; template<typename Expr, typename Context> struct null_eval<Expr, Context, 3> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); proto::eval(proto::child_c< 1>(expr), ctx); proto::eval(proto::child_c< 2>(expr), ctx); } }; template<typename Expr, typename Context> struct null_eval<Expr, Context, 4> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); proto::eval(proto::child_c< 1>(expr), ctx); proto::eval(proto::child_c< 2>(expr), ctx); proto::eval(proto::child_c< 3>(expr), ctx); } }; template<typename Expr, typename Context> struct null_eval<Expr, Context, 5> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); proto::eval(proto::child_c< 1>(expr), ctx); proto::eval(proto::child_c< 2>(expr), ctx); proto::eval(proto::child_c< 3>(expr), ctx); proto::eval(proto::child_c< 4>(expr), ctx); } }; template<typename Expr, typename Context> struct null_eval<Expr, Context, 6> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); proto::eval(proto::child_c< 1>(expr), ctx); proto::eval(proto::child_c< 2>(expr), ctx); proto::eval(proto::child_c< 3>(expr), ctx); proto::eval(proto::child_c< 4>(expr), ctx); proto::eval(proto::child_c< 5>(expr), ctx); } }; template<typename Expr, typename Context> struct null_eval<Expr, Context, 7> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); proto::eval(proto::child_c< 1>(expr), ctx); proto::eval(proto::child_c< 2>(expr), ctx); proto::eval(proto::child_c< 3>(expr), ctx); proto::eval(proto::child_c< 4>(expr), ctx); proto::eval(proto::child_c< 5>(expr), ctx); proto::eval(proto::child_c< 6>(expr), ctx); } }; template<typename Expr, typename Context> struct null_eval<Expr, Context, 8> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); proto::eval(proto::child_c< 1>(expr), ctx); proto::eval(proto::child_c< 2>(expr), ctx); proto::eval(proto::child_c< 3>(expr), ctx); proto::eval(proto::child_c< 4>(expr), ctx); proto::eval(proto::child_c< 5>(expr), ctx); proto::eval(proto::child_c< 6>(expr), ctx); proto::eval(proto::child_c< 7>(expr), ctx); } }; template<typename Expr, typename Context> struct null_eval<Expr, Context, 9> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); proto::eval(proto::child_c< 1>(expr), ctx); proto::eval(proto::child_c< 2>(expr), ctx); proto::eval(proto::child_c< 3>(expr), ctx); proto::eval(proto::child_c< 4>(expr), ctx); proto::eval(proto::child_c< 5>(expr), ctx); proto::eval(proto::child_c< 6>(expr), ctx); proto::eval(proto::child_c< 7>(expr), ctx); proto::eval(proto::child_c< 8>(expr), ctx); } }; template<typename Expr, typename Context> struct null_eval<Expr, Context, 10> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { proto::eval(proto::child_c< 0>(expr), ctx); proto::eval(proto::child_c< 1>(expr), ctx); proto::eval(proto::child_c< 2>(expr), ctx); proto::eval(proto::child_c< 3>(expr), ctx); proto::eval(proto::child_c< 4>(expr), ctx); proto::eval(proto::child_c< 5>(expr), ctx); proto::eval(proto::child_c< 6>(expr), ctx); proto::eval(proto::child_c< 7>(expr), ctx); proto::eval(proto::child_c< 8>(expr), ctx); proto::eval(proto::child_c< 9>(expr), ctx); } }; PK �%"\Lk��� � detail/callable_eval.hppnu �[��� #if !defined(BOOST_PROTO_DONT_USE_PREPROCESSED_FILES) #include <boost/proto/context/detail/preprocessed/callable_eval.hpp> #elif !defined(BOOST_PP_IS_ITERATING) #define BOOST_PROTO_CHILD_N_TYPE(Z, N, Expr) \ typedef typename proto::result_of::child_c<Expr const &, N>::type BOOST_PP_CAT(child, N); \ /**/ #define BOOST_PROTO_CHILD_N(Z, N, expr) \ proto::child_c<N>(expr) \ /**/ #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) #pragma wave option(preserve: 2, line: 0, output: "preprocessed/callable_eval.hpp") #endif /////////////////////////////////////////////////////////////////////////////// /// \file callable_eval.hpp /// Contains specializations of the callable_eval\<\> class template. // // Copyright 2008 Eric Niebler. 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) #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) #pragma wave option(preserve: 1) #endif #define BOOST_PP_ITERATION_PARAMS_1 \ (3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/context/detail/callable_eval.hpp>)) #include BOOST_PP_ITERATE() #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) #pragma wave option(output: null) #endif #undef BOOST_PROTO_CHILD_N_TYPE #undef BOOST_PROTO_CHILD_N #else #define N BOOST_PP_ITERATION() namespace detail { template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, N> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_( stag_ BOOST_PP_ENUM_TRAILING(N, BOOST_PROTO_CHILD_N, sexpr_) ), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { /// \brief A BinaryFunction that accepts a Proto expression and a /// callable context and calls the context with the expression tag /// and children as arguments, effectively fanning the expression /// out. /// /// <tt>callable_eval\<\></tt> requires that \c Context is a /// PolymorphicFunctionObject that can be invoked with \c Expr's /// tag and children as expressions, as follows: /// /// \code /// context(Expr::proto_tag(), child_c\<0\>(expr), child_c\<1\>(expr), ...) /// \endcode template<typename Expr, typename Context> struct callable_eval<Expr, Context, N> { BOOST_PP_REPEAT(N, BOOST_PROTO_CHILD_N_TYPE, Expr) typedef typename BOOST_PROTO_RESULT_OF< Context( typename Expr::proto_tag BOOST_PP_ENUM_TRAILING_PARAMS(N, child) ) >::type result_type; /// \param expr The current expression /// \param context The callable evaluation context /// \return <tt>context(Expr::proto_tag(), child_c\<0\>(expr), child_c\<1\>(expr), ...)</tt> result_type operator ()(Expr &expr, Context &context) const { return context( typename Expr::proto_tag() BOOST_PP_ENUM_TRAILING(N, BOOST_PROTO_CHILD_N, expr) ); } }; } #undef N #endif PK �%"\�A`}� � detail/default_eval.hppnu �[��� #if !defined(BOOST_PROTO_DONT_USE_PREPROCESSED_FILES) #include <boost/proto/context/detail/preprocessed/default_eval.hpp> #elif !defined(BOOST_PP_IS_ITERATING) #define BOOST_PROTO_DEFAULT_EVAL_SHIFTED(Z, M, DATA) \ BOOST_PROTO_DEFAULT_EVAL(Z, BOOST_PP_ADD(M, 2), DATA) \ /**/ #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) #pragma wave option(preserve: 2, line: 0, output: "preprocessed/default_eval.hpp") #endif /////////////////////////////////////////////////////////////////////////////// /// \file default_eval.hpp /// Contains specializations of the default_eval\<\> class template. // // Copyright 2008 Eric Niebler. 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) #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) #pragma wave option(preserve: 1) #endif #define BOOST_PP_ITERATION_PARAMS_1 \ (3, (3, BOOST_PROTO_MAX_ARITY, <boost/proto/context/detail/default_eval.hpp>)) #include BOOST_PP_ITERATE() #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) #pragma wave option(output: null) #endif #undef BOOST_PROTO_DEFAULT_EVAL_SHIFTED #else #define N BOOST_PP_ITERATION() template<typename Expr, typename Context> struct default_eval<Expr, Context, proto::tag::function, N> { typedef typename proto::detail::result_of_fixup< BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 0, Expr) >::type function_type; typedef typename BOOST_PROTO_RESULT_OF< function_type(BOOST_PP_ENUM_SHIFTED(N, BOOST_PROTO_DEFAULT_EVAL_TYPE, Expr)) >::type result_type; result_type operator ()(Expr &expr, Context &context) const { return this->invoke(expr, context, is_member_function_pointer<function_type>()); } private: result_type invoke(Expr &expr, Context &context, mpl::false_) const { return BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)( BOOST_PP_ENUM_SHIFTED(N, BOOST_PROTO_DEFAULT_EVAL, expr) ); } result_type invoke(Expr &expr, Context &context, mpl::true_) const { BOOST_PROTO_USE_GET_POINTER(); typedef typename detail::class_member_traits<function_type>::class_type class_type; return ( BOOST_PROTO_GET_POINTER(class_type, (BOOST_PROTO_DEFAULT_EVAL(~, 1, expr))) ->* BOOST_PROTO_DEFAULT_EVAL(~, 0, expr) )(BOOST_PP_ENUM(BOOST_PP_SUB(N, 2), BOOST_PROTO_DEFAULT_EVAL_SHIFTED, expr)); } }; #undef N #endif PK �%"\-� � detail/null_eval.hppnu �[��� #if !defined(BOOST_PROTO_DONT_USE_PREPROCESSED_FILES) #include <boost/proto/context/detail/preprocessed/null_eval.hpp> #elif !defined(BOOST_PP_IS_ITERATING) #define BOOST_PROTO_EVAL_N(Z, N, DATA) \ proto::eval(proto::child_c<N>(expr), ctx); \ /**/ #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) #pragma wave option(preserve: 2, line: 0, output: "preprocessed/null_eval.hpp") #endif /////////////////////////////////////////////////////////////////////////////// /// \file null_eval.hpp /// Contains specializations of the null_eval\<\> class template. // // Copyright 2008 Eric Niebler. 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) #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) #pragma wave option(preserve: 1) #endif #define BOOST_PP_ITERATION_PARAMS_1 \ (3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/context/detail/null_eval.hpp>)) #include BOOST_PP_ITERATE() #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) #pragma wave option(output: null) #endif #undef BOOST_PROTO_EVAL_N #else #define N BOOST_PP_ITERATION() template<typename Expr, typename Context> struct null_eval<Expr, Context, N> { typedef void result_type; void operator ()(Expr &expr, Context &ctx) const { BOOST_PP_REPEAT(N, BOOST_PROTO_EVAL_N, ~) } }; #undef N #endif PK �%"\8%��.# .# callable.hppnu �[��� /////////////////////////////////////////////////////////////////////////////// /// \file callable.hpp /// Definintion of callable_context\<\>, an evaluation context for /// proto::eval() that explodes each node and calls the derived context /// type with the expressions constituents. If the derived context doesn't /// have an overload that handles this node, fall back to some other /// context. // // Copyright 2008 Eric Niebler. 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_PROTO_CONTEXT_CALLABLE_HPP_EAN_06_23_2007 #define BOOST_PROTO_CONTEXT_CALLABLE_HPP_EAN_06_23_2007 #include <boost/config.hpp> #include <boost/detail/workaround.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/iteration/iterate.hpp> #include <boost/preprocessor/facilities/intercept.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_trailing.hpp> #include <boost/preprocessor/repetition/enum_trailing_params.hpp> #include <boost/preprocessor/arithmetic/inc.hpp> #include <boost/preprocessor/selection/max.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/bool.hpp> #include <boost/utility/result_of.hpp> #include <boost/type_traits/remove_cv.hpp> #include <boost/proto/proto_fwd.hpp> #include <boost/proto/traits.hpp> // for child_c namespace boost { namespace proto { namespace detail { template<typename Context> struct callable_context_wrapper : remove_cv<Context>::type { callable_context_wrapper(); typedef private_type_ fun_type(...); operator fun_type *() const; BOOST_DELETED_FUNCTION(callable_context_wrapper &operator =(callable_context_wrapper const &)) }; template<typename T> yes_type check_is_expr_handled(T const &); no_type check_is_expr_handled(private_type_ const &); template<typename Expr, typename Context, long Arity = Expr::proto_arity_c> struct is_expr_handled; template<typename Expr, typename Context> struct is_expr_handled<Expr, Context, 0> { static callable_context_wrapper<Context> &sctx_; static Expr &sexpr_; static typename Expr::proto_tag &stag_; static const bool value = sizeof(yes_type) == sizeof( detail::check_is_expr_handled( (sctx_(stag_, proto::value(sexpr_)), 0) ) ); typedef mpl::bool_<value> type; }; } namespace context { /// \brief A BinaryFunction that accepts a Proto expression and a /// callable context and calls the context with the expression tag /// and children as arguments, effectively fanning the expression /// out. /// /// <tt>callable_eval\<\></tt> requires that \c Context is a /// PolymorphicFunctionObject that can be invoked with \c Expr's /// tag and children as expressions, as follows: /// /// \code /// context(Expr::proto_tag(), child_c<0>(expr), child_c<1>(expr), ...) /// \endcode template< typename Expr , typename Context , long Arity // = Expr::proto_arity_c > struct callable_eval {}; /// \brief A BinaryFunction that accepts a Proto expression and a /// callable context and calls the context with the expression tag /// and children as arguments, effectively fanning the expression /// out. /// /// <tt>callable_eval\<\></tt> requires that \c Context is a /// PolymorphicFunctionObject that can be invoked with \c Expr's /// tag and children as expressions, as follows: /// /// \code /// context(Expr::proto_tag(), value(expr)) /// \endcode template<typename Expr, typename Context> struct callable_eval<Expr, Context, 0> { typedef typename proto::result_of::value<Expr const &>::type value_type; typedef typename BOOST_PROTO_RESULT_OF< Context(typename Expr::proto_tag, value_type) >::type result_type; /// \param expr The current expression /// \param context The callable evaluation context /// \return <tt>context(Expr::proto_tag(), value(expr))</tt> result_type operator ()(Expr &expr, Context &context) const { return context(typename Expr::proto_tag(), proto::value(expr)); } }; /// \brief An evaluation context adaptor that makes authoring a /// context a simple matter of writing function overloads, rather /// then writing template specializations. /// /// <tt>callable_context\<\></tt> is a base class that implements /// the context protocol by passing fanned-out expression nodes to /// the derived context, making it easy to customize the handling /// of expression types by writing function overloads. Only those /// expression types needing special handling require explicit /// handling. All others are dispatched to a user-specified /// default context, \c DefaultCtx. /// /// <tt>callable_context\<\></tt> is defined simply as: /// /// \code /// template<typename Context, typename DefaultCtx = default_context> /// struct callable_context /// { /// template<typename Expr, typename ThisContext = Context> /// struct eval /// : mpl::if_< /// is_expr_handled_<Expr, Context> // For exposition /// , callable_eval<Expr, ThisContext> /// , typename DefaultCtx::template eval<Expr, Context> /// >::type /// {}; /// }; /// \endcode /// /// The Boolean metafunction <tt>is_expr_handled_\<\></tt> uses /// metaprogramming tricks to determine whether \c Context has /// an overloaded function call operator that accepts the /// fanned-out constituents of an expression of type \c Expr. /// If so, the handling of the expression is dispatched to /// <tt>callable_eval\<\></tt>. If not, it is dispatched to /// the user-specified \c DefaultCtx. /// /// Below is an example of how to use <tt>callable_context\<\></tt>: /// /// \code /// // An evaluation context that increments all /// // integer terminals in-place. /// struct increment_ints /// : callable_context< /// increment_ints const // derived context /// , null_context const // fall-back context /// > /// { /// typedef void result_type; /// /// // Handle int terminals here: /// void operator()(proto::tag::terminal, int &i) const /// { /// ++i; /// } /// }; /// \endcode /// /// With \c increment_ints, we can do the following: /// /// \code /// literal<int> i = 0, j = 10; /// proto::eval( i - j * 3.14, increment_ints() ); /// /// assert( i.get() == 1 && j.get() == 11 ); /// \endcode template< typename Context , typename DefaultCtx // = default_context > struct callable_context { /// A BinaryFunction that accepts an \c Expr and a /// \c Context, and either fans out the expression and passes /// it to the context, or else hands off the expression to /// \c DefaultCtx. /// /// If \c Context is a PolymorphicFunctionObject such that /// it can be invoked with the tag and children of \c Expr, /// as <tt>ctx(Expr::proto_tag(), child_c\<0\>(expr), child_c\<1\>(expr)...)</tt>, /// then <tt>eval\<Expr, ThisContext\></tt> inherits from /// <tt>callable_eval\<Expr, ThisContext\></tt>. Otherwise, /// <tt>eval\<Expr, ThisContext\></tt> inherits from /// <tt>DefaultCtx::eval\<Expr, Context\></tt>. template<typename Expr, typename ThisContext = Context> struct eval : mpl::if_c< detail::is_expr_handled<Expr, Context>::value , callable_eval<Expr, ThisContext> , typename DefaultCtx::template eval<Expr, Context> >::type {}; }; } #include <boost/proto/context/detail/callable_eval.hpp> }} #endif PK ��!\̒e� pooled_fixedsize_stack.hppnu �[��� PK ��!\���� � i continuation.hppnu �[��� PK ��!\=�^� � b fiber.hppnu �[��� PK ��!\���]5. 5. ? continuation_fcontext.hppnu �[��� PK ��!\��V8; 8; �C fiber_winfib.hppnu �[��� PK ��!\f A�- �- 5 fiber_fcontext.hppnu �[��� PK ��!\ό� � g� stack_traits.hppnu �[��� PK ��!\�#0�G �G d� fiber_ucontext.hppnu �[��� PK ��!\͗2�; �; ~� continuation_winfib.hppnu �[��� PK ��!\�t � � �5 posix/segmented_stack.hppnu �[��� PK ��!\ԑR�� � # �> posix/protected_fixedsize_stack.hppnu �[��� PK ��!\�.�,F F �J flags.hppnu �[��� PK ��!\�,�� ,M detail/invoke.hppnu �[��� PK ��!\Ĺ��� � uR detail/externc.hppnu �[��� PK ��!\(�ބ� � UU detail/exchange.hppnu �[��� PK ��!\k�:�� � }X detail/prefetch.hppnu �[��� PK ��!\��F�G G _` detail/apply.hppnu �[��� PK ��!\-�� �h detail/config.hppnu �[��� PK ��!\=�� � Fz detail/exception.hppnu �[��� PK ��!\��5Ë � I~ detail/fcontext.hppnu �[��� PK ��!\&��� � � detail/index_sequence.hppnu �[��� PK ��!\�sA�} } $� detail/tuple.hppnu �[��� PK ��!\0��� � � detail/disable_overload.hppnu �[��� PK ��!\Ȭ\�$ $ % ӝ windows/protected_fixedsize_stack.hppnu �[��� PK ��!\@ug| | L� segmented_stack.hppnu �[��� PK ��!\٣7(�G �G � continuation_ucontext.hppnu �[��� PK ��!\�ʁI< < B� preallocated.hppnu �[��� PK ��!\� h=� � �� stack_context.hppnu �[��� PK ��!\37\ �� fixedsize_stack.hppnu �[��� PK ��!\X�Ǿ� � � protected_fixedsize_stack.hppnu �[��� PK �%"\�[��L �L � default.hppnu �[��� PK �%"\G �(+ + �S null.hppnu �[��� PK �%"\��`3�W �W % %Z detail/preprocessed/callable_eval.hppnu �[��� PK �%"\_yf�S S $ I� detail/preprocessed/default_eval.hppnu �[��� PK �%"\�!�� � ! � detail/preprocessed/null_eval.hppnu �[��� PK �%"\Lk��� � � detail/callable_eval.hppnu �[��� PK �%"\�A`}� � �) detail/default_eval.hppnu �[��� PK �%"\-� � �5 detail/null_eval.hppnu �[��� PK �%"\8%��.# .# = callable.hppnu �[��� PK '