]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/libs/context/doc/execution_context_v2.qbk
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / context / doc / execution_context_v2.qbk
diff --git a/ceph/src/boost/libs/context/doc/execution_context_v2.qbk b/ceph/src/boost/libs/context/doc/execution_context_v2.qbk
deleted file mode 100644 (file)
index a79c1d2..0000000
+++ /dev/null
@@ -1,664 +0,0 @@
-[/
-          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
-]
-
-[#ecv2]
-[section:ecv2 Class execution_context (version 2)]
-
-[note This class is enabled per default.]
-
-Class __econtext__ encapsulates context switching and manages the associated
-context' stack (allocation/deallocation).
-
-__econtext__ allocates the context stack (using its [link stack
-__stack_allocator__] argument) and creates a control structure on top of it.
-This structure is responsible for managing context' stack. The address of the
-control structure is stored in the first frame of context' stack (e.g. it can
-not directly accessed from within __econtext__). In contrast to __ecv1__ the
-ownership of the control structure is not shared (no member variable to control
-structure in __econtext__). __econtext__ keeps internally a state that is moved
-by a call of __ec_op__ (`*this` will be invalidated), e.g. after a calling
-__ec_op__, `*this` can not be used for an additional context switch.
-
-__econtext__ is  only move-constructible and move-assignable.
-
-The moved state is assigned to a new instance of __econtext__. This object
-becomes the first argument of the context-function, if the context was resumed
-the first time, or the first element in a tuple returned by __ec_op__ that has
-been called in the resumed context.
-In contrast to __ecv1__, the context switch is faster because no global pointer
-etc. is involved.
-
-[important Segmented stacks are not supported by __econtext__ (v2).]
-
-On return the context-function of the current context has to specify an
-__econtext__ to which the execution control is transferred after termination
-of the current context.
-
-If an instance with valid state goes out of scope and the context-function has
-not yet returned, the stack is traversed in order to access the control
-structure (address stored at the first stack frame) and context' stack is
-deallocated via the __stack_allocator__. The stack walking makes the destruction
-of __econtext__ slow and should be prevented if possible.
-
-__econtext__ expects a __context_fn__ with signature
-`execution_context(execution_context ctx, Args ... args)`. The parameter `ctx`
-represents the context from which this context was resumed (e.g. that has called
-__ec_op__ on `*this`) and `args` are the data passed to __ec_op__. The return
-value represents the execution_context that has to be resumed, after termiantion
-of this context.
-
-Benefits of __ecv2__ over __ecv1__ are: faster context switch, type-safety of
-passed/returned arguments.
-
-
-[heading usage of __econtext__]
-
-        int n=35;
-        ctx::execution_context<int> source(
-            [n](ctx::execution_context<int> sink, int) mutable {
-                int a=0;
-                int b=1;
-                while(n-->0){
-                    auto result=sink(a);
-                    sink=std::move(std::get<0>(result));
-                    auto next=a+b;
-                    a=b;
-                    b=next;
-                }
-                return sink;
-            });
-        for(int i=0;i<10;++i){
-            auto result=source(i);
-            source=std::move(std::get<0>(result));
-            std::cout<<std::get<1>(result)<<" ";
-        }
-
-        output:
-            0 1 1 2 3 5 8 13 21 34
-
-This simple example demonstrates the basic usage of __econtext__ as a generator.
-The context `sink` represents the ['main]-context (function ['main()] running).
-`sink` is generated by the framework (first element of lambda's parameter list).
-Because the state is invalidated (== changed) by each call of __ec_op__, the new
-state of the __econtext__, returned by __ec_op__, needs to be assigned to `sink`
-after each call.
-
-The lambda that calculates the Fibonacci numbers is executed inside
-the context represented by `source`. Calculated Fibonacci numbers are
-transferred between the two context' via expression ['sink(a)] (and returned by
-['source()]). Note that this example represents a ['generator] thus the value
-transferred into the lambda via ['source()] is not used. Using
-['boost::optional<>] as transferred type, might also appropriate to express this
-fact.
-
-The locale variables `a`, `b` and ` next` remain their values during each
-context switch (['yield(a)]). This is possible due `source` has its own stack
-and the stack is exchanged by each context switch.
-
-
-[heading parameter passing]
-With `execution_context<void>` no data will be transferred, only the context
-switch is executed.
-
-    boost::context::execution_context<void> ctx1([](boost::context::execution_context<void> ctx2){
-                std::printf("inside ctx1\n");
-                return ctx2();
-            });
-    ctx1();
-
-    output:
-        inside ctx1
-
-`ctx1()` resumes `ctx1`, e.g. the lambda passed at the constructor of `ctx1` is
-entered. Argument `ctx2` represents the context that has been suspended with the
-invocation of `ctx1()`. When the lambda returns `ctx2`, context `ctx1` will be
-terminated while the context represented by `ctx2` is resumed, hence the control
-of execution returns from `ctx1()`.
-
-The arguments passed to __ec_op__, in one context, is passed as the last
-arguments of the __context_fn__ if the context is started for the first time.
-In all following invocations of __ec_op__ the arguments passed to __ec_op__, in
-one context, is returned by __ec_op__ in the other context.
-
-    boost::context::execution_context<int> ctx1([](boost::context::execution_context<int> ctx2, int j){
-                std::printf("inside ctx1, j == %d\n", j);
-                return ctx2(j+1);
-            });
-    int i = 1;
-    std::tie(ctx1, i) = ctx1(i);
-    std::printf("i == %d\n", i);
-
-    output:
-        inside ctx1, j == 1
-        i == 2
-
-`ctx1(i)` enters the lambda in context `ctx1` with argument `j=1`. The
-expression `ctx2(j+1)` resumes the context represented by `ctx2` and transfers
-back an integer of `j+1`. On return of `ctx1(i)`, the variable `i` contains the
-value of `j+1`.
-
-If more than one argument has to be transferred, the signature of the
-context-function is simply extended.
-
-    boost::context::execution_context<int,int> ctx1([](boost::context::execution_context<int,int> ctx2, int i, int j){
-                std::printf("inside ctx1, i == %d j == %d\n", i, j);
-                return ctx2(i+j,i-j);
-            });
-    int i = 2, j = 1;
-    std::tie(ctx1, i, j) = ctx1(i,j);
-    std::printf("i == %d j == %d\n", i, j);
-
-    output:
-        inside ctx1, i == 2 j == 1
-        i == 3 j == 1
-
-For use-cases, that require to transfer data of different type in each
-direction, ['boost::variant<>] could be used.
-
-        class X{
-        private:
-            std::exception_ptr excptr_;
-            boost::context::execution_context<boost::variant<int,std::string>> ctx_;
-
-        public:
-            X():
-                excptr_(),
-                ctx_(
-                     [=](boost::context::execution_context<boost::variant<int,std::string>> ctx, boost::variant<int,std::string> data){
-                        try {
-                            for (;;) {
-                                int i = boost::get<int>(data);
-                                data = boost::lexical_cast<std::string>(i);
-                                auto result = ctx( data);
-                                ctx = std::move( std::get<0>( result) );
-                                data = std::get<1>( result);
-                        } catch (std::bad_cast const&) {
-                            excptr_=std::current_exception();
-                        }
-                        return ctx;
-                     })
-            {}
-
-            std::string operator()(int i){
-                boost::variant<int,std::string> data = i;
-                auto result = ctx_( data);
-                ctx_ = std::move( std::get<0>( result) );
-                data = std::get<1>( result);
-                if(excptr_){
-                    std::rethrow_exception(excptr_);
-                }
-                return boost::get<std::string>(data);
-            }
-        };
-
-        X x;
-        std::cout << x( 7) << std::endl;
-
-        output:
-        7
-
-In the case of unidirectional transfer of data, ['boost::optional<>] or a
-pointer are appropriate.
-
-
-[heading exception handling]
-If the function executed inside a __econtext__ emits ans exception, the
-application is terminated by calling ['std::terminate()]. ['std::exception_ptr]
-can be used to transfer exceptions between different execution contexts.
-
-[important Do not jump from inside a catch block and then re-throw the exception
-in another execution context.]
-
-[#ecv2_ontop]
-[heading Executing function on top of a context]
-Sometimes it is useful to execute a new function on top of a resumed context.
-For this purpose __ec_op__ with first argument `exec_ontop_arg` has to be used.
-The function passed as argument must return a tuple of execution_context and
-arguments.
-
-    boost::context::execution_context<int> f1(boost::context::execution_context<int> ctx,int data) {
-        std::cout << "f1: entered first time: " << data  << std::endl;
-        std::tie(ctx,data) = ctx(data+1);
-        std::cout << "f1: entered second time: " << data  << std::endl;
-        std::tie(ctx,data) = ctx(data+1);
-        std::cout << "f1: entered third time: " << data << std::endl;
-        return ctx;
-    }
-
-    std::tuple<boost::context::execution_context<int>,int> f2(boost::context::execution_context<int> ctx,int data) {
-        std::cout << "f2: entered: " << data << std::endl;
-        return std::make_tuple(std::move(ctx),-1);
-    }
-
-    int data = 0;
-    ctx::execution_context< int > ctx(f1);
-    std::tie(ctx,data) = ctx(data+1);
-    std::cout << "f1: returned first time: " << data << std::endl;
-    std::tie(ctx,data) = ctx(data+1);
-    std::cout << "f1: returned second time: " << data << std::endl;
-    std::tie(ctx,data) = ctx(ctx::exec_ontop_arg,f2,data+1);
-
-    output:
-        f1: entered first time: 1
-        f1: returned first time: 2
-        f1: entered second time: 3
-        f1: returned second time: 4
-        f2: entered: 5
-        f1: entered third time: -1
-
-The expression `ctx(ctx::exec_ontop_arg,f2,data+1)` executes `f2()` on top of
-context `ctx`, e.g. an additional stack frame is allocated on top of the context
-stack (in front of `f1()`). `f2()` returns argument `-1` that will returned by
-the second invocation of `ctx(data+1)` in `f1()`.
-
-Another option is to execute a function on top of the context that throws an
-exception.
-
-    struct interrupt {
-        boost::context::execution_context< void >   ctx;
-
-        interrupt( boost::context::execution_context< void > && ctx_) :
-            ctx( std::forward< boost::context::execution_context< void > >( ctx_) ) {
-        }
-    };
-
-    boost::context::execution_context<void> f1(boost::context::execution_context<void> ctx) {
-        try {
-            for (;;) {
-                std::cout << "f1()" << std::endl;
-                ctx = ctx();
-            }
-        } catch (interrupt & e) {
-            std::cout << "f1(): interrupted" << std::endl;
-            ctx = std::move( e.ctx);
-        }
-        return ctx;
-    }
-
-    boost::context::execution_context<void> f2(boost::context::execution_context<void> ctx) {
-        throw interrupt(std::move(ctx));
-        return ctx;
-    }
-
-    boost::context::execution_context< void > ctx(f1);
-    ctx = ctx();
-    ctx = ctx();
-    ctx = ctx(boost::context::exec_ontop_arg,f2);
-
-    output:
-        f1()
-        f1()
-        f1(): interrupted
-
-In this example `f2()` is used to interrupt the `for`-loop in `f1()`.
-
-
-[heading stack unwinding]
-On construction of __econtext__ a stack is allocated.
-If the __context_fn__ returns the stack will be destructed.
-If the __context_fn__ has not yet returned and the destructor of an valid
-__econtext__ instance (e.g. ['execution_context::operator bool()] returns
-`true`) is called, the stack will be destructed too.
-
-[important Code executed by __context_fn__ must not prevent the propagation of the
-__forced_unwind__ exception.  Absorbing that exception will cause stack
-unwinding to fail.  Thus, any code that catches all exceptions must re-throw any
-pending __forced_unwind__ exception.]
-
-
-[#ecv2_prealloc]
-[heading allocating control structures on top of stack]
-Allocating control structures on top of the stack requires to allocated the
-__stack_context__ and create the control structure with placement new before
-__econtext__ is created.
-[note The user is responsible for destructing the control structure at the top
-of the stack.]
-
-        // stack-allocator used for (de-)allocating stack
-        fixedsize_stack salloc( 4048);
-        // allocate stack space
-        stack_context sctx( salloc.allocate() );
-        // reserve space for control structure on top of the stack
-        void * sp = static_cast< char * >( sctx.sp) - sizeof( my_control_structure);
-        std::size_t size = sctx.size - sizeof( my_control_structure);
-        // placement new creates control structure on reserved space
-        my_control_structure * cs = new ( sp) my_control_structure( sp, size, sctx, salloc);
-        ...
-        // destructing the control structure
-        cs->~my_control_structure();
-        ...
-        struct my_control_structure  {
-            // captured context
-            execution_context cctx;
-
-            template< typename StackAllocator >
-            my_control_structure( void * sp, std::size_t size, stack_context sctx, StackAllocator salloc) :
-                // create captured context
-                cctx( std::allocator_arg, preallocated( sp, size, sctx), salloc, entry_func) {
-            }
-            ...
-        };
-
-
-[heading inverting the control flow]
-
-        /*
-         * grammar:
-         *   P ---> E '\0'
-         *   E ---> T {('+'|'-') T}
-         *   T ---> S {('*'|'/') S}
-         *   S ---> digit | '(' E ')'
-         */
-        class Parser{
-            // implementation omitted; see examples directory
-        };
-
-        std::istringstream is("1+1");
-        bool done=false;
-        std::exception_ptr except;
-
-        // execute parser in new execution context
-        boost::context::execution_context<char> source(
-                [&is,&done,&except](ctx::execution_context<char> sink,char){
-                // create parser with callback function
-                Parser p( is,
-                          [&sink](char ch){
-                                // resume main execution context
-                                auto result = sink(ch);
-                                sink = std::move(std::get<0>(result));
-                        });
-                    try {
-                        // start recursive parsing
-                        p.run();
-                    } catch (...) {
-                        // store other exceptions in exception-pointer
-                        except = std::current_exception();
-                    }
-                    // set termination flag
-                    done=true;
-                    // resume main execution context
-                    return sink;
-                });
-
-        // user-code pulls parsed data from parser
-        // invert control flow
-        auto result = source('\0');
-        source = std::move(std::get<0>(result));
-        char c = std::get<1>(result);
-        if ( except) {
-            std::rethrow_exception(except);
-        }
-        while( ! done) {
-            printf("Parsed: %c\n",c);
-            std::tie(source,c) = source('\0');
-            if (except) {
-                std::rethrow_exception(except);
-            }
-        }
-
-        output:
-            Parsed: 1
-            Parsed: +
-            Parsed: 1
-
-In this example a recursive descent parser uses a callback to emit a newly
-passed symbol. Using __econtext__ the control flow can be inverted, e.g. the
-user-code pulls parsed symbols from the parser - instead to get pushed from the
-parser (via callback).
-
-The data (character) is transferred between the two __econtext__.
-
-If the code executed by __econtext__ emits an exception, the application is
-terminated. ['std::exception_ptr] can be used to transfer exceptions between
-different execution contexts.
-
-Sometimes it is necessary to unwind the stack of an unfinished context to
-destroy local stack variables so they can release allocated resources (RAII
-pattern). The user is responsible for this task.
-
-
-[heading Class `execution_context`]
-
-    struct exec_ontop_arg_t {};
-    const exec_ontop_arg_t exec_ontop_arg{};
-
-    template< typename ... Args >
-    class execution_context {
-    public:
-        template< typename Fn, typename ... Params >
-        execution_context( Fn && fn, Params && ... params);
-    
-        template< typename StackAlloc, typename Fn, typename ... Params >
-        execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Params && ... params);
-    
-        template< typename StackAlloc, typename Fn, typename ... Params >
-        execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params);
-    
-        template< typename Fn, typename ... Params >
-        execution_context( std::allocator_arg_t, segemented_stack, Fn && fn, Params && ... params) = delete;
-    
-        template< typename Fn, typename ... Params >
-        execution_context( std::allocator_arg_t, preallocated palloc, segmented, Fn && fn, Params && ... params)= delete;
-
-        ~execution_context();
-    
-        execution_context( execution_context && other) noexcept;
-        execution_context & operator=( execution_context && other) noexcept;
-    
-        execution_context( execution_context const& other) noexcept = delete;
-        execution_context & operator=( execution_context const& other) noexcept = delete;
-    
-        explicit operator bool() const noexcept;
-        bool operator!() const noexcept;
-    
-        std::tuple< execution_context, Args ... > operator()( Args ... args);
-    
-        template< typename Fn >
-        std::tuple< execution_context, Args ... > operator()( exec_ontop_arg_t, Fn && fn, Args ... args);
-    
-        bool operator==( execution_context const& other) const noexcept;
-    
-        bool operator!=( execution_context const& other) const noexcept;
-    
-        bool operator<( execution_context const& other) const noexcept;
-    
-        bool operator>( execution_context const& other) const noexcept;
-    
-        bool operator<=( execution_context const& other) const noexcept;
-    
-        bool operator>=( execution_context const& other) const noexcept;
-    
-        template< typename charT, class traitsT >
-        friend std::basic_ostream< charT, traitsT > &
-        operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other);
-    };
-
-[constructor_heading ecv2..constructor]
-
-    template< typename Fn, typename ... Params >
-    execution_context( Fn && fn, Params && ... params);
-    
-    template< typename StackAlloc, typename Fn, typename ... Params >
-    execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Params && ... params);
-    
-    template< typename StackAlloc, typename Fn, typename ... Params >
-    execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Params && ... params);
-
-[variablelist
-[[Effects:] [Creates a new execution context and prepares the context to execute
-`fn`. `fixedsize_stack` is used as default stack allocator
-(stack size == fixedsize_stack::traits::default_size()).
-The constructor with argument type `preallocated`, is used to create a user
-defined data [link ecv2_prealloc (for instance additional control structures)] on
-top of the stack.]]
-]
-[destructor_heading ecv2..destructor destructor]
-
-    ~execution_context();
-
-[variablelist
-[[Effects:] [Destructs the associated stack if `*this` is a valid context,
-e.g. ['execution_context::operator bool()] returns `true`.]]
-[[Throws:] [Nothing.]]
-]
-
-[move_constructor_heading ecv2..move constructor]
-
-    execution_context( execution_context && other) noexcept;
-
-[variablelist
-[[Effects:] [Moves underlying capture record to `*this`.]]
-[[Throws:] [Nothing.]]
-]
-
-[move_assignment_heading ecv2..move assignment]
-
-    execution_context & operator=( execution_context && other) noexcept;
-
-[variablelist
-[[Effects:] [Moves the state of `other` to `*this` using move semantics.]]
-[[Throws:] [Nothing.]]
-]
-
-[operator_heading ecv2..operator_bool..operator bool]
-
-    explicit operator bool() const noexcept;
-
-[variablelist
-[[Returns:] [`true` if `*this` points to a capture record.]]
-[[Throws:] [Nothing.]]
-]
-
-[operator_heading ecv2..operator_not..operator!]
-
-    bool operator!() const noexcept;
-
-[variablelist
-[[Returns:] [`true` if `*this` does not point to a capture record.]]
-[[Throws:] [Nothing.]]
-]
-
-[operator_heading ecv2..operator_call..operator()]
-
-    std::tuple< execution_context< Args ... >, Args ... > operator()( Args ... args); // member of generic execution_context template
-
-    execution_context< void > operator()(); // member of execution_context< void >
-
-[variablelist
-[[Effects:] [Stores internally the current context data (stack pointer,
-instruction pointer, and CPU registers) of the current active context and
-restores the context data from `*this`, which implies jumping to `*this`'s
-context.
-The arguments, `... args`, are passed to the current context to be returned
-by the most recent call to `execution_context::operator()` in the same thread.]]
-[[Returns:] [The tuple of execution_context and returned arguments passed to the
-most recent call to `execution_context::operator()`, if any and a
-execution_context representing the context that has been suspended.]]
-[[Note:] [The returned execution_context indicates if the suspended context has
-terminated (return from context-function) via `bool operator()`. If the returned
-execution_context has terminated no data are transferred in the returned tuple.]]
-]
-
-[operator_heading ecv2..operator_call_ontop..operator()]
-
-            template< typename Fn >
-            std::tuple< execution_context< Args ... >, Args ... > operator()( exec_ontop_arg_t, Fn && fn, Args ... args); // member of generic execution_context
-
-            template< typename Fn >
-            execution_context< void > operator()( exec_ontop_arg_t, Fn && fn); // member of execution_context< void >
-
-[variablelist
-[[Effects:] [Same as __ec_op__. Additionally, function `fn` is executed
-in the context of `*this` (e.g. the stack frame of `fn` is allocated on
-stack of `*this`).]]
-[[Returns:] [The tuple of execution_context and returned arguments passed to the
-most recent call to `execution_context::operator()`, if any and a
-execution_context representing the context that has been suspended .]]
-[[Note:] [The tuple of execution_context and returned arguments from `fn` are
-passed as arguments to the context-function of resumed context (if the context
-is entered the first time) or those arguments are returned from
-`execution_context::operator()` within the resumed context.]]
-[[Note:] [Function `fn` needs to return a tuple of execution_context and
-arguments ([link ecv2_ontop see description]).]]
-[[Note:] [The context calling this function must not be destroyed before the
-arguments, that will be returned from `fn`, are preserved at least in the stack
-frame of the resumed context.]]
-[[Note:] [The returned execution_context indicates if the suspended context has
-terminated (return from context-function) via `bool operator()`. If the returned
-execution_context has terminated no data are transferred in the returned tuple.]]
-]
-
-[operator_heading ecv2..operator_equal..operator==]
-
-        bool operator==( execution_context const& other) const noexcept;
-
-[variablelist
-[[Returns:] [`true` if `*this` and `other` represent the same execution context,
-`false` otherwise.]]
-[[Throws:] [Nothing.]]
-]
-
-[operator_heading ecv2..operator_notequal..operator!=]
-
-        bool operator!=( execution_context const& other) const noexcept;
-
-[variablelist
-[[Returns:] [[`! (other == * this)]]]
-[[Throws:] [Nothing.]]
-]
-
-[operator_heading ecv2..operator_less..operator<]
-
-        bool operator<( execution_context const& other) const noexcept;
-
-[variablelist
-[[Returns:] [`true` if `*this != other` is true and the
-implementation-defined total order of `execution_context` values places `*this`
-before `other`, false otherwise.]]
-[[Throws:] [Nothing.]]
-]
-
-[operator_heading ecv2..operator_greater..operator>]
-
-        bool operator>( execution_context const& other) const noexcept;
-
-[variablelist
-[[Returns:] [`other < * this`]]
-[[Throws:] [Nothing.]]
-]
-
-[operator_heading ecv2..operator_lesseq..operator<=]
-
-        bool operator<=( execution_context const& other) const noexcept;
-
-[variablelist
-[[Returns:] [`! (other < * this)`]]
-[[Throws:] [Nothing.]]
-]
-
-[operator_heading ecv2..operator_greatereq..operator>=]
-
-        bool operator>=( execution_context const& other) const noexcept;
-
-[variablelist
-[[Returns:] [`! (* this < other)`]]
-[[Throws:] [Nothing.]]
-]
-
-[hding ecv2_..Non-member function [`operator<<()]]
-
-        template< typename charT, class traitsT >
-        std::basic_ostream< charT, traitsT > &
-        operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other);
-
-[variablelist
-[[Efects:] [Writes the representation of `other` to stream `os`.]]
-[[Returns:] [`os`]]
-]
-
-
-[endsect]