BVB Source Codes

mars Show execution_context_v1.hpp Source code

Return Download mars: download execution_context_v1.hpp Source code - Download mars Source code - Type:.hpp
  1.  
  2. //          Copyright Oliver Kowalke 2014.
  3. // Distributed under the Boost Software License, Version 1.0.
  4. //    (See accompanying file LICENSE_1_0.txt or copy at
  5. //          http://www.boost.org/LICENSE_1_0.txt)
  6.  
  7. #ifndef BOOST_CONTEXT_EXECUTION_CONTEXT_H
  8. #define BOOST_CONTEXT_EXECUTION_CONTEXT_H
  9.  
  10. #include <boost/context/detail/config.hpp>
  11.  
  12. #include <algorithm>
  13. #include <atomic>
  14. #include <cstddef>
  15. #include <cstdint>
  16. #include <cstdlib>
  17. #include <functional>
  18. #include <memory>
  19. #include <ostream>
  20. #include <tuple>
  21. #include <utility>
  22.  
  23. #include <boost/assert.hpp>
  24. #include <boost/config.hpp>
  25. #include <boost/intrusive_ptr.hpp>
  26.  
  27. #include <boost/context/detail/apply.hpp>
  28. #include <boost/context/detail/disable_overload.hpp>
  29. #include <boost/context/detail/fcontext.hpp>
  30. #include <boost/context/fixedsize_stack.hpp>
  31. #include <boost/context/flags.hpp>
  32. #include <boost/context/preallocated.hpp>
  33. #include <boost/context/segmented_stack.hpp>
  34. #include <boost/context/stack_context.hpp>
  35.  
  36. #ifdef BOOST_HAS_ABI_HEADERS
  37. # include BOOST_ABI_PREFIX
  38. #endif
  39.  
  40. #if defined(BOOST_USE_SEGMENTED_STACKS)
  41. extern "C" {
  42. void __splitstack_getcontext( void * [BOOST_CONTEXT_SEGMENTS]);
  43. void __splitstack_setcontext( void * [BOOST_CONTEXT_SEGMENTS]);
  44. }
  45. #endif
  46.  
  47. namespace mars_boost {} namespace boost = mars_boost; namespace mars_boost {
  48. namespace context {
  49. namespace detail {
  50.  
  51. template< typename Fn >
  52. transfer_t context_ontop( transfer_t);
  53.  
  54. struct activation_record;
  55.  
  56. struct data_t {
  57.     activation_record   *   from;
  58.     void                *   data;
  59. };
  60.  
  61. struct activation_record {
  62.     typedef mars_boost::intrusive_ptr< activation_record >    ptr_t;
  63.  
  64.     thread_local static ptr_t   current_rec;
  65.  
  66.     std::atomic< std::size_t >  use_count{ 0 };
  67.     fcontext_t                  fctx{ nullptr };
  68.     stack_context               sctx{};
  69.     bool                        main_ctx{ true };
  70.  
  71.     // used for toplevel-context
  72.     // (e.g. main context, thread-entry context)
  73.     constexpr activation_record() = default;
  74.  
  75.     activation_record( fcontext_t fctx_, stack_context sctx_) noexcept :
  76.         fctx{ fctx_ },
  77.         sctx( sctx_ ), // sctx{ sctx_ } - clang-3.6: no viable conversion from 'boost::context::stack_context' to 'std::size_t'
  78.         main_ctx{ false } {
  79.     }
  80.  
  81.     virtual ~activation_record() = default;
  82.  
  83.     bool is_main_context() const noexcept {
  84.         return main_ctx;
  85.     }
  86.  
  87.     void * resume( void * vp) {
  88.         // store current activation record in local variable
  89.         auto from = current_rec.get();
  90.         // store `this` in static, thread local pointer
  91.         // `this` will become the active (running) context
  92.         // returned by execution_context::current()
  93.         current_rec = this;
  94. #if defined(BOOST_USE_SEGMENTED_STACKS)
  95.         // adjust segmented stack properties
  96.         __splitstack_getcontext( from->sctx.segments_ctx);
  97.         __splitstack_setcontext( sctx.segments_ctx);
  98. #endif
  99.         data_t d = { from, vp };
  100.         // context switch from parent context to `this`-context
  101.         transfer_t t = jump_fcontext( fctx, & d);
  102.         data_t * dp = reinterpret_cast< data_t * >( t.data);
  103.         dp->from->fctx = t.fctx;
  104.         // parent context resumed
  105.         return dp->data;
  106.     }
  107.  
  108.     template< typename Fn >
  109.     void * resume_ontop( void *  data, Fn && fn) {
  110.         // store current activation record in local variable
  111.         activation_record * from = current_rec.get();
  112.         // store `this` in static, thread local pointer
  113.         // `this` will become the active (running) context
  114.         // returned by execution_context::current()
  115.         current_rec = this;
  116. #if defined(BOOST_USE_SEGMENTED_STACKS)
  117.         // adjust segmented stack properties
  118.         __splitstack_getcontext( from->sctx.segments_ctx);
  119.         __splitstack_setcontext( sctx.segments_ctx);
  120. #endif
  121.         std::tuple< void *, Fn > p = std::forward_as_tuple( data, fn);
  122.         data_t d = { from, & p };
  123.         // context switch from parent context to `this`-context
  124.         // execute Fn( Tpl) on top of `this`
  125.         transfer_t t = ontop_fcontext( fctx, & d, context_ontop< Fn >);
  126.         data_t * dp = reinterpret_cast< data_t * >( t.data);
  127.         dp->from->fctx = t.fctx;
  128.         // parent context resumed
  129.         return dp->data;
  130.     }
  131.  
  132.     virtual void deallocate() noexcept {
  133.     }
  134.  
  135.     friend void intrusive_ptr_add_ref( activation_record * ar) noexcept {
  136.         ++ar->use_count;
  137.     }
  138.  
  139.     friend void intrusive_ptr_release( activation_record * ar) noexcept {
  140.         BOOST_ASSERT( nullptr != ar);
  141.         if ( 0 == --ar->use_count) {
  142.             ar->deallocate();
  143.         }
  144.     }
  145. };
  146.  
  147. struct activation_record_initializer {
  148.     activation_record_initializer() noexcept;
  149.     ~activation_record_initializer();
  150. };
  151.  
  152. template< typename Fn >
  153. transfer_t context_ontop( transfer_t t) {
  154.     data_t * dp = reinterpret_cast< data_t * >( t.data);
  155.     dp->from->fctx = t.fctx;
  156.     auto tpl = reinterpret_cast< std::tuple< void *, Fn > * >( dp->data);
  157.     BOOST_ASSERT( nullptr != tpl);
  158.     auto data = std::get< 0 >( * tpl);
  159.     typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 1 >( * tpl) );
  160.     dp->data = apply( fn, std::tie( data) );
  161.     return { t.fctx, dp };
  162. }
  163.  
  164. template< typename StackAlloc, typename Fn, typename ... Args >
  165. class capture_record : public activation_record {
  166. private:
  167.     StackAlloc                                          salloc_;
  168.     typename std::decay< Fn >::type                     fn_;
  169.     std::tuple< typename std::decay< Args >::type ... > args_;
  170.     activation_record                               *   caller_;
  171.  
  172.     static void destroy( capture_record * p) noexcept {
  173.         StackAlloc salloc = p->salloc_;
  174.         stack_context sctx = p->sctx;
  175.         // deallocate activation record
  176.         p->~capture_record();
  177.         // destroy stack with stack allocator
  178.         salloc.deallocate( sctx);
  179.     }
  180.  
  181. public:
  182.     capture_record( stack_context sctx, StackAlloc const& salloc,
  183.                     fcontext_t fctx,
  184.                     activation_record * caller,
  185.                     Fn && fn, Args && ... args) noexcept :
  186.         activation_record{ fctx, sctx },
  187.         salloc_{ salloc },
  188.         fn_( std::forward< Fn >( fn) ),
  189.         args_( std::forward< Args >( args) ... ),
  190.         caller_{ caller } {
  191.     }
  192.  
  193.     void deallocate() noexcept override final {
  194.         destroy( this);
  195.     }
  196.  
  197.     void run() {
  198.         auto data = caller_->resume( nullptr);
  199.         apply( fn_, std::tuple_cat( args_, std::tie( data) ) );
  200.         BOOST_ASSERT_MSG( ! main_ctx, "main-context does not execute activation-record::run()");
  201.     }
  202. };
  203.  
  204. }
  205.  
  206. class BOOST_CONTEXT_DECL execution_context {
  207. private:
  208.     // tampoline function
  209.     // entered if the execution context
  210.     // is resumed for the first time
  211.     template< typename AR >
  212.     static void entry_func( detail::transfer_t t) noexcept {
  213.         detail::data_t * dp = reinterpret_cast< detail::data_t * >( t.data);
  214.         AR * ar = static_cast< AR * >( dp->data);
  215.         BOOST_ASSERT( nullptr != ar);
  216.         dp->from->fctx = t.fctx;
  217.         // start execution of toplevel context-function
  218.         ar->run();
  219.     }
  220.  
  221.     typedef mars_boost::intrusive_ptr< detail::activation_record >    ptr_t;
  222.  
  223.     ptr_t   ptr_;
  224.  
  225.     template< typename StackAlloc, typename Fn, typename ... Args >
  226.     static detail::activation_record * create_context( StackAlloc salloc,
  227.                                                        Fn && fn, Args && ... args) {
  228.         typedef detail::capture_record<
  229.             StackAlloc, Fn, Args ...
  230.         >                                           capture_t;
  231.  
  232.         auto sctx = salloc.allocate();
  233.         // reserve space for control structure
  234. #if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
  235.         const std::size_t size = sctx.size - sizeof( capture_t);
  236.         void * sp = static_cast< char * >( sctx.sp) - sizeof( capture_t);
  237. #else
  238.         constexpr std::size_t func_alignment = 64; // alignof( capture_t);
  239.         constexpr std::size_t func_size = sizeof( capture_t);
  240.         // reserve space on stack
  241.         void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
  242.         // align sp pointer
  243.         std::size_t space = func_size + func_alignment;
  244.         sp = std::align( func_alignment, func_size, sp, space);
  245.         BOOST_ASSERT( nullptr != sp);
  246.         // calculate remaining size
  247.         const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
  248. #endif
  249.         // create fast-context
  250.         const detail::fcontext_t fctx = detail::make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
  251.         BOOST_ASSERT( nullptr != fctx);
  252.         // get current activation record
  253.         auto curr = execution_context::current().ptr_;
  254.         // placment new for control structure on fast-context stack
  255.         return ::new ( sp) capture_t{
  256.                 sctx, salloc, fctx, curr.get(), std::forward< Fn >( fn), std::forward< Args >( args) ... };
  257.     }
  258.  
  259.     template< typename StackAlloc, typename Fn, typename ... Args >
  260.     static detail::activation_record * create_context( preallocated palloc, StackAlloc salloc,
  261.                                                        Fn && fn, Args && ... args) {
  262.         typedef detail::capture_record<
  263.             StackAlloc, Fn, Args ...
  264.         >                                           capture_t;
  265.  
  266.         // reserve space for control structure
  267. #if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
  268.         const std::size_t size = palloc.size - sizeof( capture_t);
  269.         void * sp = static_cast< char * >( palloc.sp) - sizeof( capture_t);
  270. #else
  271.         constexpr std::size_t func_alignment = 64; // alignof( capture_t);
  272.         constexpr std::size_t func_size = sizeof( capture_t);
  273.         // reserve space on stack
  274.         void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
  275.         // align sp pointer
  276.         std::size_t space = func_size + func_alignment;
  277.         sp = std::align( func_alignment, func_size, sp, space);
  278.         BOOST_ASSERT( nullptr != sp);
  279.         // calculate remaining size
  280.         const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
  281. #endif
  282.         // create fast-context
  283.         const detail::fcontext_t fctx = detail::make_fcontext( sp, size, & execution_context::entry_func< capture_t >);
  284.         BOOST_ASSERT( nullptr != fctx);
  285.         // get current activation record
  286.         auto curr = execution_context::current().ptr_;
  287.         // placment new for control structure on fast-context stack
  288.         return ::new ( sp) capture_t{
  289.                 palloc.sctx, salloc, fctx, curr.get(), std::forward< Fn >( fn), std::forward< Args >( args) ... };
  290.     }
  291.  
  292.     execution_context() noexcept :
  293.         // default constructed with current activation_record
  294.         ptr_{ detail::activation_record::current_rec } {
  295.     }
  296.  
  297. public:
  298.     static execution_context current() noexcept;
  299.  
  300. #if defined(BOOST_USE_SEGMENTED_STACKS)
  301.     template< typename Fn,
  302.               typename ... Args,
  303.               typename = detail::disable_overload< execution_context, Fn >
  304.     >
  305.     execution_context( Fn && fn, Args && ... args) :
  306.         // deferred execution of fn and its arguments
  307.         // arguments are stored in std::tuple<>
  308.         // non-type template parameter pack via std::index_sequence_for<>
  309.         // preserves the number of arguments
  310.         // used to extract the function arguments from std::tuple<>
  311.         ptr_{ create_context( segmented_stack(),
  312.                               std::forward< Fn >( fn),
  313.                               std::forward< Args >( args) ...) } {
  314.         ptr_->resume( ptr_.get() );
  315.     }
  316.  
  317.     template< typename Fn,
  318.               typename ... Args
  319.     >
  320.     execution_context( std::allocator_arg_t, segmented_stack salloc, Fn && fn, Args && ... args) :
  321.         // deferred execution of fn and its arguments
  322.         // arguments are stored in std::tuple<>
  323.         // non-type template parameter pack via std::index_sequence_for<>
  324.         // preserves the number of arguments
  325.         // used to extract the function arguments from std::tuple<>
  326.         ptr_{ create_context( salloc,
  327.                               std::forward< Fn >( fn),
  328.                               std::forward< Args >( args) ...) } {
  329.         ptr_->resume( ptr_.get() );
  330.     }
  331.  
  332.     template< typename Fn,
  333.               typename ... Args
  334.     >
  335.     execution_context( std::allocator_arg_t, preallocated palloc, segmented_stack salloc, Fn && fn, Args && ... args) :
  336.         // deferred execution of fn and its arguments
  337.         // arguments are stored in std::tuple<>
  338.         // non-type template parameter pack via std::index_sequence_for<>
  339.         // preserves the number of arguments
  340.         // used to extract the function arguments from std::tuple<>
  341.         ptr_{ create_context( palloc, salloc,
  342.                               std::forward< Fn >( fn),
  343.                               std::forward< Args >( args) ...) } {
  344.         ptr_->resume( ptr_.get() );
  345.     }
  346. #else
  347.     template< typename Fn,
  348.               typename ... Args,
  349.               typename = detail::disable_overload< execution_context, Fn >
  350.     >
  351.     execution_context( Fn && fn, Args && ... args) :
  352.         // deferred execution of fn and its arguments
  353.         // arguments are stored in std::tuple<>
  354.         // non-type template parameter pack via std::index_sequence_for<>
  355.         // preserves the number of arguments
  356.         // used to extract the function arguments from std::tuple<>
  357.         ptr_{ create_context( fixedsize_stack(),
  358.                               std::forward< Fn >( fn),
  359.                               std::forward< Args >( args) ...) } {
  360.         ptr_->resume( ptr_.get() );
  361.     }
  362.  
  363.     template< typename StackAlloc,
  364.               typename Fn,
  365.               typename ... Args
  366.     >
  367.     execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args) :
  368.         // deferred execution of fn and its arguments
  369.         // arguments are stored in std::tuple<>
  370.         // non-type template parameter pack via std::index_sequence_for<>
  371.         // preserves the number of arguments
  372.         // used to extract the function arguments from std::tuple<>
  373.         ptr_{ create_context( salloc,
  374.                               std::forward< Fn >( fn),
  375.                               std::forward< Args >( args) ...) } {
  376.         ptr_->resume( ptr_.get() );
  377.     }
  378.  
  379.     template< typename StackAlloc,
  380.               typename Fn,
  381.               typename ... Args
  382.     >
  383.     execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) :
  384.         // deferred execution of fn and its arguments
  385.         // arguments are stored in std::tuple<>
  386.         // non-type template parameter pack via std::index_sequence_for<>
  387.         // preserves the number of arguments
  388.         // used to extract the function arguments from std::tuple<>
  389.         ptr_{ create_context( palloc, salloc,
  390.                               std::forward< Fn >( fn),
  391.                               std::forward< Args >( args) ...) } {
  392.         ptr_->resume( ptr_.get() );
  393.     }
  394. #endif
  395.  
  396.     execution_context( execution_context const& other) noexcept :
  397.         ptr_{ other.ptr_ } {
  398.     }
  399.  
  400.     execution_context( execution_context && other) noexcept :
  401.         ptr_{ other.ptr_ } {
  402.         other.ptr_.reset();
  403.     }
  404.  
  405.     execution_context & operator=( execution_context const& other) noexcept {
  406.         // intrusive_ptr<> does not test for self-assignment
  407.         if ( this == & other) return * this;
  408.         ptr_ = other.ptr_;
  409.         return * this;
  410.     }
  411.  
  412.     execution_context & operator=( execution_context && other) noexcept {
  413.         if ( this == & other) return * this;
  414.         execution_context tmp{ std::move( other) };
  415.         swap( tmp);
  416.         return * this;
  417.     }
  418.  
  419.     void * operator()( void * vp = nullptr) {
  420.         return ptr_->resume( vp);
  421.     }
  422.  
  423.     template< typename Fn >
  424.     void * operator()( exec_ontop_arg_t, Fn && fn, void * vp = nullptr) {
  425.         return ptr_->resume_ontop( vp,
  426.                                    std::forward< Fn >( fn) );
  427.     }
  428.  
  429.     explicit operator bool() const noexcept {
  430.         return nullptr != ptr_.get();
  431.     }
  432.  
  433.     bool operator!() const noexcept {
  434.         return nullptr == ptr_.get();
  435.     }
  436.  
  437.     bool operator==( execution_context const& other) const noexcept {
  438.         return ptr_ == other.ptr_;
  439.     }
  440.  
  441.     bool operator!=( execution_context const& other) const noexcept {
  442.         return ptr_ != other.ptr_;
  443.     }
  444.  
  445.     bool operator<( execution_context const& other) const noexcept {
  446.         return ptr_ < other.ptr_;
  447.     }
  448.  
  449.     bool operator>( execution_context const& other) const noexcept {
  450.         return other.ptr_ < ptr_;
  451.     }
  452.  
  453.     bool operator<=( execution_context const& other) const noexcept {
  454.         return ! ( * this > other);
  455.     }
  456.  
  457.     bool operator>=( execution_context const& other) const noexcept {
  458.         return ! ( * this < other);
  459.     }
  460.  
  461.     template< typename charT, class traitsT >
  462.     friend std::basic_ostream< charT, traitsT > &
  463.     operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
  464.         if ( nullptr != other.ptr_) {
  465.             return os << other.ptr_;
  466.         } else {
  467.             return os << "{not-a-context}";
  468.         }
  469.     }
  470.  
  471.     void swap( execution_context & other) noexcept {
  472.         ptr_.swap( other.ptr_);
  473.     }
  474. };
  475.  
  476. inline
  477. void swap( execution_context & l, execution_context & r) noexcept {
  478.     l.swap( r);
  479. }
  480.  
  481. }}
  482.  
  483. #ifdef BOOST_HAS_ABI_HEADERS
  484. # include BOOST_ABI_SUFFIX
  485. #endif
  486.  
  487. #endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H
  488.  
downloadexecution_context_v1.hpp Source code - Download mars Source code
Related Source Codes/Software:
Hero - Elegant transition library for iOS & tvOS 2017-06-09
deep-photo-styletransfer - Code and data for paper "Deep Photo Style Transfer... 2017-06-09
mastodon - A GNU Social-compatible microblogging server ... 2017-06-09
plyr - A simple HTML5, YouTube and Vimeo player ... 2017-06-08
prepack - Prepack is a partial evaluator for JavaScript. Pre... 2017-06-08
Public-APIs - 2017-06-09
lottie-ios - An iOS library to natively render After Effects ve... 2017-06-09
Awesome-Hacking - A collection of various awesome lists for hackers,... 2017-06-09
algorithms - Minimal examples of data structures and algorithms... 2017-06-10
lectures - Oxford Deep NLP 2017 course 2017-06-10
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top