annotate DEPENDENCIES/generic/include/boost/context/execution_context.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1
Chris@102 2 // Copyright Oliver Kowalke 2014.
Chris@102 3 // Distributed under the Boost Software License, Version 1.0.
Chris@102 4 // (See accompanying file LICENSE_1_0.txt or copy at
Chris@102 5 // http://www.boost.org/LICENSE_1_0.txt)
Chris@102 6
Chris@102 7 #ifndef BOOST_CONTEXT_EXECUTION_CONTEXT_H
Chris@102 8 #define BOOST_CONTEXT_EXECUTION_CONTEXT_H
Chris@102 9
Chris@102 10 #include <boost/context/detail/config.hpp>
Chris@102 11
Chris@102 12 #if ! defined(BOOST_CONTEXT_NO_EXECUTION_CONTEXT)
Chris@102 13
Chris@102 14 # include <cstddef>
Chris@102 15 # include <cstdint>
Chris@102 16 # include <cstdlib>
Chris@102 17 # include <exception>
Chris@102 18 # include <memory>
Chris@102 19 # include <tuple>
Chris@102 20 # include <utility>
Chris@102 21
Chris@102 22 # include <boost/assert.hpp>
Chris@102 23 # include <boost/config.hpp>
Chris@102 24 # include <boost/context/fcontext.hpp>
Chris@102 25 # include <boost/intrusive_ptr.hpp>
Chris@102 26
Chris@102 27 # include <boost/context/stack_context.hpp>
Chris@102 28 # include <boost/context/segmented_stack.hpp>
Chris@102 29
Chris@102 30 # ifdef BOOST_HAS_ABI_HEADERS
Chris@102 31 # include BOOST_ABI_PREFIX
Chris@102 32 # endif
Chris@102 33
Chris@102 34 # if defined(BOOST_USE_SEGMENTED_STACKS)
Chris@102 35 extern "C" {
Chris@102 36
Chris@102 37 void __splitstack_getcontext( void * [BOOST_CONTEXT_SEGMENTS]);
Chris@102 38
Chris@102 39 void __splitstack_setcontext( void * [BOOST_CONTEXT_SEGMENTS]);
Chris@102 40
Chris@102 41 }
Chris@102 42 # endif
Chris@102 43
Chris@102 44 namespace boost {
Chris@102 45 namespace context {
Chris@102 46
Chris@102 47 struct preallocated {
Chris@102 48 void * sp;
Chris@102 49 std::size_t size;
Chris@102 50 stack_context sctx;
Chris@102 51
Chris@102 52 preallocated( void * sp_, std::size_t size_, stack_context sctx_) noexcept :
Chris@102 53 sp( sp_), size( size_), sctx( sctx_) {
Chris@102 54 }
Chris@102 55 };
Chris@102 56
Chris@102 57 class BOOST_CONTEXT_DECL execution_context {
Chris@102 58 private:
Chris@102 59 struct fcontext {
Chris@102 60 std::size_t use_count;
Chris@102 61 fcontext_t fctx;
Chris@102 62 stack_context sctx;
Chris@102 63
Chris@102 64 // main-context
Chris@102 65 fcontext() noexcept :
Chris@102 66 use_count( 1),
Chris@102 67 fctx( nullptr),
Chris@102 68 sctx() {
Chris@102 69 }
Chris@102 70
Chris@102 71 // worker-context
Chris@102 72 fcontext( fcontext_t fctx_, stack_context const& sctx_) noexcept :
Chris@102 73 use_count( 0),
Chris@102 74 fctx( fctx_),
Chris@102 75 sctx( sctx_) {
Chris@102 76 }
Chris@102 77
Chris@102 78 virtual ~fcontext() noexcept {
Chris@102 79 }
Chris@102 80
Chris@102 81 virtual void deallocate() {
Chris@102 82 }
Chris@102 83
Chris@102 84 virtual void run() noexcept {
Chris@102 85 }
Chris@102 86
Chris@102 87 friend void intrusive_ptr_add_ref( fcontext * ctx) {
Chris@102 88 ++ctx->use_count;
Chris@102 89 }
Chris@102 90
Chris@102 91 friend void intrusive_ptr_release( fcontext * ctx) {
Chris@102 92 BOOST_ASSERT( nullptr != ctx);
Chris@102 93
Chris@102 94 if ( 0 == --ctx->use_count) {
Chris@102 95 ctx->~fcontext();
Chris@102 96 }
Chris@102 97 }
Chris@102 98 };
Chris@102 99
Chris@102 100 template< typename Fn, typename StackAlloc >
Chris@102 101 class worker_fcontext : public fcontext {
Chris@102 102 private:
Chris@102 103 StackAlloc salloc_;
Chris@102 104 Fn fn_;
Chris@102 105
Chris@102 106 static void destroy( worker_fcontext * p) {
Chris@102 107 StackAlloc salloc( p->salloc_);
Chris@102 108 stack_context sctx( p->sctx);
Chris@102 109 p->~worker_fcontext();
Chris@102 110 salloc.deallocate( sctx);
Chris@102 111 }
Chris@102 112
Chris@102 113 public:
Chris@102 114 explicit worker_fcontext( stack_context sctx, StackAlloc const& salloc, fcontext_t fctx, Fn && fn) noexcept :
Chris@102 115 fcontext( fctx, sctx),
Chris@102 116 salloc_( salloc),
Chris@102 117 fn_( std::forward< Fn >( fn) ) {
Chris@102 118 }
Chris@102 119
Chris@102 120 void deallocate() override final {
Chris@102 121 destroy( this);
Chris@102 122 }
Chris@102 123
Chris@102 124 void run() noexcept override final {
Chris@102 125 fn_();
Chris@102 126 }
Chris@102 127 };
Chris@102 128
Chris@102 129 static void entry_func( intptr_t p) noexcept {
Chris@102 130 BOOST_ASSERT( 0 != p);
Chris@102 131
Chris@102 132 fcontext * bp( reinterpret_cast< fcontext * >( p) );
Chris@102 133 BOOST_ASSERT( nullptr != bp);
Chris@102 134
Chris@102 135 bp->run();
Chris@102 136 }
Chris@102 137
Chris@102 138 typedef boost::intrusive_ptr< fcontext > ptr_t;
Chris@102 139
Chris@102 140 thread_local static fcontext main_ctx_;
Chris@102 141 thread_local static ptr_t current_ctx_;
Chris@102 142
Chris@102 143 boost::intrusive_ptr< fcontext > ptr_;
Chris@102 144 # if defined(BOOST_USE_SEGMENTED_STACKS)
Chris@102 145 bool use_segmented_stack_ = false;
Chris@102 146 # endif
Chris@102 147
Chris@102 148 template< typename StackAlloc, typename Fn >
Chris@102 149 static fcontext * create_context( StackAlloc salloc, Fn && fn) {
Chris@102 150 typedef worker_fcontext< Fn, StackAlloc > func_t;
Chris@102 151
Chris@102 152 stack_context sctx( salloc.allocate() );
Chris@102 153 // reserve space for control structure
Chris@102 154 std::size_t size = sctx.size - sizeof( func_t);
Chris@102 155 void * sp = static_cast< char * >( sctx.sp) - sizeof( func_t);
Chris@102 156 #if 0
Chris@102 157 constexpr std::size_t func_alignment = 64; // alignof( func_t);
Chris@102 158 constexpr std::size_t func_size = sizeof( func_t);
Chris@102 159 // reserve space on stack
Chris@102 160 void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
Chris@102 161 // align sp pointer
Chris@102 162 sp = std::align( func_alignment, func_size, sp, func_size + func_alignment);
Chris@102 163 BOOST_ASSERT( nullptr != sp);
Chris@102 164 // calculate remaining size
Chris@102 165 std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
Chris@102 166 #endif
Chris@102 167 // create fast-context
Chris@102 168 fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func);
Chris@102 169 BOOST_ASSERT( nullptr != fctx);
Chris@102 170 // placment new for control structure on fast-context stack
Chris@102 171 return new ( sp) func_t( sctx, salloc, fctx, std::forward< Fn >( fn) );
Chris@102 172 }
Chris@102 173
Chris@102 174 template< typename StackAlloc, typename Fn >
Chris@102 175 static fcontext * create_context( preallocated palloc, StackAlloc salloc, Fn && fn) {
Chris@102 176 typedef worker_fcontext< Fn, StackAlloc > func_t;
Chris@102 177
Chris@102 178 // reserve space for control structure
Chris@102 179 std::size_t size = palloc.size - sizeof( func_t);
Chris@102 180 void * sp = static_cast< char * >( palloc.sp) - sizeof( func_t);
Chris@102 181 #if 0
Chris@102 182 constexpr std::size_t func_alignment = 64; // alignof( func_t);
Chris@102 183 constexpr std::size_t func_size = sizeof( func_t);
Chris@102 184 // reserve space on stack
Chris@102 185 void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
Chris@102 186 // align sp pointer
Chris@102 187 sp = std::align( func_alignment, func_size, sp, func_size + func_alignment);
Chris@102 188 BOOST_ASSERT( nullptr != sp);
Chris@102 189 // calculate remaining size
Chris@102 190 std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
Chris@102 191 #endif
Chris@102 192 // create fast-context
Chris@102 193 fcontext_t fctx = make_fcontext( sp, size, & execution_context::entry_func);
Chris@102 194 BOOST_ASSERT( nullptr != fctx);
Chris@102 195 // placment new for control structure on fast-context stack
Chris@102 196 return new ( sp) func_t( palloc.sctx, salloc, fctx, std::forward< Fn >( fn) );
Chris@102 197 }
Chris@102 198
Chris@102 199 template< typename StackAlloc, typename Fn, typename Tpl, std::size_t ... I >
Chris@102 200 static fcontext * create_worker_fcontext( StackAlloc salloc,
Chris@102 201 Fn && fn_, Tpl && tpl_,
Chris@102 202 std::index_sequence< I ... >) {
Chris@102 203 return create_context( salloc,
Chris@102 204 [fn=std::forward< Fn >( fn_),tpl=std::forward< Tpl >( tpl_)] () mutable {
Chris@102 205 try {
Chris@102 206 fn(
Chris@102 207 // std::tuple_element<> does not perfect forwarding
Chris@102 208 std::forward< decltype( std::get< I >( std::declval< Tpl >() ) ) >(
Chris@102 209 std::get< I >( std::forward< Tpl >( tpl) ) ) ... );
Chris@102 210 } catch (...) {
Chris@102 211 std::terminate();
Chris@102 212 }
Chris@102 213 });
Chris@102 214 }
Chris@102 215
Chris@102 216 template< typename StackAlloc, typename Fn, typename Tpl, std::size_t ... I >
Chris@102 217 static fcontext * create_worker_fcontext( preallocated palloc, StackAlloc salloc,
Chris@102 218 Fn && fn_, Tpl && tpl_,
Chris@102 219 std::index_sequence< I ... >) {
Chris@102 220 return create_context( palloc, salloc,
Chris@102 221 [fn=std::forward< Fn >( fn_),tpl=std::forward< Tpl >( tpl_)] () mutable {
Chris@102 222 try {
Chris@102 223 fn(
Chris@102 224 // std::tuple_element<> does not perfect forwarding
Chris@102 225 std::forward< decltype( std::get< I >( std::declval< Tpl >() ) ) >(
Chris@102 226 std::get< I >( std::forward< Tpl >( tpl) ) ) ... );
Chris@102 227 } catch (...) {
Chris@102 228 std::terminate();
Chris@102 229 }
Chris@102 230 });
Chris@102 231 }
Chris@102 232
Chris@102 233 execution_context() :
Chris@102 234 ptr_( current_ctx_) {
Chris@102 235 }
Chris@102 236
Chris@102 237 public:
Chris@102 238 static execution_context current() noexcept {
Chris@102 239 return execution_context();
Chris@102 240 }
Chris@102 241
Chris@102 242 # if defined(BOOST_USE_SEGMENTED_STACKS)
Chris@102 243 template< typename Fn, typename ... Args >
Chris@102 244 explicit execution_context( segmented_stack salloc, Fn && fn, Args && ... args) :
Chris@102 245 ptr_( create_worker_fcontext( salloc,
Chris@102 246 std::forward< Fn >( fn),
Chris@102 247 std::make_tuple( std::forward< Args >( args) ... ),
Chris@102 248 std::index_sequence_for< Args ... >() ) ),
Chris@102 249 use_segmented_stack_( true) {
Chris@102 250 }
Chris@102 251
Chris@102 252 template< typename Fn, typename ... Args >
Chris@102 253 explicit execution_context( preallocated palloc, segmented_stack salloc, Fn && fn, Args && ... args) :
Chris@102 254 ptr_( create_worker_fcontext( palloc, salloc,
Chris@102 255 std::forward< Fn >( fn),
Chris@102 256 std::make_tuple( std::forward< Args >( args) ... ),
Chris@102 257 std::index_sequence_for< Args ... >() ) ),
Chris@102 258 use_segmented_stack_( true) {
Chris@102 259 }
Chris@102 260 # endif
Chris@102 261
Chris@102 262 template< typename StackAlloc, typename Fn, typename ... Args >
Chris@102 263 explicit execution_context( StackAlloc salloc, Fn && fn, Args && ... args) :
Chris@102 264 ptr_( create_worker_fcontext( salloc,
Chris@102 265 std::forward< Fn >( fn),
Chris@102 266 std::make_tuple( std::forward< Args >( args) ... ),
Chris@102 267 std::index_sequence_for< Args ... >() ) ) {
Chris@102 268 }
Chris@102 269
Chris@102 270 template< typename StackAlloc, typename Fn, typename ... Args >
Chris@102 271 explicit execution_context( preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args) :
Chris@102 272 ptr_( create_worker_fcontext( palloc, salloc,
Chris@102 273 std::forward< Fn >( fn),
Chris@102 274 std::make_tuple( std::forward< Args >( args) ... ),
Chris@102 275 std::index_sequence_for< Args ... >() ) ) {
Chris@102 276 }
Chris@102 277
Chris@102 278 void resume( bool preserve_fpu = false) noexcept {
Chris@102 279 fcontext * old_ctx( current_ctx_.get() );
Chris@102 280 fcontext * new_ctx( ptr_.get() );
Chris@102 281 current_ctx_ = ptr_;
Chris@102 282 # if defined(BOOST_USE_SEGMENTED_STACKS)
Chris@102 283 if ( use_segmented_stack_) {
Chris@102 284 __splitstack_getcontext( old_ctx->sctx.segments_ctx);
Chris@102 285 __splitstack_setcontext( new_ctx->sctx.segments_ctx);
Chris@102 286
Chris@102 287 jump_fcontext( & old_ctx->fctx, new_ctx->fctx, reinterpret_cast< intptr_t >( new_ctx), preserve_fpu);
Chris@102 288
Chris@102 289 __splitstack_setcontext( old_ctx->sctx.segments_ctx);
Chris@102 290 } else {
Chris@102 291 jump_fcontext( & old_ctx->fctx, new_ctx->fctx, reinterpret_cast< intptr_t >( new_ctx), preserve_fpu);
Chris@102 292 }
Chris@102 293 # else
Chris@102 294 jump_fcontext( & old_ctx->fctx, new_ctx->fctx, reinterpret_cast< intptr_t >( new_ctx), preserve_fpu);
Chris@102 295 # endif
Chris@102 296 }
Chris@102 297 };
Chris@102 298
Chris@102 299 }}
Chris@102 300
Chris@102 301 # ifdef BOOST_HAS_ABI_HEADERS
Chris@102 302 # include BOOST_ABI_SUFFIX
Chris@102 303 # endif
Chris@102 304
Chris@102 305 #endif
Chris@102 306
Chris@102 307 #endif // BOOST_CONTEXT_EXECUTION_CONTEXT_H