|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r77938 - in trunk: boost/context boost/context/detail libs/context/doc libs/context/example libs/context/example/asio libs/context/example/continuation libs/context/example/enumerator libs/context/performance libs/context/src libs/context/src/asm libs/context/test
From: oliver.kowalke_at_[hidden]
Date: 2012-04-12 14:42:42
Author: olli
Date: 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
New Revision: 77938
URL: http://svn.boost.org/trac/boost/changeset/77938
Log:
context: library stripped
Added:
trunk/libs/context/doc/stack.qbk (contents, props changed)
trunk/libs/context/example/jump.cpp (contents, props changed)
Removed:
trunk/boost/context/context.hpp
trunk/boost/context/detail/context_base.hpp
trunk/boost/context/detail/context_object.hpp
trunk/boost/context/flags.hpp
trunk/libs/context/doc/Jamfile.v2
trunk/libs/context/doc/asio.qbk
trunk/libs/context/doc/context.xml
trunk/libs/context/doc/context_ref.qbk
trunk/libs/context/doc/continuation.qbk
trunk/libs/context/doc/enumerator.qbk
trunk/libs/context/doc/examples.qbk
trunk/libs/context/doc/stack_ref.qbk
trunk/libs/context/example/asio/
trunk/libs/context/example/base_api.cpp
trunk/libs/context/example/continuation/
trunk/libs/context/example/do_return.cpp
trunk/libs/context/example/enumerator/
trunk/libs/context/example/exit.cpp
trunk/libs/context/example/float.cpp
trunk/libs/context/example/pic.sh
trunk/libs/context/example/swap.cpp
trunk/libs/context/example/unwind.cpp
Text files modified:
trunk/boost/context/all.hpp | 8
trunk/boost/context/detail/config.hpp | 6
trunk/boost/context/detail/fcontext_arm.hpp | 29 +-
trunk/boost/context/detail/fcontext_i386.hpp | 29 +-
trunk/boost/context/detail/fcontext_i386_win.hpp | 33 +-
trunk/boost/context/detail/fcontext_mips.hpp | 31 +-
trunk/boost/context/detail/fcontext_ppc.hpp | 31 +-
trunk/boost/context/detail/fcontext_x86_64.hpp | 29 +-
trunk/boost/context/detail/fcontext_x86_64_win.hpp | 31 +-
trunk/boost/context/fcontext.hpp | 19 +
trunk/boost/context/stack_allocator.hpp | 8
trunk/boost/context/stack_utils.hpp | 8
trunk/libs/context/doc/config.qbk | 27 +-
trunk/libs/context/doc/context.qbk | 25 +-
trunk/libs/context/doc/fcontext.qbk | 361 ++++++++++++++++++++++++++++-----------
trunk/libs/context/doc/overview.qbk | 15
trunk/libs/context/doc/rationale.qbk | 38 ---
trunk/libs/context/doc/tested.qbk | 18 -
trunk/libs/context/doc/todo.qbk | 1
trunk/libs/context/example/Jamfile.v2 | 66 ------
trunk/libs/context/example/link.cpp | 60 +++--
trunk/libs/context/example/transfer.cpp | 61 +++---
trunk/libs/context/performance/performance.cpp | 65 +-----
trunk/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S | 30 +-
trunk/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm | 30 +-
trunk/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S | 24 +-
trunk/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S | 16
trunk/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S | 30 +-
trunk/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S | 28 +-
trunk/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S | 52 ++--
trunk/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm | 26 +-
trunk/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S | 22 +-
trunk/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S | 14
trunk/libs/context/src/fcontext.cpp | 11
trunk/libs/context/src/seh.cpp | 18 -
trunk/libs/context/src/stack_allocator_posix.cpp | 2
trunk/libs/context/src/stack_allocator_windows.cpp | 2
trunk/libs/context/src/stack_utils_posix.cpp | 2
trunk/libs/context/src/stack_utils_windows.cpp | 2
trunk/libs/context/test/test_context.cpp | 286 +++++++++++++++----------------
40 files changed, 810 insertions(+), 784 deletions(-)
Modified: trunk/boost/context/all.hpp
==============================================================================
--- trunk/boost/context/all.hpp (original)
+++ trunk/boost/context/all.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,13 +4,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_ALL_H
-#define BOOST_CONTEXTS_ALL_H
+#ifndef BOOST_CTX_ALL_H
+#define BOOST_CTX_ALL_H
-#include <boost/context/context.hpp>
#include <boost/context/fcontext.hpp>
-#include <boost/context/flags.hpp>
#include <boost/context/stack_allocator.hpp>
#include <boost/context/stack_utils.hpp>
-#endif // BOOST_CONTEXTS_ALL_H
+#endif // BOOST_CTX_ALL_H
Deleted: trunk/boost/context/context.hpp
==============================================================================
--- trunk/boost/context/context.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,338 +0,0 @@
-
-// 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_CONTEXTS_CONTEXT_H
-#define BOOST_CONTEXTS_CONTEXT_H
-
-#include <boost/assert.hpp>
-#include <boost/bind.hpp>
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/move/move.hpp>
-#include <boost/preprocessor/repetition.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/remove_reference.hpp>
-#include <boost/utility/enable_if.hpp>
-
-#include <boost/context/detail/context_base.hpp>
-#include <boost/context/detail/context_object.hpp>
-#include <boost/context/flags.hpp>
-#include <boost/context/stack_allocator.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace contexts {
-
-class context
-{
-private:
- typedef detail::context_base::ptr_t base_ptr_t;
-
- base_ptr_t impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( context);
-
-#ifndef BOOST_NO_RVALUE_REFERENCES
- template< typename Allocator >
- static base_ptr_t make_context_(
- void( * fn)(), std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc)
- {
- return base_ptr_t(
- new detail::context_object< void(*)(), Allocator >(
- boost::forward< void(*)() >( fn), alloc, size, do_unwind, do_return) );
- }
-
- template< typename Allocator >
- static base_ptr_t make_context_(
- void( * fn)(), std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc)
- {
- BOOST_ASSERT( nxt);
- return base_ptr_t(
- new detail::context_object< void(*)(), Allocator >(
- boost::forward< void(*)() >( fn), alloc, size, do_unwind, nxt.impl_) );
- }
-
- template< typename Fn, typename Allocator >
- static base_ptr_t make_context_(
- Fn && fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc)
- {
- return base_ptr_t(
- new detail::context_object< typename remove_reference< Fn >::type, Allocator >(
- fn, alloc, size, do_unwind, do_return) );
- }
-
- template< typename Fn, typename Allocator >
- static base_ptr_t make_context_(
- Fn && fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc)
- {
- BOOST_ASSERT( nxt);
- return base_ptr_t(
- new detail::context_object< typename remove_reference< Fn >::type, Allocator >(
- fn, alloc, size, do_unwind, nxt.impl_) );
- }
-#else
- template< typename Fn, typename Allocator >
- static base_ptr_t make_context_(
- Fn fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc)
- {
- return base_ptr_t(
- new detail::context_object< Fn, Allocator >(
- fn, alloc, size, do_unwind, do_return) );
- }
-
- template< typename Fn, typename Allocator >
- static base_ptr_t make_context_(
- Fn fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc)
- {
- BOOST_ASSERT( nxt);
- return base_ptr_t(
- new detail::context_object< Fn, Allocator >(
- fn, alloc, size, do_unwind, nxt.impl_) );
- }
-
- template< typename Fn, typename Allocator >
- static base_ptr_t make_context_(
- BOOST_RV_REF( Fn) fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc)
- {
- return base_ptr_t(
- new detail::context_object< Fn, Allocator >(
- fn, alloc, size, do_unwind, do_return) );
- }
-
- template< typename Fn, typename Allocator >
- static base_ptr_t make_context_(
- BOOST_RV_REF( Fn) fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc)
- {
- BOOST_ASSERT( nxt);
- return base_ptr_t(
- new detail::context_object< Fn, Allocator >(
- fn, alloc, size, do_unwind, nxt.impl_) );
- }
-#endif
-
-public:
- typedef void ( * unspecified_bool_type)( context ***);
-
- static void unspecified_bool( context ***) {}
-
- context() :
- impl_()
- {}
-
-#ifndef BOOST_NO_RVALUE_REFERENCES
-# ifdef BOOST_MSVC
- template< typename Fn >
- context( Fn & fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- impl_( make_context_( static_cast< Fn & >( fn), size, do_unwind, do_return, stack_allocator() ) )
- {}
-
- template< typename Fn, typename Allocator >
- context( Fn & fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc) :
- impl_( make_context_( static_cast< Fn & >( fn), size, do_unwind, do_return, alloc) )
- {}
-
- template< typename Fn >
- context( Fn & fn, std::size_t size, flag_unwind_t do_unwind, context & nxt) :
- impl_( make_context_( static_cast< Fn & >( fn), size, do_unwind, nxt, stack_allocator() ) )
- {}
-
- template< typename Fn, typename Allocator >
- context( Fn & fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc) :
- impl_( make_context_( static_cast< Fn & >( fn), size, do_unwind, nxt, alloc) )
- {}
-# endif
- template< typename Fn >
- context( Fn && fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- impl_( make_context_( static_cast< Fn && >( fn), size, do_unwind, do_return, stack_allocator() ) )
- {}
-
- template< typename Fn, typename Allocator >
- context( Fn && fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc) :
- impl_( make_context_( static_cast< Fn && >( fn), size, do_unwind, do_return, alloc) )
- {}
-
- template< typename Fn >
- context( Fn && fn, std::size_t size, flag_unwind_t do_unwind, context & nxt) :
- impl_( make_context_( static_cast< Fn && >( fn), size, do_unwind, nxt, stack_allocator() ) )
- {}
-
- template< typename Fn, typename Allocator >
- context( Fn && fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc) :
- impl_( make_context_( static_cast< Fn && >( fn), size, do_unwind, nxt, alloc) )
- {}
-#else
- template< typename Fn >
- context( Fn fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- impl_( make_context_( fn, size, do_unwind, do_return, stack_allocator() ) )
- {}
-
- template< typename Fn, typename Allocator >
- context( Fn fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc) :
- impl_( make_context_( fn, size, do_unwind, do_return, alloc) )
- {}
-
- template< typename Fn >
- context( Fn fn, std::size_t size, flag_unwind_t do_unwind, context & nxt) :
- impl_( make_context_( fn, size, do_unwind, nxt, stack_allocator() ) )
- {}
-
- template< typename Fn, typename Allocator >
- context( Fn fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc) :
- impl_( make_context_( fn, size, do_unwind, nxt, alloc) )
- {}
-
- template< typename Fn >
- context( BOOST_RV_REF( Fn) fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- impl_( make_context_( fn, size, do_unwind, do_return, stack_allocator() ) )
- {}
-
- template< typename Fn, typename Allocator >
- context( BOOST_RV_REF( Fn) fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc) :
- impl_( make_context_( fn, size, do_unwind, do_return, alloc) )
- {}
-
- template< typename Fn >
- context( BOOST_RV_REF( Fn) fn, std::size_t size, flag_unwind_t do_unwind, context & nxt) :
- impl_( make_context_( fn, size, do_unwind, nxt, stack_allocator() ) )
- {}
-
- template< typename Fn, typename Allocator >
- context( BOOST_RV_REF( Fn) fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc) :
- impl_( make_context_( fn, size, do_unwind, nxt, alloc) )
- {}
-#endif
-
-#define BOOST_CONTEXT_ARG(z, n, unused) BOOST_PP_CAT(A, n) BOOST_PP_CAT(a, n)
-
-#define BOOST_CONTEXT_ARGS(n) BOOST_PP_ENUM(n, BOOST_CONTEXT_ARG, ~)
-
-#define BOOST_CONTEXT_CTOR(z, n, unused) \
- template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
- context( Fn fn, BOOST_CONTEXT_ARGS(n), std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) : \
- impl_( \
- make_context_( \
- boost::bind( boost::type< void >(), fn, BOOST_PP_ENUM_PARAMS(n, a) ), \
- size, do_unwind, do_return, stack_allocator() ) ) \
- {} \
- \
- template< typename Fn, typename Allocator, BOOST_PP_ENUM_PARAMS(n, typename A) > \
- context( Fn fn, BOOST_CONTEXT_ARGS(n), std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc) : \
- impl_( \
- make_context_( \
- boost::bind( boost::type< void >(), fn, BOOST_PP_ENUM_PARAMS(n, a) ), \
- size, do_unwind, do_return, alloc) ) \
- {} \
- \
- template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
- context( Fn fn, BOOST_CONTEXT_ARGS(n), std::size_t size, flag_unwind_t do_unwind, context & nxt) : \
- impl_( \
- make_context_( \
- boost::bind( boost::type< void >(), fn, BOOST_PP_ENUM_PARAMS(n, a) ), \
- size, do_unwind, nxt, stack_allocator() ) ) \
- {} \
- \
- template< typename Fn, typename Allocator, BOOST_PP_ENUM_PARAMS(n, typename A) > \
- context( Fn fn, BOOST_CONTEXT_ARGS(n), std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc) : \
- impl_( \
- make_context_( \
- boost::bind( boost::type< void >(), fn, BOOST_PP_ENUM_PARAMS(n, a) ), \
- size, do_unwind, nxt, alloc) ) \
- {} \
-
-#ifndef BOOST_CONTEXT_ARITY
-#define BOOST_CONTEXT_ARITY 10
-#endif
-
-BOOST_PP_REPEAT_FROM_TO( 1, BOOST_CONTEXT_ARITY, BOOST_CONTEXT_CTOR, ~)
-
-#undef BOOST_CONTEXT_CTOR
-#undef BOOST_CONTEXT_ARGS
-#undef BOOST_CONTEXT_ARG
-
- context( BOOST_RV_REF( context) other) :
- impl_()
- { swap( other); }
-
- context & operator=( BOOST_RV_REF( context) other)
- {
- if ( this == & other) return * this;
- context tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- operator unspecified_bool_type() const
- { return impl_ ? unspecified_bool : 0; }
-
- bool operator!() const
- { return ! impl_; }
-
- void swap( context & other)
- { impl_.swap( other.impl_); }
-
- intptr_t start()
- {
- BOOST_ASSERT( impl_);
- return impl_->start();
- }
-
- intptr_t resume( intptr_t vp = 0)
- {
- BOOST_ASSERT( impl_);
- return impl_->resume( vp);
- }
-
- intptr_t suspend( intptr_t vp = 0)
- {
- BOOST_ASSERT( impl_);
- return impl_->suspend( vp);
- }
-
- void unwind_stack()
- {
- BOOST_ASSERT( impl_);
- impl_->unwind_stack();
- }
-
- bool is_complete() const
- {
- BOOST_ASSERT( impl_);
- return impl_->is_complete();
- }
-
- bool is_started() const
- {
- BOOST_ASSERT( impl_);
- return impl_->is_started();
- }
-
- bool is_resumed() const
- {
- BOOST_ASSERT( impl_);
- return impl_->is_resumed();
- }
-
- bool is_running() const
- {
- BOOST_ASSERT( impl_);
- return impl_->is_running();
- }
-};
-
-inline
-void swap( context & l, context & r)
-{ l.swap( r); }
-
-}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXTS_CONTEXT_H
Modified: trunk/boost/context/detail/config.hpp
==============================================================================
--- trunk/boost/context/detail/config.hpp (original)
+++ trunk/boost/context/detail/config.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_DETAIL_CONFIG_H
-#define BOOST_CONTEXTS_DETAIL_CONFIG_H
+#ifndef BOOST_CTX_DETAIL_CONFIG_H
+#define BOOST_CTX_DETAIL_CONFIG_H
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
@@ -39,4 +39,4 @@
# include <boost/config/auto_link.hpp>
#endif
-#endif // BOOST_CONTEXTS_DETAIL_CONFIG_H
+#endif // BOOST_CTX_DETAIL_CONFIG_H
Deleted: trunk/boost/context/detail/context_base.hpp
==============================================================================
--- trunk/boost/context/detail/context_base.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,229 +0,0 @@
-
-// 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_CONTEXTS_DETAIL_CONTEXT_BASE_H
-#define BOOST_CONTEXTS_DETAIL_CONTEXT_BASE_H
-
-#include <algorithm>
-#include <cstddef>
-#include <cstdlib>
-#include <cstring>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/intrusive_ptr.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/context/detail/config.hpp>
-#include <boost/context/fcontext.hpp>
-#include <boost/context/flags.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace contexts {
-namespace detail {
-
-struct forced_unwind {};
-
-template< typename Ctx >
-void trampoline( intptr_t vp)
-{
- BOOST_ASSERT( vp);
-
- Ctx * ctx( reinterpret_cast< Ctx * >( vp) );
-
- try
- { ctx->exec(); }
- catch ( forced_unwind const&)
- {
- ctx->flags_ |= Ctx::flag_complete;
- boost_fcontext_jump( & ctx->ctx_callee_, & ctx->ctx_caller_, 0);
- }
- catch (...)
- { std::terminate(); }
-
- ctx->flags_ |= Ctx::flag_complete;
-
- // in order to return to the code invoked the context
- // nxt_->caller_ hast to set to the first one
- if ( ctx->nxt_)
- {
- Ctx * nxt( dynamic_cast< Ctx * >( ctx->nxt_.get() ) );
- BOOST_ASSERT( nxt);
- std::swap( nxt->ctx_caller_, ctx->ctx_caller_);
- if ( 0 != ( nxt->flags_ & Ctx::flag_do_return) )
- nxt->ctx_callee_.fc_link = & nxt->ctx_caller_;
- nxt->flags_ |= Ctx::flag_running;
- nxt->flags_ |= Ctx::flag_started;
- }
-}
-
-class context_base : private noncopyable
-{
-public:
- typedef intrusive_ptr< context_base > ptr_t;
-
- template< typename Allocator >
- context_base(
- Allocator & alloc, std::size_t size,
- flag_unwind_t do_unwind, flag_return_t do_return) :
- use_count_( 0), base_( alloc.allocate( size) ), ctx_caller_(), ctx_callee_(), nxt_(),
- flags_( stack_unwind == do_unwind ? flag_force_unwind : flag_dont_force_unwind)
- {
- BOOST_ASSERT( base_);
-
- std::memset( & ctx_caller_, 0, sizeof( ctx_caller_) );
- std::memset( & ctx_callee_, 0, sizeof( ctx_callee_) );
- ctx_callee_.fc_stack.ss_base = base_;
- ctx_callee_.fc_stack.ss_limit =
- static_cast< char * >( ctx_callee_.fc_stack.ss_base) - size;
-
- if ( return_to_caller == do_return)
- {
- flags_ |= flag_do_return;
- ctx_callee_.fc_link = & ctx_caller_;
- }
-
- boost_fcontext_make(
- & ctx_callee_, trampoline< context_base >, reinterpret_cast< intptr_t >( this) );
- }
-
- template< typename Allocator >
- context_base( Allocator & alloc, std::size_t size, flag_unwind_t do_unwind, ptr_t nxt) :
- use_count_( 0), base_( alloc.allocate( size) ), ctx_caller_(), ctx_callee_(), nxt_( nxt),
- flags_( stack_unwind == do_unwind ? flag_force_unwind : flag_dont_force_unwind)
- {
- BOOST_ASSERT( base_);
- BOOST_ASSERT( ! nxt_->is_complete() );
-
- std::memset( & ctx_callee_, 0, sizeof( ctx_callee_) );
- std::memset( & ctx_caller_, 0, sizeof( ctx_caller_) );
- ctx_callee_.fc_stack.ss_base = base_;
- ctx_callee_.fc_stack.ss_limit =
- static_cast< char * >( ctx_callee_.fc_stack.ss_base) - size;
- ctx_callee_.fc_link = & dynamic_pointer_cast< context_base >( nxt_)->ctx_callee_;
-
- boost_fcontext_make(
- & ctx_callee_, trampoline< context_base >, reinterpret_cast< intptr_t >( this) );
- }
-
- virtual ~context_base() {}
-
- template< typename Allocator >
- void cleanup( Allocator & alloc)
- {
- if ( ! is_complete()
- && ( is_started() || is_resumed() )
- && ( unwind_requested() ) )
- unwind_stack();
- std::size_t size = static_cast< char * >( ctx_callee_.fc_stack.ss_base) -
- static_cast< char * >( ctx_callee_.fc_stack.ss_limit);
- alloc.deallocate( base_, size);
- }
-
- bool unwind_requested() const
- { return 0 != ( flags_ & flag_force_unwind); }
-
- bool is_complete() const
- { return 0 != ( flags_ & flag_complete); }
-
- bool is_started() const
- { return 0 != ( flags_ & flag_started); }
-
- bool is_resumed() const
- { return 0 != ( flags_ & flag_resumed); }
-
- bool is_running() const
- { return 0 != ( flags_ & flag_running); }
-
- intptr_t start()
- {
- BOOST_ASSERT( ! is_complete() );
- BOOST_ASSERT( ! is_started() );
- BOOST_ASSERT( ! is_running() );
-
- flags_ |= flag_started;
- flags_ |= flag_running;
- return boost_fcontext_start( & ctx_caller_, & ctx_callee_);
- }
-
- intptr_t resume( intptr_t vp)
- {
- BOOST_ASSERT( is_started() );
- BOOST_ASSERT( ! is_complete() );
- BOOST_ASSERT( ! is_running() );
-
- flags_ |= flag_resumed;
- flags_ |= flag_running;
- return boost_fcontext_jump( & ctx_caller_, & ctx_callee_, vp);
- }
-
- intptr_t suspend( intptr_t vp)
- {
- BOOST_ASSERT( ! is_complete() );
- BOOST_ASSERT( is_running() );
-
- flags_ &= ~flag_running;
- intptr_t res = boost_fcontext_jump( & ctx_callee_, & ctx_caller_, vp);
- if ( 0 != ( flags_ & flag_unwind_stack) )
- throw forced_unwind();
- return res;
- }
-
- void unwind_stack()
- {
- BOOST_ASSERT( ! is_complete() );
- BOOST_ASSERT( ! is_running() );
-
- flags_ |= flag_unwind_stack;
- boost_fcontext_jump( & ctx_caller_, & ctx_callee_, 0);
- flags_ &= ~flag_unwind_stack;
- BOOST_ASSERT( is_complete() );
- }
-
- virtual void exec() = 0;
-
- friend inline void intrusive_ptr_add_ref( context_base * p)
- { ++p->use_count_; }
-
- friend inline void intrusive_ptr_release( context_base * p)
- { if ( --p->use_count_ == 0) delete p; }
-
-private:
- template< typename T >
- friend void trampoline( intptr_t vp);
-
- enum flag_t
- {
- flag_started = 1 << 1,
- flag_resumed = 1 << 2,
- flag_running = 1 << 3,
- flag_complete = 1 << 4,
- flag_unwind_stack = 1 << 5,
- flag_force_unwind = 1 << 6,
- flag_dont_force_unwind = 1 << 7,
- flag_do_return = 1 << 8,
- };
-
- std::size_t use_count_;
- void * base_;
- boost_fcontext_t ctx_caller_;
- boost_fcontext_t ctx_callee_;
- ptr_t nxt_;
- short flags_;
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXTS_DETAIL_CONTEXT_BASE_H
Deleted: trunk/boost/context/detail/context_object.hpp
==============================================================================
--- trunk/boost/context/detail/context_object.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,157 +0,0 @@
-
-// 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_CONTEXTS_DETAIL_CONTEXT_OBJECT_H
-#define BOOST_CONTEXTS_DETAIL_CONTEXT_OBJECT_H
-
-#include <cstddef>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-#include <boost/utility/base_from_member.hpp>
-
-#include <boost/context/detail/config.hpp>
-#include <boost/context/detail/context_base.hpp>
-#include <boost/context/flags.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace contexts {
-namespace detail {
-
-template< typename Fn, typename Allocator >
-class context_object : private base_from_member< Fn >,
- private base_from_member< Allocator >,
- public context_base
-{
-private:
- typedef base_from_member< Fn > fn_t;
- typedef base_from_member< Allocator > alloc_t;
-
- context_object( context_object &);
- context_object & operator=( context_object const&);
-
-public:
-#ifndef BOOST_NO_RVALUE_REFERENCES
- context_object( Fn & fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, do_return)
- {}
-
- context_object( Fn & fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, typename context_base::ptr_t nxt) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, nxt)
- {}
-
- context_object( Fn && fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- fn_t( static_cast< Fn && >( fn) ), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, do_return)
- {}
-
- context_object( Fn && fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, typename context_base::ptr_t nxt) :
- fn_t( static_cast< Fn && >( fn) ), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, nxt)
- {}
-#else
- context_object( Fn fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, do_return)
- {}
-
- context_object( Fn fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, typename context_base::ptr_t nxt) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, nxt)
- {}
-
- context_object( BOOST_RV_REF( Fn) fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, do_return)
- {}
-
- context_object( BOOST_RV_REF( Fn) fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, typename context_base::ptr_t nxt) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, nxt)
- {}
-#endif
-
- ~context_object()
- { cleanup( alloc_t::member); }
-
- void exec()
- { fn_t::member(); }
-};
-
-template< typename Fn, typename Allocator >
-class context_object< reference_wrapper< Fn >, Allocator > : private base_from_member< Fn & >,
- private base_from_member< Allocator >,
- public context_base
-{
-private:
- typedef base_from_member< Fn & > fn_t;
- typedef base_from_member< Allocator > alloc_t;
-
- context_object( context_object &);
- context_object & operator=( context_object const&);
-
-public:
- context_object( reference_wrapper< Fn > fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, do_return)
- {}
-
- context_object( reference_wrapper< Fn > fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, typename context_base::ptr_t nxt) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, nxt)
- {}
-
- ~context_object()
- { cleanup( alloc_t::member); }
-
- void exec()
- { fn_t::member(); }
-};
-
-template< typename Fn, typename Allocator >
-class context_object< const reference_wrapper< Fn >, Allocator > : private base_from_member< Fn & >,
- private base_from_member< Allocator >,
- public context_base
-{
-private:
- typedef base_from_member< Fn & > fn_t;
- typedef base_from_member< Allocator > alloc_t;
-
- context_object( context_object &);
- context_object & operator=( context_object const&);
-
-public:
- context_object( const reference_wrapper< Fn > fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, do_return)
- {}
-
- context_object( const reference_wrapper< Fn > fn, Allocator const& alloc, std::size_t size, flag_unwind_t do_unwind, typename context_base::ptr_t nxt) :
- fn_t( fn), alloc_t( alloc),
- context_base( alloc_t::member, size, do_unwind, nxt)
- {}
-
- ~context_object()
- { cleanup( alloc_t::member); }
-
- void exec()
- { fn_t::member(); }
-};
-
-}}}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_CONTEXTS_DETAIL_CONTEXT_OBJECT_H
Modified: trunk/boost/context/detail/fcontext_arm.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_arm.hpp (original)
+++ trunk/boost/context/detail/fcontext_arm.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_DETAIL_FCONTEXT_ARM_H
-#define BOOST_CONTEXTS_DETAIL_FCONTEXT_ARM_H
+#ifndef BOOST_CTX_DETAIL_FCONTEXT_ARM_H
+#define BOOST_CTX_DETAIL_FCONTEXT_ARM_H
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -16,30 +16,33 @@
# include BOOST_ABI_PREFIX
#endif
+namespace boost {
+namespace ctx {
+
extern "C" {
#define BOOST_CONTEXT_CALLDECL
-typedef struct boost_fcontext_stack boost_fcontext_stack_t;
-struct boost_fcontext_stack
+struct stack_t
{
- void * ss_base;
- void * ss_limit;
+ void * base;
+ void * limit;
};
-typedef struct boost_fcontext boost_fcontext_t;
-struct boost_fcontext
+struct fcontext_t
{
- boost::uint32_t fc_greg[11];
- boost::uint32_t fc_freg[16];
- boost_fcontext_stack_t fc_stack;
- boost_fcontext_t * fc_link;
+ boost::uint32_t fc_greg[11];
+ boost::uint32_t fc_freg[16];
+ stack_t fc_stack;
+ fcontext_t * fc_link;
};
}
+}}
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_DETAIL_FCONTEXT_ARM_H
+#endif // BOOST_CTX_DETAIL_FCONTEXT_ARM_H
Modified: trunk/boost/context/detail/fcontext_i386.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_i386.hpp (original)
+++ trunk/boost/context/detail/fcontext_i386.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_DETAIL_FCONTEXT_I386H
-#define BOOST_CONTEXTS_DETAIL_FCONTEXT_I386H
+#ifndef BOOST_CTX_DETAIL_FCONTEXT_I386H
+#define BOOST_CTX_DETAIL_FCONTEXT_I386H
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -16,30 +16,33 @@
# include BOOST_ABI_PREFIX
#endif
+namespace boost {
+namespace ctx {
+
extern "C" {
#define BOOST_CONTEXT_CALLDECL __attribute__((cdecl))
-typedef struct boost_fcontext_stack boost_fcontext_stack_t;
-struct boost_fcontext_stack
+struct stack_t
{
- void * ss_base;
- void * ss_limit;
+ void * base;
+ void * limit;
};
-typedef struct boost_fcontext boost_fcontext_t;
-struct boost_fcontext
+struct fcontext_t
{
- boost::uint32_t fc_greg[6];
- boost::uint32_t fc_freg[2];
- boost_fcontext_stack_t fc_stack;
- boost_fcontext_t * fc_link;
+ boost::uint32_t fc_greg[6];
+ boost::uint32_t fc_freg[2];
+ stack_t fc_stack;
+ fcontext_t * fc_link;
};
}
+}}
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_DETAIL_FCONTEXT_I386_H
+#endif // BOOST_CTX_DETAIL_FCONTEXT_I386_H
Modified: trunk/boost/context/detail/fcontext_i386_win.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_i386_win.hpp (original)
+++ trunk/boost/context/detail/fcontext_i386_win.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_DETAIL_FCONTEXT_I386H
-#define BOOST_CONTEXTS_DETAIL_FCONTEXT_I386H
+#ifndef BOOST_CTX_DETAIL_FCONTEXT_I386H
+#define BOOST_CTX_DETAIL_FCONTEXT_I386H
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -16,32 +16,35 @@
# include BOOST_ABI_PREFIX
#endif
+namespace boost {
+namespace ctx {
+
extern "C" {
#define BOOST_CONTEXT_CALLDECL __cdecl
-typedef struct boost_fcontext_stack boost_fcontext_stack_t;
-struct boost_fcontext_stack
+struct stack_t
{
- void * ss_base;
- void * ss_limit;
+ void * base;
+ void * limit;
};
-typedef struct boost_fcontext boost_fcontext_t;
-struct boost_fcontext
+struct fcontext_t
{
- boost::uint32_t fc_greg[6];
- boost::uint32_t fc_freg[2];
- boost_fcontext_stack_t fc_stack;
- boost_fcontext_t * fc_link;
- void * fc_excpt_lst;
- void * fc_local_storage;
+ boost::uint32_t fc_greg[6];
+ boost::uint32_t fc_freg[2];
+ stack_t fc_stack;
+ fcontext_t * fc_link;
+ void * fc_excpt_lst;
+ void * fc_local_storage;
};
}
+}}
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_DETAIL_FCONTEXT_I386_H
+#endif // BOOST_CTX_DETAIL_FCONTEXT_I386_H
Modified: trunk/boost/context/detail/fcontext_mips.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_mips.hpp (original)
+++ trunk/boost/context/detail/fcontext_mips.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_DETAIL_FCONTEXT_MIPS_H
-#define BOOST_CONTEXTS_DETAIL_FCONTEXT_MIPS_H
+#ifndef BOOST_CTX_DETAIL_FCONTEXT_MIPS_H
+#define BOOST_CTX_DETAIL_FCONTEXT_MIPS_H
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -16,36 +16,39 @@
# include BOOST_ABI_PREFIX
#endif
+namespace boost {
+namespace ctx {
+
extern "C" {
#define BOOST_CONTEXT_CALLDECL
// on MIPS we assume 64bit regsiters - even for 32bit ABIs
-typedef struct boost_fcontext_stack boost_fcontext_stack_t;
-struct boost_fcontext_stack
+struct stack_t
{
- void * ss_base;
- void * ss_limit;
+ void * base;
+ void * limit;
};
-typedef struct boost_fcontext boost_fcontext_t;
-struct boost_fcontext
+struct fcontext_t
{
- boost::uint64_t fc_greg[13];
+ boost::uint64_t fc_greg[13];
# if _MIPS_SIM == _ABI64
- boost::uint64_t fc_freg[8];
+ boost::uint64_t fc_freg[8];
# else
- boost::uint64_t fc_freg[6];
+ boost::uint64_t fc_freg[6];
# endif
- boost_fcontext_stack_t fc_stack;
- boost_fcontext_t * fc_link;
+ stack_t fc_stack;
+ fcontext_t * fc_link;
};
}
+}}
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_DETAIL_FCONTEXT_MIPS_H
+#endif // BOOST_CTX_DETAIL_FCONTEXT_MIPS_H
Modified: trunk/boost/context/detail/fcontext_ppc.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_ppc.hpp (original)
+++ trunk/boost/context/detail/fcontext_ppc.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_DETAIL_FCONTEXT_PPC_H
-#define BOOST_CONTEXTS_DETAIL_FCONTEXT_PPC_H
+#ifndef BOOST_CTX_DETAIL_FCONTEXT_PPC_H
+#define BOOST_CTX_DETAIL_FCONTEXT_PPC_H
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -16,34 +16,37 @@
# include BOOST_ABI_PREFIX
#endif
+namespace boost {
+namespace ctx {
+
extern "C" {
#define BOOST_CONTEXT_CALLDECL
-typedef struct boost_fcontext_stack boost_fcontext_stack_t;
-struct boost_fcontext_stack
+struct stack_t
{
- void * ss_base;
- void * ss_limit;
+ void * base;
+ void * limit;
};
-typedef struct boost_fcontext boost_fcontext_t;
-struct boost_fcontext
+struct fcontext_t
{
# if defined(__powerpc64__)
- boost::uint64_t fc_greg[23];
+ boost::uint64_t fc_greg[23];
# else
- boost::uint32_t fc_greg[23];
+ boost::uint32_t fc_greg[23];
# endif
- boost::uint64_t fc_freg[19];
- boost_fcontext_stack_t fc_stack;
- boost_fcontext_t * fc_link;
+ boost::uint64_t fc_freg[19];
+ stack_t fc_stack;
+ fcontext_t * fc_link;
};
}
+}}
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_DETAIL_FCONTEXT_PPC_H
+#endif // BOOST_CTX_DETAIL_FCONTEXT_PPC_H
Modified: trunk/boost/context/detail/fcontext_x86_64.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_x86_64.hpp (original)
+++ trunk/boost/context/detail/fcontext_x86_64.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_DETAIL_FCONTEXT_X86_64_H
-#define BOOST_CONTEXTS_DETAIL_FCONTEXT_X86_64_H
+#ifndef BOOST_CTX_DETAIL_FCONTEXT_X86_64_H
+#define BOOST_CTX_DETAIL_FCONTEXT_X86_64_H
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
@@ -16,30 +16,33 @@
# include BOOST_ABI_PREFIX
#endif
+namespace boost {
+namespace ctx {
+
extern "C" {
#define BOOST_CONTEXT_CALLDECL
-typedef struct boost_fcontext_stack boost_fcontext_stack_t;
-struct boost_fcontext_stack
+struct stack_t
{
- void * ss_base;
- void * ss_limit;
+ void * base;
+ void * limit;
};
-typedef struct boost_fcontext boost_fcontext_t;
-struct boost_fcontext
+struct fcontext_t
{
- boost::uint64_t fc_greg[8];
- boost::uint32_t fc_freg[2];
- boost_fcontext_stack_t fc_stack;
- boost_fcontext_t * fc_link;
+ boost::uint64_t fc_greg[8];
+ boost::uint32_t fc_freg[2];
+ stack_t fc_stack;
+ fcontext_t * fc_link;
};
}
+}}
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_DETAIL_FCONTEXT_X86_64_H
+#endif // BOOST_CTX_DETAIL_FCONTEXT_X86_64_H
Modified: trunk/boost/context/detail/fcontext_x86_64_win.hpp
==============================================================================
--- trunk/boost/context/detail/fcontext_x86_64_win.hpp (original)
+++ trunk/boost/context/detail/fcontext_x86_64_win.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_DETAIL_FCONTEXT_X86_64_H
-#define BOOST_CONTEXTS_DETAIL_FCONTEXT_X86_64_H
+#ifndef BOOST_CTX_DETAIL_FCONTEXT_X86_64_H
+#define BOOST_CTX_DETAIL_FCONTEXT_X86_64_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
@@ -17,31 +17,34 @@
# include BOOST_ABI_PREFIX
#endif
+namespace boost {
+namespace ctx {
+
extern "C" {
#define BOOST_CONTEXT_CALLDECL
-typedef struct boost_fcontext_stack boost_fcontext_stack_t;
-struct boost_fcontext_stack
+struct stack_t
{
- void * ss_base;
- void * ss_limit;
+ void * base;
+ void * limit;
};
-typedef struct boost_fcontext boost_fcontext_t;
-struct boost_fcontext
+struct fcontext_t
{
- boost::uint64_t fc_greg[10];
- boost::uint32_t fc_freg[2];
- boost_fcontext_stack_t fc_stack;
- boost_fcontext_t * fc_link;
- void * fc_local_storage;
+ boost::uint64_t fc_greg[10];
+ boost::uint32_t fc_freg[2];
+ stack_t fc_stack;
+ fcontext_t * fc_link;
+ void * fc_local_storage;
};
}
+}}
+
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_DETAIL_FCONTEXT_X86_64_H
+#endif // BOOST_CTX_DETAIL_FCONTEXT_X86_64_H
Modified: trunk/boost/context/fcontext.hpp
==============================================================================
--- trunk/boost/context/fcontext.hpp (original)
+++ trunk/boost/context/fcontext.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_FCONTEXT_H
-#define BOOST_CONTEXTS_FCONTEXT_H
+#ifndef BOOST_CTX_FCONTEXT_H
+#define BOOST_CTX_FCONTEXT_H
#if defined(__PGI)
#include <stdint.h>
@@ -59,18 +59,19 @@
# error "platform not supported"
#endif
-extern "C" {
+namespace boost {
+namespace ctx {
-BOOST_CONTEXT_DECL void * BOOST_CONTEXT_CALLDECL boost_fcontext_align( void * vp);
-BOOST_CONTEXT_DECL intptr_t BOOST_CONTEXT_CALLDECL boost_fcontext_start( boost_fcontext_t * ofc, boost_fcontext_t const* nfc);
-BOOST_CONTEXT_DECL intptr_t BOOST_CONTEXT_CALLDECL boost_fcontext_jump( boost_fcontext_t * ofc, boost_fcontext_t const* nfc, intptr_t vp);
-BOOST_CONTEXT_DECL void BOOST_CONTEXT_CALLDECL boost_fcontext_make( boost_fcontext_t * fc, void (* fn)( intptr_t), intptr_t vp);
+extern "C" BOOST_CONTEXT_DECL void * BOOST_CONTEXT_CALLDECL align_stack( void * vp);
+extern "C" BOOST_CONTEXT_DECL intptr_t BOOST_CONTEXT_CALLDECL start_fcontext( fcontext_t * ofc, fcontext_t const* nfc);
+extern "C" BOOST_CONTEXT_DECL intptr_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t * ofc, fcontext_t const* nfc, intptr_t vp);
+extern "C" BOOST_CONTEXT_DECL void BOOST_CONTEXT_CALLDECL make_fcontext( fcontext_t * fc, void (* fn)( intptr_t), intptr_t vp);
-}
+}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_FCONTEXT_H
+#endif // BOOST_CTX_FCONTEXT_H
Deleted: trunk/boost/context/flags.hpp
==============================================================================
--- trunk/boost/context/flags.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,27 +0,0 @@
-
-// 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_CONTEXTS_FLAGS_H
-#define BOOST_CONTEXTS_FLAGS_H
-
-namespace boost {
-namespace contexts {
-
-enum flag_unwind_t
-{
- stack_unwind = 0,
- no_stack_unwind
-};
-
-enum flag_return_t
-{
- return_to_caller = 0,
- exit_application
-};
-
-}}
-
-#endif // BOOST_CONTEXTS_FLAGS_H
Modified: trunk/boost/context/stack_allocator.hpp
==============================================================================
--- trunk/boost/context/stack_allocator.hpp (original)
+++ trunk/boost/context/stack_allocator.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_STACK_ALLOCATOR_H
-#define BOOST_CONTEXTS_STACK_ALLOCATOR_H
+#ifndef BOOST_CTX_STACK_ALLOCATOR_H
+#define BOOST_CTX_STACK_ALLOCATOR_H
#include <cstddef>
@@ -18,7 +18,7 @@
#endif
namespace boost {
-namespace contexts {
+namespace ctx {
class BOOST_CONTEXT_DECL stack_allocator
{
@@ -34,4 +34,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_STACK_ALLOCATOR_H
+#endif // BOOST_CTX_STACK_ALLOCATOR_H
Modified: trunk/boost/context/stack_utils.hpp
==============================================================================
--- trunk/boost/context/stack_utils.hpp (original)
+++ trunk/boost/context/stack_utils.hpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_CONTEXTS_STACK_UTILS_H
-#define BOOST_CONTEXTS_STACK_UTILS_H
+#ifndef BOOST_CTX_STACK_UTILS_H
+#define BOOST_CTX_STACK_UTILS_H
#include <cstddef>
@@ -18,7 +18,7 @@
#endif
namespace boost {
-namespace contexts {
+namespace ctx {
BOOST_CONTEXT_DECL std::size_t default_stacksize();
@@ -38,4 +38,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_CONTEXTS_STACK_UTILS_H
+#endif // BOOST_CTX_STACK_UTILS_H
Deleted: trunk/libs/context/doc/Jamfile.v2
==============================================================================
--- trunk/libs/context/doc/Jamfile.v2 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,33 +0,0 @@
-# (C) Copyright 2008 Anthony Williams
-#
-# 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)
-
-path-constant boost-images : ../../../doc/src/images ;
-
-xml context : context.qbk ;
-
-boostbook standalone
- :
- context
- :
- # HTML options first:
- # Use graphics not text for navigation:
- <xsl:param>navig.graphics=1
- # How far down we chunk nested sections, basically all of them:
- <xsl:param>chunk.section.depth=3
- # Don't put the first section on the same page as the TOC:
- <xsl:param>chunk.first.sections=1
- # How far down sections get TOC's
- <xsl:param>toc.section.depth=10
- # Max depth in each TOC:
- <xsl:param>toc.max.depth=3
- # How far down we go with TOC's
- <xsl:param>generate.section.toc.level=10
- # Path for links to Boost:
- <xsl:param>boost.root=../../../..
- # Path for libraries index:
- <xsl:param>boost.libraries=../../../../libs/libraries.htm
- # Use the main Boost stylesheet:
- <xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
- ;
Deleted: trunk/libs/context/doc/asio.qbk
==============================================================================
--- trunk/libs/context/doc/asio.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,168 +0,0 @@
-[/
- 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
-]
-
-[section:asio ASIO]
-
-Adapted from [@http://blog.think-async.com/2009/08/secret-sauce-revealed.html
-Thinking Asynchronously in C++] using boost.asio to implement a simple echo
-server.
-
-Chris Kohlhoff uses stackless coroutines based on preprocessor-based switch
-statements to implement an echo server using boost.asio.
-Class `continuation` provides a simple coroutine implemenatation using
-boost.context.
-
- class continuation
- {
- private:
- boost::contexts::context ctx_;
- boost::function< void( continuation &) > fn_;
- bool started_;
-
- void trampoline_()
- { fn_( * this); }
-
- public:
- continuation( boost::function< void( continuation &) > const& fn) :
- ctx_(
- & continuation::trampoline_, this,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind, boost::contexts::return_to_caller),
- fn_( fn), started_( false)
- {}
-
- void resume()
- {
- if ( ! started_)
- {
- started_ = true;
- ctx_.start();
- }
- else ctx_.resume();
- }
-
- void suspend()
- { ctx_.suspend(); }
-
- bool is_complete() const
- { return ctx_.is_complete(); }
- };
-
-The operator `server::operator()` is called by the asio reactor and jumps to
-coroutine (which is entering or resuming in function `server::do_()`).
-In function `sever::do_()` the control flow is all in one place and easy to
-follow; *this is queued for accepting a connection before control flow
-is passed back to the reactor via `suspend()`. If `server::do_()` is reentered,
-a local buffer is created and an asynch. read operation is queued into the
-reactor.
-The control flow is then returned to the reactor for io-multiplexing again.
-After some bytes were received `server::do_()` is reentred again starting a
-asynch. write operation.
-
-The advantage over the ordinary `bind()` version is that the state of execution
-is preserved so that variables used by the read/write operations may have local
-scope. Stackfull coroutines (as boost.context provides) enable
-application-protocol stacks which can be more easily implemented.
-For instance, if only part of a message is received (some bytes are outstanding
-before message can be parsed or serviced), then the current state can be easily
-suspended/preserved (even from nested functions of the protocol stack)
-until the remaining bytes are received.
-
- class server : public boost::enable_shared_from_this< server >,
- private continuation
- {
- private:
- boost::asio::ip::tcp::acceptor acceptor_;
- boost::system::error_code ec_;
- std::size_t n_;
-
- void do_()
- {
- for (;;)
- {
- boost::asio::ip::tcp::socket socket( acceptor_.get_io_service() );
- // accept connection request and enque *this for reading data from conenction
- acceptor_.async_accept( socket, boost::bind( & server::operator(), this->shared_from_this(), _1, 0) );
- // suspend() jumps back to operator() which returns to asio reactor
- suspend();
-
- while ( ! ec_)
- {
- // buffer has local scope!
- boost::array< char, 1024 > buffer;
-
- // enqueue *this to read some bytes from the connection into buffer
- socket.async_read_some(
- boost::asio::buffer( buffer),
- boost::bind( & server::operator(), this->shared_from_this(), _1, _2) );
- // suspend() jumps back to operator(); asio reactor
- suspend();
-
- // finish and return
- if ( ec_) break;
-
- // enqueue *this to write data from buffer to connection
- boost::asio::async_write(
- socket,
- boost::asio::buffer( buffer, n_),
- boost::bind( & server::operator(), this->shared_from_this(), _1, _2) );
- // suspend() jumps back to operator(); asio reactor
- suspend();
- }
- }
- }
-
- server( boost::asio::io_service & io_service, short port) :
- continuation( boost::bind( & server::do_, this) ),
- acceptor_( io_service, boost::asio::ip::tcp::endpoint( boost::asio::ip::tcp::v4(), port) ),
- ec_(), n_( 0)
- {}
-
- public:
- typedef boost::shared_ptr< server > ptr_t;
-
- static ptr_t create( boost::asio::io_service & io_service, short port)
- { return ptr_t( new server( io_service, port) ); }
-
- void operator()( boost::system::error_code ec, size_t n)
- {
- ec_ = ec;
- n_ = n;
- // jump to coroutine (do_())
- resume();
- }
- };
-
- int main( int argc, char * argv[])
- {
- try
- {
- if ( argc != 2)
- {
- std::cerr << "Usage: echo_server <port>\n";
- return 1;
- }
- {
- boost::asio::io_service io_service;
- io_service.post(
- boost::bind(
- & server::operator(),
- server::create( io_service, boost::lexical_cast< short >( argv[1]) ),
- boost::system::error_code(), 0) );
- io_service.run();
- }
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
- catch ( std::exception const& e)
- { std::cerr << "Exception: " << e.what() << std::endl; }
-
- return EXIT_FAILURE;
- }
-
-[endsect]
Modified: trunk/libs/context/doc/config.qbk
==============================================================================
--- trunk/libs/context/doc/config.qbk (original)
+++ trunk/libs/context/doc/config.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -7,35 +7,34 @@
[section:installtion How to build and install]
-__boost_context__ must be built for the particular compiler(s) and CPU
-architecture(s)s being targeted. __boost_context__ includes assembly code and,
-therefore, requires GNU AS for supported POSIX systems, and MASM for Windows
-systems.
+__boost_context__ must be built for the particular compiler(s) and CPU architecture(s)s
+being targeted. __boost_context__ includes assembly code and, therefore, requires
+GNU AS for supported POSIX systems, and MASM for Windows systems.
-[note The architecture and address model are optional __boost_build__ properties
-that must be given on the bjam command line, as shown in the table below.]
+[note The architecture, instruction set, and address model are optional __boost_build__
+properties that must be given on the bjam command line, as shown in the table below.]
[table
[[][]]
[
[ARM, UNIX, aapcs, elf]
- [bjam toolset = gcc architecture = arm address-model = 32]
+ [bjam toolset = gcc architecture = arm]
]
[
[MIPS (32bit), UNIX, o32, elf]
- [bjam toolset = gcc architecture = mips1 address-model = 32]
+ [bjam toolset = gcc architecture = mips1]
]
[
[I386, UNIX, sysv, elf]
- [bjam toolset = gcc architecture = x86 address-model = 32]
+ [bjam toolset = gcc architecture = x86 instruction-set = i686 address-model = 32]
]
[
[I386, UNIX, sysv, elf]
- [bjam toolset = intel architecture = x86 address-model = 32]
+ [bjam toolset = intel architecture = x86 instruction-set = i686 address-model = 32]
]
[
[I386, Windows, ms, pe]
- [bjam toolset = msvc-9.0 architecture = x86 address-model = 32]
+ [bjam toolset = msvc-9.0 architecture = x86 instruction-set = i686 address-model = 32]
]
[
[PowerPc (32bit), UNIX, sysv, elf]
@@ -47,15 +46,15 @@
]
[
[X86_64, UNIX, sysv, elf]
- [bjam toolset = gcc architecture = x86 address-model = 64]
+ [bjam toolset = gcc architecture = x86 instruction-set = yorksfield address-model = 64]
]
[
[X86_64, UNIX, sysv, elf]
- [bjam toolset = intel architecture = x86 address-model = 64]
+ [bjam toolset = intel architecture = x86 instruction-set = yorksfield address-model = 64]
]
[
[X86_64, Windows, ms, pe]
- [bjam toolset = msvc-10.0 architecture = x86 address-model = 64]
+ [bjam toolset = msvc-10.0 architecture = x86 instruction-set = yorksfield address-model = 64]
]
]
[endsect]
Modified: trunk/libs/context/doc/context.qbk
==============================================================================
--- trunk/libs/context/doc/context.qbk (original)
+++ trunk/libs/context/doc/context.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -9,7 +9,7 @@
[quickbook 1.4]
[authors [Kowalke, Oliver]]
[copyright 2009 Oliver Kowalke]
- [purpose C++ Library for swiching different user contexts]
+ [purpose C++ Library for swiching different user ctx]
[category text]
[license
Distributed under the Boost Software License, Version 1.0.
@@ -21,8 +21,7 @@
[def __boost_build__ [*Boost.Build]]
[def __boost_context__ [*Boost.Context]]
-[def __boost_fiber__ [*Boost.Fiber]]
-[def __boost_move__ [*Boost.Move]]
+[def __boost_fiber__ [*Boost.Coroutine]]
[def __boost_task__ [*Boost.Task]]
[template cs_example_link[link_text] [link context.examples.enumerator [link_text]]]
@@ -43,7 +42,6 @@
[def __tls__ ['thread-local storage]]
[def __stack_allocator__ ['StackAllocator]]
[def __stack_allocator_concept__ ['StackAllocator concept]]
-[def __yield__ ['yield]]
[def __fcontext__ ['fcontext_t]]
[def __ucontext__ ['ucontext_t]]
@@ -52,25 +50,24 @@
[def __fls_free__ ['::FlsFree()]]
[def __bad_alloc__ ['std::bad_alloc]]
-[def __context__ [context_link ['context]]]
-[def __context_start__ ['context::start()]]
-[def __context_resume__ ['context::resume()]]
-[def __context_suspend__ ['context::suspend()]]
-[def __context_unwind__ ['context::unwind_stack()]]
-[def __forced_unwind__ ['forced_unwind]]
+[def __fc_base__ ['fc_base]]
+[def __fc_limit__ ['fc_limit]]
+[def __fc_link__ ['fc_link]]
+[def __start_fcontext__ ['start_fcontext()]]
+[def __jump_fcontext__ ['jump_fcontext()]]
+[def __make_fcontext__ ['make_fcontext()]]
[def __invalid_argument__ ['std::invalid_argument]]
[def __stack_alloc__ ['allocate()]]
[def __stack_dealloc__ ['deallocate()]]
[def __stack_helper__ ['stack_helper]]
+[def __yield__ ['yield]]
-[def __context_ns__ ['boost::contexts]]
+[def __context_ns__ ['boost::ctx]]
[include overview.qbk]
[include requirements.qbk]
-[include context_ref.qbk]
-[include stack_ref.qbk]
[include fcontext.qbk]
-[include examples.qbk]
+[include stack.qbk]
[include performance.qbk]
[include tested.qbk]
[include rationale.qbk]
Deleted: trunk/libs/context/doc/context.xml
==============================================================================
--- trunk/libs/context/doc/context.xml 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,3473 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE article PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<article id="context" last-revision="$Date: 2012/02/01 18:25:59 $" xmlns:xi="http://www.w3.org/2001/XInclude">
- <title>Context</title>
- <articleinfo>
- <authorgroup>
- <author>
- <firstname>Oliver</firstname> <surname>Kowalke</surname>
- </author>
- </authorgroup>
- <copyright>
- <year>2009</year> <holder>Oliver Kowalke</holder>
- </copyright>
- <legalnotice>
- <para>
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at <ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)
- </para>
- </legalnotice>
- <articlepurpose>
- C++ Library for swiching different user contexts
- </articlepurpose>
- <articlecategory name="category:text"></articlecategory>
- </articleinfo>
- <section id="context.overview">
- <title><link linkend="context.overview">Overview</link></title>
- <para>
- <emphasis role="bold">Boost.Context</emphasis> is a foundational library that
- provides a sort of cooperative multitasking on a single thread. By providing
- an abstraction of the current execution state in the current thread, including
- the stack (with local variables) and stack pointer, all registers and CPU flags,
- and the instruction pointer, a <link linkend="context.context.context"><emphasis>context</emphasis></link>
- instance represents a specific point in the application's execution path. This
- is useful for building higher-level abstractions, like <emphasis>coroutines</emphasis>,
- <emphasis>cooperative threads (userland threads)</emphasis> or an aquivalent
- to <ulink url="http://msdn.microsoft.com/en-us/library/9k7k7cf0%28v=vs.80%29.aspx">C#
- keyword <emphasis>yield</emphasis></ulink> in C++ ( <link linkend="context.examples.enumerator">see
- enumerator example</link>).
- </para>
- <para>
- A <link linkend="context.context.context"><emphasis>context</emphasis></link>
- provides the means to suspend the current execution path and to transfer execution
- control, thereby permitting another <link linkend="context.context.context"><emphasis>context</emphasis></link>
- to run on the current thread. This stateful transfer mechanism enables a <link
- linkend="context.context.context"><emphasis>context</emphasis></link> to suspend
- execution from within nested functions and, later, to resume from where it
- was suspended. While the execution path represented by a <link linkend="context.context.context"><emphasis>context</emphasis></link>
- only runs on a single thread, it can be migrated to another thread at any given
- time.
- </para>
- <para>
- A context switch between threads requires system calls (involving the OS kernel),
- which can cost thousands of CPU cycles on x86 CPUs. By contrast, transferring
- control among them requires only a few hundred CPU cycles because it does not
- involve system calls as it is done within a single thread.
- </para>
- <para>
- In order to use the classes and functions described here, you can either include
- the specific headers specified by the descriptions of each class or function,
- or include the master library header:
- </para>
-
-<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">all</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
-</programlisting>
- <para>
- which includes all the other headers in turn.
- </para>
- <para>
- All functions and classes are contained in the namespace <emphasis>boost::contexts</emphasis>.
- </para>
- <para>
- <emphasis role="bold">Boost.Context</emphasis> depends on <emphasis role="bold">Boost.Move</emphasis>.
- </para>
- </section>
- <section id="context.installtion">
- <title><link linkend="context.installtion">How to build and install</link></title>
- <para>
- <emphasis role="bold">Boost.Context</emphasis> must be built for the particular
- compiler(s) and CPU architecture(s)s being targeted. <emphasis role="bold">Boost.Context</emphasis>
- includes assembly code and, therefore, requires GNU AS for supported POSIX
- systems, and MASM for Windows systems.
- </para>
- <note>
- <para>
- The architecture, instruction set, and address model are optional <emphasis
- role="bold">Boost.Build</emphasis> properties that must be given on the bjam
- command line, as shown in the table below.
- </para>
- </note>
- <informaltable frame="all">
- <tgroup cols="2">
- <thead>
- <row>
- <entry>
- </entry>
- <entry>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>
- ARM, UNIX, aapcs, elf
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = gcc architecture = arm
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- MIPS (32bit), UNIX, o32, elf
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = gcc architecture = mips1 <footnote>
- <para>
- Because of a bug in shared_ptr you have to apply a patch 'patches/llsc-mips.patch'
- to shared_ptr or provide cxxflags="-mips2" at bjam command-line.
- </para>
- </footnote>
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- I386, UNIX, sysv, elf
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = gcc architecture = x86 instruction-set = i686 address-model
- = 32
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- I386, UNIX, sysv, elf
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = intel architecture = x86 instruction-set = i686 address-model
- = 32
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- I386, Windows, ms, pe
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = msvc-9.0 architecture = x86 instruction-set = i686
- address-model = 32
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- PowerPc (32bit), UNIX, sysv, elf
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = gcc architecture = power address-model = 32
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- PowerPc (64bit), UNIX, sysv, elf
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = gcc architecture = power address-model = 64
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- X86_64, UNIX, sysv, elf
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = gcc architecture = x86 instruction-set = yorksfield
- address-model = 64
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- X86_64, UNIX, sysv, elf
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = intel architecture = x86 instruction-set = yorksfield
- address-model = 64
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- X86_64, Windows, ms, pe
- </para>
- </entry>
- <entry>
- <para>
- bjam toolset = msvc-10.0 architecture = x86 instruction-set = yorksfield
- address-model = 64
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </section>
- <section id="context.context">
- <title><link linkend="context.context">Context</link></title>
- <para>
- Each instance of <link linkend="context.context.context"><emphasis>context</emphasis></link>
- represents a context (CPU registers and stack space) of execution or <emphasis>not-a-context</emphasis>.
- Objects of type <link linkend="context.context.context"><emphasis>context</emphasis></link>
- are moveable but not copyable and can be returned by a function.
- </para>
-
-<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">make_context</phrase><phrase role="special">();</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">f</phrase><phrase role="special">()</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">(</phrase> <phrase role="identifier">make_context</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
- <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
-<phrase role="special">}</phrase>
-</programlisting>
- <note>
- <para>
- <emphasis role="bold">Boost.Move</emphasis> is used to emulate rvalue references.
- </para>
- </note>
- <warning>
- <para>
- If contexts are used in a multithreaded application, they can migrated between
- threads, but must not reference <emphasis>thread-local storage</emphasis>.
- </para>
- </warning>
- <note>
- <para>
- If <emphasis>fiber-local storage</emphasis> is used on Windows, the user
- is responsible for calling <emphasis>::FlsAlloc()</emphasis>, <emphasis>::FlsFree()</emphasis>.
- </para>
- </note>
- <anchor id="context.context.executing_a_context"/>
- <bridgehead renderas="sect3">
- <link linkend="context.context.executing_a_context">Executing a context</link>
- </bridgehead>
- <para>
- A new context is created from a callable object (known as the <emphasis>context-function</emphasis>).
- The stack size, stack unwinding behavior, and context termination behavior
- are determined by additional arguments.
- </para>
- <para>
- The <link linkend="context.context.context"><emphasis>context</emphasis></link>
- constructor uses a <emphasis>StackAllocator concept</emphasis> to allocate
- an associated stack, and the destructor uses the same <emphasis>StackAllocator
- concept</emphasis> to deallocate the stack. The default <emphasis>StackAllocator
- concept</emphasis> is <emphasis>StackAllocator</emphasis>, but a custom stack-allocator
- can be passed to the constructor.
- </para>
- <para>
- Additional arguments needed by a <emphasis>context-function</emphasis> are
- supplied as additional arguments to the context constructor.
- </para>
-
-<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">f</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase>
-
-<phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">(</phrase> <phrase role="identifier">f</phrase><phrase role="special">,</phrase> <phrase role="number">42</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
-</programlisting>
- <para>
- The <emphasis>context-function</emphasis>, as well as its arguments, if any,
- are copied into the context's state. If a reference is required, use boost::ref.
- </para>
- <para>
- The maximum number of arguments of <emphasis>context-function</emphasis> is
- defined by BOOST_CONTEXT_ARITY (default is 10 and might be increased).
- </para>
- <para>
- Calling <emphasis>context::start()</emphasis> invokes the <emphasis>context-function</emphasis>
- in a newly created context complete with registers, flags, stack and instruction
- pointers. When control should be returned to the original calling context,
- call <emphasis>context::suspend()</emphasis>. The current context information
- (registers, flags, and stack and instruction pointers) is saved and the original
- context information is restored. Calling <emphasis>context::resume()</emphasis>
- resumes execution in the second context after saving the new state of the original
- context. Note that <emphasis>context::start()</emphasis> must be called first
- and only once.
- </para>
-
-<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">j</phrase><phrase role="special">)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="keyword">for</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">j</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fn(): local variable i == "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="comment">// save current context
-</phrase> <phrase role="comment">// value of local variable is preserved
-</phrase> <phrase role="comment">// transfer execution control back to main()
-</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
-
- <phrase role="comment">// ctx.resume() was called
-</phrase> <phrase role="comment">// execution control transfered back from main()
-</phrase> <phrase role="special">}</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="number">7</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
-
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"main() starts context ctx"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
- <phrase role="comment">// start the context ctx for the first time; enter fn()
-</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
-
- <phrase role="comment">// ctx.suspend() was called so we returned from start()
-</phrase> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"main() calls context ctx"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
- <phrase role="comment">// resume inside fn()
-</phrase> <phrase role="comment">// execution control is transfered to ctx
-</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
-
- <phrase role="comment">// ctx.suspend() was called within fn()
-</phrase> <phrase role="special">}</phrase>
-
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"Done"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">starts</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">0</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">2</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">3</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">4</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">5</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">6</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">Done</phrase>
-</programlisting>
- <warning>
- <para>
- Calling <emphasis>context::resume()</emphasis> from inside the same context
- results in undefined behaviour.
- </para>
- </warning>
- <note>
- <para>
- In contrast to threads, which are preemtive, <link linkend="context.context.context"><emphasis>context</emphasis></link>
- switches are cooperative (programmer controls when switch will happen). The
- kernel is not involved in the context switches.
- </para>
- </note>
- <anchor id="context.context.transfer_of_data"/>
- <bridgehead renderas="sect3">
- <link linkend="context.context.transfer_of_data">Transfer of data</link>
- </bridgehead>
- <para>
- The argument passed to <emphasis>context::resume()</emphasis>, in one context,
- is returned by <emphasis>context::suspend()</emphasis> in the other context.
- The intptr_t passed to <emphasis>context::suspend()</emphasis>, in one context,
- is returned by <emphasis>context::resume()</emphasis> (or <emphasis>context::start()</emphasis>,
- depending upon which function was called previously) in the other context.
- <emphasis>context::start()</emphasis> has no argument because it enters the
- start of the function, and there is no previous call to <emphasis>context::suspend()</emphasis>
- to return a value.
- </para>
-
-<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">()</phrase>
-<phrase role="special">{</phrase>
- <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">7</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fn(): local variable i == "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="comment">// save current context
-</phrase> <phrase role="comment">// transfer execution control back to caller
-</phrase> <phrase role="comment">// pass content of variable back
-</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">j</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">);</phrase>
- <phrase role="comment">// j == 10 because x == 10 in main()
-</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"transfered value: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">j</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
-
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"main() calls context ctx"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="comment">// start the context ctx for the first time
-</phrase> <phrase role="comment">// enter fn()
-</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">x</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
- <phrase role="comment">// x == 7 because i == 7 in fn()
-</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"transfered value: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">x</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="identifier">x</phrase> <phrase role="special">=</phrase> <phrase role="number">10</phrase><phrase role="special">;</phrase>
- <phrase role="comment">// ctx.suspend() was called so we returned from start()
-</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">(</phrase> <phrase role="identifier">x</phrase><phrase role="special">);</phrase>
-
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"Done"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">7</phrase>
- <phrase role="identifier">transfered</phrase> <phrase role="identifier">value</phrase><phrase role="special">:</phrase> <phrase role="number">7</phrase>
- <phrase role="identifier">transfered</phrase> <phrase role="identifier">value</phrase><phrase role="special">:</phrase> <phrase role="number">10</phrase>
- <phrase role="identifier">Done</phrase>
-</programlisting>
- <anchor id="context.context.exceptions_in__emphasis_context_function__emphasis_"/>
- <bridgehead renderas="sect3">
- <link linkend="context.context.exceptions_in__emphasis_context_function__emphasis_">Exceptions
- in <emphasis>context-function</emphasis></link>
- </bridgehead>
- <para>
- If the <emphasis>context-function</emphasis> emits an exception, std::terminate()
- is called.
- </para>
- <important>
- <para>
- Code executed by context must not prevent the propagation of the <emphasis>forced_unwind</emphasis>
- exception. Absorbing that exception will cause stack unwinding to fail. Thus,
- any code that catches all exceptions must rethrow the pending exception.
- </para>
- </important>
-
-<programlisting><phrase role="keyword">try</phrase>
-<phrase role="special">{</phrase>
- <phrase role="comment">// code that might throw
-</phrase><phrase role="special">}</phrase>
-<phrase role="keyword">catch</phrase><phrase role="special">(</phrase> <phrase role="identifier">forced_unwind</phrase><phrase role="special">)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="keyword">throw</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-<phrase role="keyword">catch</phrase><phrase role="special">(...)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="comment">// possibly not rethrow pending exception
-</phrase><phrase role="special">}</phrase>
-</programlisting>
- <anchor id="context.context.handling_execution_context_termination"/>
- <bridgehead renderas="sect3">
- <link linkend="context.context.handling_execution_context_termination">Handling
- execution context termination</link>
- </bridgehead>
- <para>
- The last context constructor argument is an enumerated type which determines
- what should happen when the context is complete (that is, when the <emphasis>context-function</emphasis>
- returns). The available values are <code><phrase role="identifier">return_to_caller</phrase></code>
- and <code><phrase role="identifier">exit_application</phrase></code>.
- </para>
- <para>
- When the last constructor argument is <code><phrase role="identifier">return_to_caller</phrase></code>,
- execution control is transferred back to the last invocation of <emphasis>context::start()</emphasis>
- or <emphasis>context::resume()</emphasis> when the context is complete, as
- shown in this example:
- </para>
-
-<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">j</phrase><phrase role="special">)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="keyword">for</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">j</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fn(): local variable i == "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="comment">// fn() returns
-</phrase> <phrase role="comment">// execution control is transfered back to main()
-</phrase><phrase role="special">}</phrase>
-
-<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="number">7</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
-
- <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
- <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"main() calls context ctx"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="comment">// fn() returned; the context is complete
-</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"Done"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">0</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">2</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">3</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">4</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">5</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">6</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">Done</phrase>
-</programlisting>
- <para>
- When the last constructor argument is <code><phrase role="identifier">exit_application</phrase></code>,
- the application terminates with an exit status of zero when the context is
- complete, as shown in the following example:
- </para>
-
-<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">j</phrase><phrase role="special">)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="keyword">for</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="identifier">j</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fn(): local variable i == "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="comment">// fn() returns
-</phrase> <phrase role="comment">// application will terminate
-</phrase><phrase role="special">}</phrase>
-
-<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="number">7</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">exit_application</phrase><phrase role="special">);</phrase>
-
- <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
- <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"main() calls context ctx"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="comment">// never reached
-</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">1</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">2</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">3</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">4</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">5</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="identifier">local</phrase> <phrase role="identifier">variable</phrase> <phrase role="identifier">i</phrase> <phrase role="special">==</phrase> <phrase role="number">6</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">calls</phrase> <phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase>
-</programlisting>
- <anchor id="context.context.chaining_contexts"/>
- <bridgehead renderas="sect3">
- <link linkend="context.context.chaining_contexts">Chaining contexts</link>
- </bridgehead>
- <para>
- <emphasis role="bold">Boost.Context</emphasis> provides the ability to chain
- context instances by passing a reference to another context, other than that
- <emphasis>not-a-context</emphasis>, as the last constructor argument. In this
- way, it is possible to create a chain of contexts. Depending on the <code><phrase
- role="identifier">do_return</phrase></code> argument in the constructor of
- the last context in the chain, the application terminates or execution control
- is transferred back to the last invocation of <emphasis>context::resume()</emphasis>.
- Each call of <emphasis>context::suspend()</emphasis>, for the chained context
- instances, will return to <emphasis>context::resume()</emphasis>.
- </para>
-
-<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx2</phrase><phrase role="special">;</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">fn1</phrase><phrase role="special">()</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fn1(): when this function returns fn2() will be entered"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">fn2</phrase><phrase role="special">()</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fn2(): first time entered"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">ctx2</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fn2(): second time entered\n"</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fn2(): return to main()"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
-<phrase role="special">{</phrase>
- <phrase role="special">{</phrase>
- <phrase role="comment">// ctx2 will return to ctx2.resume()
-</phrase> <phrase role="identifier">ctx2</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">fn2</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
-
- <phrase role="comment">// ctx1 defines ctx2 as its successor
-</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx1</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">fn1</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">ctx2</phrase><phrase role="special">);</phrase>
-
- <phrase role="comment">// transfer execution control to ctx1
-</phrase> <phrase role="comment">// fn1() is entered
-</phrase> <phrase role="identifier">ctx1</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
-
- <phrase role="comment">// ctx2.suspend() was called
-</phrase> <phrase role="special">}</phrase>
-
- <phrase role="comment">// ctx2 was already started by ctx1
-</phrase> <phrase role="identifier">ctx2</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
-
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"Done"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">fn1</phrase><phrase role="special">():</phrase> <phrase role="identifier">when</phrase> <phrase role="keyword">this</phrase> <phrase role="identifier">function</phrase> <phrase role="identifier">returns</phrase> <phrase role="identifier">fn2</phrase><phrase role="special">()</phrase> <phrase role="identifier">will</phrase> <phrase role="identifier">be</phrase> <phrase role="identifier">entered</phrase>
- <phrase role="identifier">fn2</phrase><phrase role="special">():</phrase> <phrase role="identifier">first</phrase> <phrase role="identifier">time</phrase> <phrase role="identifier">entered</phrase>
- <phrase role="identifier">fn2</phrase><phrase role="special">():</phrase> <phrase role="identifier">second</phrase> <phrase role="identifier">time</phrase> <phrase role="identifier">entered</phrase>
- <phrase role="identifier">fnd2</phrase><phrase role="special">():</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">to</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
- <phrase role="identifier">Done</phrase>
-</programlisting>
- <important>
- <para>
- Call <emphasis>context::start()</emphasis> only on the first context in a
- chain.
- </para>
- </important>
- <anchor id="context.context.stack_unwinding"/>
- <bridgehead renderas="sect3">
- <link linkend="context.context.stack_unwinding">Stack unwinding</link>
- </bridgehead>
- <para>
- 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 next to last argument of the context constructor, <code><phrase role="identifier">do_unwind</phrase></code>,
- indicates whether the destructor should unwind the stack. Stack unwinding can
- also be triggered by calling <emphasis>context::unwind_stack()</emphasis>.
- </para>
- <para>
- Stack unwinding assumes the following preconditions:
- </para>
- <itemizedlist>
- <listitem>
- <simpara>
- The context is not <emphasis>not-a-context</emphasis>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- The context is not complete
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- The context is not running
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- The context owns a stack
- </simpara>
- </listitem>
- </itemizedlist>
- <para>
- After unwinding, a <link linkend="context.context.context"><emphasis>context</emphasis></link>
- is complete.
- </para>
-
-<programlisting><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">;</phrase>
-
-<phrase role="keyword">struct</phrase> <phrase role="identifier">X</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">X</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"X()"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase>
-
- <phrase role="special">~</phrase><phrase role="identifier">X</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"~X()"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase>
-<phrase role="special">};</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">fn</phrase><phrase role="special">()</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">X</phrase> <phrase role="identifier">x</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">for</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"fn(): "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
- <phrase role="comment">// transfer execution control back to main()
-</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">ctx</phrase> <phrase role="special">=</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">);</phrase>
- <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
- <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="number">5</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="comment">// transfer execution control to fn()
-</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"ctx is complete: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">boolalpha</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="string">"\n"</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"call ctx.unwind_stack()"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="comment">// unwind the stack
-</phrase> <phrase role="comment">// X::~X() will be called
-</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">unwind_stack</phrase><phrase role="special">();</phrase> <phrase role="comment">// unwind the stack
-</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"ctx is complete: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">boolalpha</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="string">"\n"</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"Done"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">X</phrase><phrase role="special">()</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">0</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">1</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">2</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">3</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">4</phrase>
- <phrase role="identifier">fn</phrase><phrase role="special">():</phrase> <phrase role="number">5</phrase>
- <phrase role="identifier">ctx</phrase> <phrase role="identifier">is</phrase> <phrase role="identifier">complete</phrase><phrase role="special">:</phrase> <phrase role="keyword">false</phrase>
- <phrase role="identifier">call</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">.</phrase><phrase role="identifier">unwind_stack</phrase><phrase role="special">()</phrase>
- <phrase role="special">~</phrase><phrase role="identifier">X</phrase><phrase role="special">()</phrase>
- <phrase role="identifier">ctx</phrase> <phrase role="identifier">is</phrase> <phrase role="identifier">complete</phrase><phrase role="special">:</phrase> <phrase role="keyword">true</phrase>
- <phrase role="identifier">Done</phrase>
-</programlisting>
- <important>
- <para>
- You must not swallow <emphasis>forced_unwind</emphasis> exceptions!
- </para>
- </important>
- <section id="context.context.context">
- <title><link linkend="context.context.context">Class <code><phrase role="identifier">context</phrase></code></link></title>
-
-<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
-
-<phrase role="keyword">class</phrase> <phrase role="identifier">context</phrase>
-<phrase role="special">{</phrase>
-<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">context</phrase><phrase role="special">();</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">);</phrase>
- <phrase role="special">...</phrase>
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase role="special">,...,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A9</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,...,</phrase> <phrase role="identifier">A9</phrase><phrase role="special">,</phrase> <phrase role="identifier">a9</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
- <phrase role="special">...</phrase>
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase role="special">,...,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A9</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,...,</phrase> <phrase role="identifier">A9</phrase><phrase role="special">,</phrase> <phrase role="identifier">a9</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase ro
le="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">);</phrase>
- <phrase role="special">...</phrase>
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase role="special">,...,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A9</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,...,</phrase> <phrase role="identifier">A9</phrase><phrase role="special">,</phrase> <phrase role="identifier">a9</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
- <phrase role="special">...</phrase>
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase role="special">,...,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">A9</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase role="special">,...,</phrase> <phrase role="identifier">A9</phrase><phrase role="special">,</phrase> <phrase role="identifier">a9</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier
">alloc</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase role="special">);</phrase>
-
- <phrase role="special">~</phrase><phrase role="identifier">context</phrase><phrase role="special">();</phrase>
-
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
-
- <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">operator</phrase> <phrase role="identifier">unspecified</phrase><phrase role="special">-</phrase><phrase role="keyword">bool</phrase><phrase role="special">-</phrase><phrase role="identifier">type</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase role="special">!()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">other</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">bool</phrase> <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">bool</phrase> <phrase role="identifier">is_running</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase><phrase role="special">;</phrase>
-
- <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">start</phrase><phrase role="special">();</phrase>
-
- <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">resume</phrase><phrase role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
-
- <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">unwind_stack</phrase><phrase role="special">();</phrase>
-<phrase role="special">};</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">);</phrase>
-</programlisting>
- <anchor id="context.context.context._code__phrase_role__identifier__context__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__identifier__context__phrase__phrase_role__special______phrase___code_"><code><phrase
- role="identifier">context</phrase><phrase role="special">()</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Creates a context representing a <emphasis>not-a-context</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">template</phrase><phrase role="special"><</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase
- role="special">></phrase> <phrase role="identifier">context</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
- role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase>
- <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase
- role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
- <code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
- when ! is_stack_unbound().
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>.
- If <code><phrase role="identifier">do_unwind</phrase></code> is <code><phrase
- role="identifier">stack_unwind</phrase></code> the destructor of <code><phrase
- role="special">*</phrase><phrase role="keyword">this</phrase></code>
- unwinds the stack before destructing it. If <code><phrase role="identifier">do_return</phrase></code>
- is <code><phrase role="identifier">exit_application</phrase></code>
- the application exits with return code <code><phrase role="number">0</phrase></code>,
- otherwise execution control is transfered back to the invoker (<code><phrase
- role="identifier">resume</phrase><phrase role="special">()</phrase></code>
- returns).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- <emphasis>std::invalid_argument</emphasis> if a precondition is not
- satisfied.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator_
_phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___phrase_role__identifier__alloc
ator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">template</phrase><phrase role="special"><</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase
- role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase
- role="identifier">Allocator</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
- role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase>
- <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">flag_return_t</phrase> <phrase role="identifier">do_return</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase
- role="keyword">const</phrase><phrase role="special">&</phrase> <phrase
- role="identifier">alloc</phrase><phrase role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>.
- If <code><phrase role="identifier">do_unwind</phrase></code> is <code><phrase
- role="identifier">stack_unwind</phrase></code> the destructor of <code><phrase
- role="special">*</phrase><phrase role="keyword">this</phrase></code>
- unwinds the stack before destructing it. If <code><phrase role="identifier">do_return</phrase></code>
- is <code><phrase role="identifier">exit_application</phrase></code>
- the application exits with return code <code><phrase role="number">0</phrase></code>,
- otherwise execution control is transfered back to the invoker (<code><phrase
- role="identifier">resume</phrase><phrase role="special">()</phrase></code>
- returns).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- depends on <code><phrase role="identifier">alloc</phrase></code> if
- a precondition is not satisfied.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">template</phrase><phrase role="special"><</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase> <phrase
- role="special">></phrase> <phrase role="identifier">context</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
- role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase>
- <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">context</phrase> <phrase role="special">&</phrase>
- <phrase role="identifier">nxt</phrase><phrase role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
- <code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
- when ! is_stack_unbound(), <code><phrase role="identifier">nxt</phrase></code>
- is not a <emphasis>not-a-context</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>.
- If <code><phrase role="identifier">do_unwind</phrase></code> is <code><phrase
- role="identifier">stack_unwind</phrase></code> the destructor of <code><phrase
- role="special">*</phrase><phrase role="keyword">this</phrase></code>
- unwinds the stack before destructing it. execution control is transfered
- to <code><phrase role="identifier">nxt</phrase></code> if <code><phrase
- role="identifier">fn</phrase></code> returns (<code><phrase role="identifier">nxt</phrase></code>
- is linked).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- <emphasis>std::invalid_argument</emphasis> if a precondition is not
- satisfied.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___phrase_ro
le__identifier__allocatorconst__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___phra
se_role__identifier__allocatorconst__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">template</phrase><phrase role="special"><</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase
- role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase
- role="identifier">Allocator</phrase> <phrase role="special">></phrase>
- <phrase role="identifier">context</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
- role="identifier">size_t</phrase> <phrase role="identifier">size</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">flag_unwind_t</phrase>
- <phrase role="identifier">do_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">context</phrase> <phrase role="special">&</phrase>
- <phrase role="identifier">nxt</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">Allocatorconst</phrase><phrase role="special">&</phrase>
- <phrase role="identifier">alloc</phrase><phrase role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="identifier">nxt</phrase></code> is not a <emphasis>not-a-context</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>.
- If <code><phrase role="identifier">do_unwind</phrase></code> is <code><phrase
- role="identifier">stack_unwind</phrase></code> the destructor of <code><phrase
- role="special">*</phrase><phrase role="keyword">this</phrase></code>
- unwinds the stack before destructing it. execution control is transfered
- to <code><phrase role="identifier">nxt</phrase></code> if <code><phrase
- role="identifier">fn</phrase></code> returns (<code><phrase role="identifier">nxt</phrase></code>
- is linked).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- depends on <code><phrase role="identifier">alloc</phrase></code> if
- a precondition is not satisfied.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__phrase__phrase_role__special_________phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identif
ier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__phrase__phrase_role__special_________phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__id
entifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">template</phrase><phrase role="special"><</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase
- role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase
- role="identifier">A0</phrase><phrase role="special">,...</phrase> <phrase
- role="special">></phrase> <phrase role="identifier">context</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase
- role="special">,...,</phrase> <phrase role="identifier">std</phrase><phrase
- role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase
- role="identifier">size</phrase><phrase role="special">,</phrase> <phrase
- role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase>
- <phrase role="identifier">do_return</phrase><phrase role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
- <code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
- when ! is_stack_unbound().
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>
- (arguments <code><phrase role="identifier">A0</phrase></code>,... are
- bound to <code><phrase role="identifier">fn</phrase></code>). If <code><phrase
- role="identifier">do_unwind</phrase></code> is <code><phrase role="identifier">stack_unwind</phrase></code>
- the destructor of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- unwinds the stack before destructing it. If <code><phrase role="identifier">do_return</phrase></code>
- is <code><phrase role="identifier">exit_application</phrase></code>
- the application exits with return code <code><phrase role="number">0</phrase></code>,
- otherwise execution control is transfered back to the invoker (<code><phrase
- role="identifier">resume</phrase><phrase role="special">()</phrase></code>
- returns).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- <emphasis>std::invalid_argument</emphasis> if a precondition is not
- satisfied.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__phrase__phrase_role__special_________phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__fla
g_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__phrase__phrase_role__special_________phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier
__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_return_t__phrase___phrase_role__identifier__do_return__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">template</phrase><phrase role="special"><</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase
- role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase
- role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase
- role="special">,...</phrase> <phrase role="special">></phrase> <phrase
- role="identifier">context</phrase><phrase role="special">(</phrase> <phrase
- role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase
- role="special">,...,</phrase> <phrase role="identifier">std</phrase><phrase
- role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase
- role="identifier">size</phrase><phrase role="special">,</phrase> <phrase
- role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">flag_return_t</phrase>
- <phrase role="identifier">do_return</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">Allocator</phrase> <phrase role="keyword">const</phrase><phrase
- role="special">&</phrase> <phrase role="identifier">alloc</phrase><phrase
- role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
- <code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
- when ! is_stack_unbound().
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>
- (arguments <code><phrase role="identifier">A0</phrase></code>,... are
- bound to <code><phrase role="identifier">fn</phrase></code>). If <code><phrase
- role="identifier">do_unwind</phrase></code> is <code><phrase role="identifier">stack_unwind</phrase></code>
- the destructor of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- unwinds the stack before destructing it. If <code><phrase role="identifier">do_return</phrase></code>
- is <code><phrase role="identifier">exit_application</phrase></code>
- the application exits with return code <code><phrase role="number">0</phrase></code>,
- otherwise execution control is transfered back to the invoker (<code><phrase
- role="identifier">resume</phrase><phrase role="special">()</phrase></code>
- returns).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- depends on <code><phrase role="identifier">alloc</phrase></code> if
- a precondition is not satisfied.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__phrase__phrase_role__special_________phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identif
ier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__phrase__phrase_role__special_________phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__id
entifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">template</phrase><phrase role="special"><</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase
- role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase
- role="identifier">A0</phrase><phrase role="special">,...</phrase> <phrase
- role="special">></phrase> <phrase role="identifier">context</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase
- role="special">,...,</phrase> <phrase role="identifier">std</phrase><phrase
- role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase
- role="identifier">size</phrase><phrase role="special">,</phrase> <phrase
- role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase
- role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase
- role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="identifier">size</phrase></code> > minimum_stacksize(),
- <code><phrase role="identifier">size</phrase></code> < maximum_stacksize()
- when ! is_stack_unbound(), <code><phrase role="identifier">nxt</phrase></code>
- is not a <emphasis>not-a-context</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>
- (arguments<code><phrase role="identifier">A0</phrase></code>,... are
- bound to <code><phrase role="identifier">fn</phrase></code>). If <code><phrase
- role="identifier">do_unwind</phrase></code> is <code><phrase role="identifier">stack_unwind</phrase></code>
- the destructor of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- unwinds the stack before destructing it. execution control is transfered
- to <code><phrase role="identifier">nxt</phrase></code> if <code><phrase
- role="identifier">fn</phrase></code> returns (<code><phrase role="identifier">nxt</phrase></code>
- is linked).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- <emphasis>std::invalid_argument</emphasis> if a precondition is not
- satisfied.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__phrase__phrase_role__special_________phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier__fla
g_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__template__phrase__phrase_role__special___lt___phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__allocator__phrase__phrase_role__special_____phrase___phrase_role__keyword__typename__phrase___phrase_role__identifier__a0__phrase__phrase_role__special________phrase___phrase_role__special___gt___phrase___phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__fn__phrase___phrase_role__identifier__fn__phrase__phrase_role__special_____phrase___phrase_role__identifier__a0__phrase___phrase_role__identifier__a0__phrase__phrase_role__special_________phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__size__phrase__phrase_role__special_____phrase___phrase_role__identifier
__flag_unwind_t__phrase___phrase_role__identifier__do_unwind__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__nxt__phrase__phrase_role__special_____phrase___phrase_role__identifier__allocator__phrase___phrase_role__keyword__const__phrase__phrase_role__special___amp___phrase___phrase_role__identifier__alloc__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">template</phrase><phrase role="special"><</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">Fn</phrase><phrase
- role="special">,</phrase> <phrase role="keyword">typename</phrase> <phrase
- role="identifier">Allocator</phrase><phrase role="special">,</phrase> <phrase
- role="keyword">typename</phrase> <phrase role="identifier">A0</phrase><phrase
- role="special">,...</phrase> <phrase role="special">></phrase> <phrase
- role="identifier">context</phrase><phrase role="special">(</phrase> <phrase
- role="identifier">Fn</phrase> <phrase role="identifier">fn</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">A0</phrase> <phrase role="identifier">a0</phrase><phrase
- role="special">,...,</phrase> <phrase role="identifier">std</phrase><phrase
- role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase
- role="identifier">size</phrase><phrase role="special">,</phrase> <phrase
- role="identifier">flag_unwind_t</phrase> <phrase role="identifier">do_unwind</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase
- role="special">&</phrase> <phrase role="identifier">nxt</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">Allocator</phrase> <phrase
- role="keyword">const</phrase><phrase role="special">&</phrase> <phrase
- role="identifier">alloc</phrase><phrase role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="identifier">nxt</phrase></code> is not a <emphasis>not-a-context</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Creates a context which will execute <code><phrase role="identifier">fn</phrase></code>
- (arguments<code><phrase role="identifier">A0</phrase></code>,... are
- bound to <code><phrase role="identifier">fn</phrase></code>). If <code><phrase
- role="identifier">do_unwind</phrase></code> is <code><phrase role="identifier">stack_unwind</phrase></code>
- the destructor of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- unwinds the stack before destructing it. execution control is transfered
- to <code><phrase role="identifier">nxt</phrase></code> if <code><phrase
- role="identifier">fn</phrase></code> returns (<code><phrase role="identifier">nxt</phrase></code>
- is linked).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- depends on <code><phrase role="identifier">alloc</phrase></code> if
- a precondition is not satisfied.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__special_____phrase__phrase_role__identifier__context__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__special_____phrase__phrase_role__identifier__context__phrase__phrase_role__special______phrase___code_"><code><phrase
- role="special">~</phrase><phrase role="identifier">context</phrase><phrase
- role="special">()</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Destroys the instance and deallocates the stack. Unwinds the stack
- if it was specified in the constructor of <code><phrase role="special">*</phrase><phrase
- role="keyword">this</phrase></code>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp__amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__identifier__context__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp__amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="identifier">context</phrase><phrase role="special">(</phrase> <phrase
- role="identifier">context</phrase> <phrase role="special">&&</phrase>
- <phrase role="identifier">other</phrase><phrase role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Moves the internal data of <code><phrase role="identifier">other</phrase></code>
- to <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>.
- <code><phrase role="identifier">other</phrase></code> becomes <emphasis>not-a-context</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__keyword__operator__phrase__phrase_role__special______phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp__amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__keyword__operator__phrase__phrase_role__special______phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp__amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="identifier">context</phrase> <phrase role="special">&</phrase>
- <phrase role="keyword">operator</phrase><phrase role="special">=(</phrase>
- <phrase role="identifier">context</phrase> <phrase role="special">&&</phrase>
- <phrase role="identifier">other</phrase><phrase role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Destroys the internal data of <code><phrase role="special">*</phrase><phrase
- role="keyword">this</phrase></code> and moves the internal data of
- <code><phrase role="identifier">other</phrase></code> to <code><phrase
- role="special">*</phrase><phrase role="keyword">this</phrase></code>.
- <code><phrase role="identifier">other</phrase></code> becomes <emphasis>not-a-context</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__operator__phrase___phrase_role__identifier__unspecified__phrase__phrase_role__special_____phrase__phrase_role__keyword__bool__phrase__phrase_role__special_____phrase__phrase_role__identifier__type__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__operator__phrase___phrase_role__identifier__unspecified__phrase__phrase_role__special_____phrase__phrase_role__keyword__bool__phrase__phrase_role__special_____phrase__phrase_role__identifier__type__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"><code><phrase
- role="keyword">operator</phrase> <phrase role="identifier">unspecified</phrase><phrase
- role="special">-</phrase><phrase role="keyword">bool</phrase><phrase role="special">-</phrase><phrase
- role="identifier">type</phrase><phrase role="special">()</phrase> <phrase
- role="keyword">const</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- refers to <emphasis>not-a-context</emphasis>, the function returns
- false. Otherwise true.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__keyword__operator__phrase__phrase_role__special_______phrase___phrase_role__keyword__const__phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__keyword__operator__phrase__phrase_role__special_______phrase___phrase_role__keyword__const__phrase___code_"><code><phrase
- role="keyword">bool</phrase> <phrase role="keyword">operator</phrase><phrase
- role="special">!()</phrase> <phrase role="keyword">const</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- If <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- refers not to <emphasis>not-a-context</emphasis>, the function returns
- true. Otherwise false.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__void__phrase___phrase_role__identifier__swap__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__void__phrase___phrase_role__identifier__swap__phrase__phrase_role__special_____phrase___phrase_role__identifier__context__phrase___phrase_role__special___amp___phrase___phrase_role__identifier__other__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase
- role="special">&</phrase> <phrase role="identifier">other</phrase><phrase
- role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Swaps the internal data from <code><phrase role="special">*</phrase><phrase
- role="keyword">this</phrase></code> with the values of <code><phrase
- role="identifier">other</phrase></code>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_complete__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_complete__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"><code><phrase
- role="keyword">bool</phrase> <phrase role="identifier">is_complete</phrase><phrase
- role="special">()</phrase> <phrase role="keyword">const</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- is not a <emphasis>not-a-context</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Returns <code><phrase role="keyword">true</phrase></code> if context-function
- of <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- has returned.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_running__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_running__phrase__phrase_role__special______phrase___phrase_role__keyword__const__phrase___code_"><code><phrase
- role="keyword">bool</phrase> <phrase role="identifier">is_running</phrase><phrase
- role="special">()</phrase> <phrase role="keyword">const</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- is not a <emphasis>not-a-context</emphasis>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Returns <code><phrase role="keyword">true</phrase></code> if <code><phrase
- role="special">*</phrase><phrase role="keyword">this</phrase></code>
- is the currently active context.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__start__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__start__phrase__phrase_role__special______phrase___code_"><code><phrase
- role="identifier">intptr_t</phrase> <phrase role="identifier">start</phrase><phrase
- role="special">()</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- is not a <emphasis>not-a-context</emphasis>, <code><phrase role="special">!</phrase>
- <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase></code>
- and <code><phrase role="special">!</phrase> <phrase role="identifier">is_running</phrase><phrase
- role="special">()</phrase></code>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- <code><phrase role="identifier">start</phrase><phrase role="special">()</phrase></code>
- enters the <emphasis>context-function</emphasis> <code><phrase role="identifier">fn</phrase></code>
- with which the context was constructed. Upon return, the context was
- either left via <code><phrase role="identifier">suspend</phrase><phrase
- role="special">()</phrase></code> or the <emphasis>context-function</emphasis>
- returned.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- A intptr_t passed to <code><phrase role="identifier">suspend</phrase><phrase
- role="special">()</phrase></code> is returned if the context was left
- with <code><phrase role="identifier">suspend</phrase><phrase role="special">()</phrase></code>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__resume__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__vp__phrase___phrase_role__special_____phrase___phrase_role__number__0__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__resume__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__vp__phrase___phrase_role__special_____phrase___phrase_role__number__0__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="identifier">intptr_t</phrase> <phrase role="identifier">resume</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase
- role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase
- role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- is not a <emphasis>not-a-context</emphasis>, <code><phrase role="special">!</phrase>
- <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase></code>
- and <code><phrase role="special">!</phrase> <phrase role="identifier">is_running</phrase><phrase
- role="special">()</phrase></code>, <code><phrase role="identifier">start</phrase><phrase
- role="special">()</phrase></code> was called before.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- None, if *this was not suspended by a previous call to suspend(). Otherwise,
- execution control is transferred back to the caller of suspend(), thereby
- resuming *this. The argument, vp, will be returned by the previous
- call to suspend().
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__suspend__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__vp__phrase___phrase_role__special_____phrase___phrase_role__number__0__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__suspend__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__vp__phrase___phrase_role__special_____phrase___phrase_role__number__0__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="identifier">intptr_t</phrase> <phrase role="identifier">suspend</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase
- role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase
- role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- is not a <emphasis>not-a-context</emphasis>, <code><phrase role="special">!</phrase>
- <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase></code>
- and <code><phrase role="identifier">is_running</phrase><phrase role="special">()</phrase></code>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Transfers execution control to the caller of the most recent call to
- start() or resume(). The argument, vp, will be returned by start()
- or resume().
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- <emphasis>forced_unwind</emphasis> if <emphasis>context::unwind_stack()</emphasis>
- was called.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context._code__phrase_role__keyword__void__phrase___phrase_role__identifier__unwind_stack__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context._code__phrase_role__keyword__void__phrase___phrase_role__identifier__unwind_stack__phrase__phrase_role__special______phrase___code_"><code><phrase
- role="keyword">void</phrase> <phrase role="identifier">unwind_stack</phrase><phrase
- role="special">()</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- is not a <emphasis>not-a-context</emphasis>, <code><phrase role="special">!</phrase>
- <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase></code>
- and <code><phrase role="special">!</phrase> <phrase role="identifier">is_running</phrase><phrase
- role="special">()</phrase></code>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Destroys all objects allocated on the stack, owned by *this, in the
- reverse order of their allocation.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Postconditions:</term>
- <listitem>
- <para>
- <code><phrase role="special">*</phrase><phrase role="keyword">this</phrase></code>
- is not a <emphasis>not-a-context</emphasis> and <code><phrase role="identifier">is_complete</phrase><phrase
- role="special">()</phrase></code>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.context.context.non_member_function__code__phrase_role__identifier__swap__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.context.context.non_member_function__code__phrase_role__identifier__swap__phrase__phrase_role__special______phrase___code_">Non-member
- function <code><phrase role="identifier">swap</phrase><phrase role="special">()</phrase></code></link>
- </bridgehead>
-
-<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">swap</phrase><phrase role="special">(</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">l</phrase><phrase role="special">,</phrase> <phrase role="identifier">context</phrase> <phrase role="special">&</phrase> <phrase role="identifier">r</phrase><phrase role="special">);</phrase>
-</programlisting>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- As if 'l.swap( r)'.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </section>
- </section>
- <section id="context.stack">
- <title><link linkend="context.stack">Stack allocation</link></title>
- <para>
- A <link linkend="context.context.context"><emphasis>context</emphasis></link>
- requires a stack which will be allocated/deallocated by a <emphasis>StackAllocator</emphasis>.
- <emphasis role="bold">Boost.Context</emphasis> uses <code><phrase role="identifier">stack_allocator</phrase></code>
- by default but a customized <code><phrase role="identifier">stack</phrase>
- <phrase role="identifier">allocator</phrase></code> can be passed to the context
- constructor instead. If a context is constructed it invokes <emphasis>allocate()</emphasis>
- function and by its destruction the stack gets released by <emphasis>deallocate()</emphasis>.
- </para>
- <anchor id="context.stack._emphasis_stackallocator_concept__emphasis_"/>
- <bridgehead renderas="sect3">
- <link linkend="context.stack._emphasis_stackallocator_concept__emphasis_"><emphasis>StackAllocator
- concept</emphasis></link>
- </bridgehead>
- <para>
- A <emphasis>StackAllocator</emphasis> must satisfy the <emphasis>StackAllocator
- concept</emphasis> requirements shown in the following table, in which <code><phrase
- role="identifier">a</phrase></code> is an object of a <emphasis>StackAllocator</emphasis>
- type, <code><phrase role="identifier">p</phrase></code> is a <code><phrase
- role="keyword">void</phrase> <phrase role="special">*</phrase></code>, and
- <code><phrase role="identifier">s</phrase></code> is a <code><phrase role="identifier">std</phrase><phrase
- role="special">::</phrase><phrase role="identifier">size_t</phrase></code>:
- </para>
- <informaltable frame="all">
- <tgroup cols="3">
- <thead>
- <row>
- <entry>
- <para>
- expression
- </para>
- </entry>
- <entry>
- <para>
- return type
- </para>
- </entry>
- <entry>
- <para>
- notes
- </para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>
- <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
- role="identifier">allocate</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">s</phrase><phrase role="special">)</phrase></code>
- </para>
- </entry>
- <entry>
- <para>
- <code><phrase role="keyword">void</phrase> <phrase role="special">*</phrase></code>
- </para>
- </entry>
- <entry>
- <para>
- returns a pointer to <code><phrase role="identifier">s</phrase></code>
- bytes allocated from the stack
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- <code><phrase role="identifier">a</phrase><phrase role="special">.</phrase><phrase
- role="identifier">deallocate</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">p</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">s</phrase><phrase role="special">)</phrase></code>
- </para>
- </entry>
- <entry>
- <para>
- <code><phrase role="keyword">void</phrase></code>
- </para>
- </entry>
- <entry>
- <para>
- deallocates <code><phrase role="identifier">s</phrase></code> bytes
- of memory beginning at <code><phrase role="identifier">p</phrase></code>,
- a pointer previously returned by <code><phrase role="identifier">a</phrase><phrase
- role="special">.</phrase><phrase role="identifier">allocate</phrase><phrase
- role="special">()</phrase></code>
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- <important>
- <para>
- The implementation of <code><phrase role="identifier">allocate</phrase><phrase
- role="special">()</phrase></code> might include logic to protect against
- exceeding the context's available stack size rather than leaving it as undefined
- behaviour.
- </para>
- </important>
- <important>
- <para>
- Calling <code><phrase role="identifier">deallocate</phrase><phrase role="special">()</phrase></code>
- with a pointer not returned by <code><phrase role="identifier">allocate</phrase><phrase
- role="special">()</phrase></code> results in undefined behaviour.
- </para>
- </important>
- <note>
- <para>
- The stack is not required to be aligned; alignment takes place inside <code><phrase
- role="identifier">boost_fcontext_make</phrase><phrase role="special">()</phrase></code>.
- </para>
- </note>
- <section id="context.stack.stack_allocator">
- <title><link linkend="context.stack.stack_allocator">Class <code><phrase role="identifier">stack_allocator</phrase></code></link></title>
- <para>
- <emphasis role="bold">Boost.Context</emphasis> provides a <emphasis>StackAllocator</emphasis>
- <code><phrase role="identifier">stack_allocator</phrase></code> which models
- the <emphasis>StackAllocator concept</emphasis> concept. It appends a <emphasis>guard-page</emphasis>
- to protect against exceeding the stack. If the guard page is accessed (read
- or write operation) a segmentation fault/access violation is generated by
- the operating system.
- </para>
- </section>
- <section id="context.stack.stack_helper">
- <title><link linkend="context.stack.stack_helper">Helper functions</link></title>
- <para>
- <emphasis role="bold">Boost.Context</emphasis> provides easy access to the
- stack related limits defined by the environment.
- </para>
-
-<programlisting><phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">default_stacksize</phrase><phrase role="special">();</phrase>
-
-<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">minimum_stacksize</phrase><phrase role="special">();</phrase>
-
-<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">maximum_stacksize</phrase><phrase role="special">();</phrase>
-
-<phrase role="keyword">bool</phrase> <phrase role="identifier">is_stack_unbound</phrase><phrase role="special">();</phrase>
-
-<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">pagesize</phrase><phrase role="special">();</phrase>
-
-<phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">page_count</phrase><phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">stacksize</phrase><phrase role="special">);</phrase>
-</programlisting>
- <anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__default_stacksize__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__default_stacksize__phrase__phrase_role__special______phrase___code_"><code><phrase
- role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
- <phrase role="identifier">default_stacksize</phrase><phrase role="special">()</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- Returns a default stack size, which may be platform specific. The present
- implementation returns a value of 256 kB.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__minimum_stacksize__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__minimum_stacksize__phrase__phrase_role__special______phrase___code_"><code><phrase
- role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
- <phrase role="identifier">minimum_stacksize</phrase><phrase role="special">()</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- Returns the minimum size in bytes of stack defined by the environment.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__maximum_stacksize__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__maximum_stacksize__phrase__phrase_role__special______phrase___code_"><code><phrase
- role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
- <phrase role="identifier">maximum_stacksize</phrase><phrase role="special">()</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Preconditions:</term>
- <listitem>
- <para>
- <code><phrase role="identifier">is_stack_unbound</phrase><phrase role="special">()</phrase></code>
- returns <code><phrase role="keyword">false</phrase></code>.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- Returns the maximum size in bytes of stack defined by the environment.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.stack.stack_helper._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_stack_unbound__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.stack.stack_helper._code__phrase_role__keyword__bool__phrase___phrase_role__identifier__is_stack_unbound__phrase__phrase_role__special______phrase___code_"><code><phrase
- role="keyword">bool</phrase> <phrase role="identifier">is_stack_unbound</phrase><phrase
- role="special">()</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- Returns <code><phrase role="keyword">true</phrase></code> if the environment
- defines no limit for the size of a stack.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__pagesize__phrase__phrase_role__special______phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__pagesize__phrase__phrase_role__special______phrase___code_"><code><phrase
- role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
- <phrase role="identifier">pagesize</phrase><phrase role="special">()</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- Returns how many bytes the operating system allocates for one page.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__page_count__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__stacksize__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.stack.stack_helper._code__phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__page_count__phrase__phrase_role__special_____phrase___phrase_role__identifier__std__phrase__phrase_role__special______phrase__phrase_role__identifier__size_t__phrase___phrase_role__identifier__stacksize__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase>
- <phrase role="identifier">page_count</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase
- role="identifier">size_t</phrase> <phrase role="identifier">stacksize</phrase><phrase
- role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- Returns how many pages have to be allocated for a stack of <code><phrase
- role="identifier">stacksize</phrase></code> bytes.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Throws:</term>
- <listitem>
- <para>
- Nothing.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </section>
- </section>
- <section id="context.capi">
- <title><link linkend="context.capi">Low level API (boost_fcontext_t)</link></title>
- <para>
- <emphasis role="bold">Boost.Context</emphasis> uses and provides a low level
- API which implements the execution control transfer mechanism. The boost_fcontext_t
- API provides a similar interface like <ulink url="http://www.kernel.org/doc/man-pages/online/pages/man2/getcontext.2.html">ucontext_t</ulink>.
- boost_fcontext_t and its functions are located in the global namespace and
- the functions are declared as extern "C".
- </para>
-
-<programlisting><phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">cstdio</phrase><phrase role="special">></phrase>
-<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">cstdlib</phrase><phrase role="special">></phrase>
-<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">cstring</phrase><phrase role="special">></phrase>
-<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">vector</phrase><phrase role="special">></phrase>
-
-<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">cstdint</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
-<phrase role="preprocessor">#include</phrase> <phrase role="special"><</phrase><phrase role="identifier">boost</phrase><phrase role="special">/</phrase><phrase role="identifier">context</phrase><phrase role="special">/</phrase><phrase role="identifier">fcontext</phrase><phrase role="special">.</phrase><phrase role="identifier">hpp</phrase><phrase role="special">></phrase>
-
-<phrase role="identifier">boost_fcontext_t</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">,</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">;</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">f1</phrase><phrase role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">p</phrase><phrase role="special">)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase> <phrase role="identifier">p</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f1() started\n"</phrase><phrase role="special">);</phrase>
- <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f1: call boost_fcontext_jump( & fc1, & fc2, 0)\n"</phrase><phrase role="special">);</phrase>
- <phrase role="comment">// jump to context fc2
-</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
- <phrase role="comment">// returned from context fc2 (function f2())
-</phrase> <phrase role="comment">// return from function f1()
-</phrase> <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f1() returns\n"</phrase><phrase role="special">);</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">f2</phrase><phrase role="special">(</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">p</phrase><phrase role="special">)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="special">(</phrase><phrase role="keyword">void</phrase><phrase role="special">)</phrase> <phrase role="identifier">p</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f2() started\n"</phrase><phrase role="special">);</phrase>
- <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f2: call boost_fcontext_jump( & fc2, & fc1, 0)\n"</phrase><phrase role="special">);</phrase>
- <phrase role="comment">// jump to context fc1
-</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
- <phrase role="comment">// never reached
-</phrase> <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"f2() returns\n"</phrase><phrase role="special">);</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
-<phrase role="special">{</phrase>
- <phrase role="comment">// creat two protected stacks
-</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">protected_stack</phrase> <phrase role="identifier">b1</phrase><phrase role="special">(</phrase><phrase role="number">262144</phrase><phrase role="special">);</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">protected_stack</phrase> <phrase role="identifier">b2</phrase><phrase role="special">(</phrase><phrase role="number">262144</phrase><phrase role="special">);</phrase>
-
- <phrase role="comment">// let context fc1 use stack b1
-</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_base</phrase> <phrase role="special">=</phrase> <phrase role="identifier">b1</phrase><phrase role="special">.</phrase><phrase role="identifier">address</phrase><phrase role="special">();</phrase>
- <phrase role="identifier">fc1</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_limit</phrase> <phrase role="special">=</phrase>
- <phrase role="keyword">static_cast</phrase><phrase role="special"><</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_base</phrase><phrase role="special">)</phrase> <phrase role="special">-</phrase> <phrase role="identifier">b1</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">();</phrase>
- <phrase role="comment">// link context fcm;
-</phrase> <phrase role="comment">// fcm will be invoked after fc1 terminated
-</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_link</phrase> <phrase role="special">=</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">;</phrase>
- <phrase role="comment">// context fc1 used f1() as context function
-</phrase> <phrase role="identifier">boost_fcontext_make</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="identifier">f1</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
-
- <phrase role="comment">// let context fc2 use stack b2
-</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_base</phrase> <phrase role="special">=</phrase> <phrase role="identifier">b2</phrase><phrase role="special">.</phrase><phrase role="identifier">address</phrase><phrase role="special">();</phrase>
- <phrase role="identifier">fc2</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_limit</phrase> <phrase role="special">=</phrase>
- <phrase role="keyword">static_cast</phrase><phrase role="special"><</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">.</phrase><phrase role="identifier">fc_stack</phrase><phrase role="special">.</phrase><phrase role="identifier">ss_base</phrase><phrase role="special">)</phrase> <phrase role="special">-</phrase> <phrase role="identifier">b2</phrase><phrase role="special">.</phrase><phrase role="identifier">size</phrase><phrase role="special">();</phrase>
- <phrase role="comment">// context fc2 used f2() as context function
-</phrase> <phrase role="identifier">boost_fcontext_make</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="identifier">f2</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
-
- <phrase role="comment">// start context f1; entering f1()
-</phrase> <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase><phrase role="identifier">stderr</phrase><phrase role="special">,</phrase><phrase role="string">"main: call boost_fcontext_start( & fcm, & fc1)\n"</phrase><phrase role="special">);</phrase>
- <phrase role="identifier">boost_fcontext_start</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">);</phrase>
-
- <phrase role="identifier">fprintf</phrase><phrase role="special">(</phrase> <phrase role="identifier">stderr</phrase><phrase role="special">,</phrase> <phrase role="string">"main() returns\n"</phrase><phrase role="special">);</phrase>
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">:</phrase> <phrase role="identifier">call</phrase> <phrase role="identifier">boost_fcontext_start</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fcm</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">)</phrase>
- <phrase role="identifier">f1</phrase><phrase role="special">()</phrase> <phrase role="identifier">started</phrase>
- <phrase role="identifier">f1</phrase><phrase role="special">:</phrase> <phrase role="identifier">call</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase>
- <phrase role="identifier">f2</phrase><phrase role="special">()</phrase> <phrase role="identifier">started</phrase>
- <phrase role="identifier">f2</phrase><phrase role="special">:</phrase> <phrase role="identifier">call</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc2</phrase><phrase role="special">,</phrase> <phrase role="special">&</phrase> <phrase role="identifier">fc1</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase>
- <phrase role="identifier">f1</phrase><phrase role="special">()</phrase> <phrase role="identifier">returns</phrase>
- <phrase role="identifier">main</phrase><phrase role="special">()</phrase> <phrase role="identifier">returns</phrase>
-</programlisting>
- <para>
- Function <code><phrase role="identifier">boost_fcontext_start</phrase><phrase
- role="special">()</phrase></code> enters the <emphasis>context-function</emphasis>
- <code><phrase role="identifier">f1</phrase><phrase role="special">()</phrase></code>
- by starting context fc1 (context fcm saves the registers of <code><phrase role="identifier">main</phrase><phrase
- role="special">()</phrase></code>). For jumping between context's fc1 and fc2
- <code><phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">()</phrase></code>
- is called. Because context fcm is chained to fc1, <code><phrase role="identifier">main</phrase><phrase
- role="special">()</phrase></code> is entered (returning from <code><phrase
- role="identifier">boost_fcontext_start</phrase><phrase role="special">()</phrase></code>)
- after context fc1 becomes complete (return from <code><phrase role="identifier">f1</phrase><phrase
- role="special">()</phrase></code>).
- </para>
- <important>
- <para>
- The low level API is the part to port to new platforms.
- </para>
- </important>
- <section id="context.capi.boost_fcontext">
- <title><link linkend="context.capi.boost_fcontext">Struct <code><phrase role="identifier">boost_fcontext_t</phrase></code>
- and related functions</link></title>
-<programlisting><phrase role="keyword">typedef</phrase> <phrase role="keyword">struct</phrase> <phrase role="identifier">boost_fcontext_stack</phrase> <phrase role="identifier">boost_fcontext_stack_t</phrase><phrase role="special">;</phrase>
-<phrase role="keyword">struct</phrase> <phrase role="identifier">boost_fcontext_stack</phrase>
-<phrase role="special">{</phrase>
- <phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ss_base</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">void</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ss_limit</phrase><phrase role="special">;</phrase>
-<phrase role="special">};</phrase>
-
-<phrase role="keyword">typedef</phrase> <phrase role="keyword">struct</phrase> <phrase role="identifier">boost_fcontext</phrase> <phrase role="identifier">boost_fcontext_t</phrase><phrase role="special">;</phrase>
-<phrase role="keyword">struct</phrase> <phrase role="identifier">boost_fcontext</phrase>
-<phrase role="special">{</phrase>
- <phrase role="special"><</phrase> <phrase role="identifier">platform</phrase> <phrase role="identifier">specific</phrase> <phrase role="special">></phrase>
-
- <phrase role="identifier">boost_fcontext_stack_t</phrase> <phrase role="identifier">fc_stack</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fc_link</phrase><phrase role="special">;</phrase>
-<phrase role="special">};</phrase>
-
-<phrase role="identifier">intptr_t</phrase> <phrase role="identifier">boost_fcontext_start</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ofc</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase> <phrase role="identifier">nfc</phrase><phrase role="special">);</phrase>
-<phrase role="identifier">intptr_t</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="special">*</phrase> <phrase role="identifier">ofc</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="keyword">const</phrase><phrase role="special">*</phrase> <phrase role="identifier">nfc</phrase><phrase role="special">,</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase><phrase role="special">);</phrase>
-<phrase role="keyword">void</phrase> <phrase role="identifier">boost_fcontext_make</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase> <phrase role="special">*</phrase> <phrase role="identifier">fc</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">(*</phrase> <phrase role="identifier">fn</phrase><phrase role="special">)(</phrase><phrase role="keyword">void</phrase><phrase role="special">*),</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">p</phrase><phrase role="special">);</phrase>
-</programlisting>
- <anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__ss_base__phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__ss_base__phrase___code_"><code><phrase
- role="identifier">ss_base</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Member:</term>
- <listitem>
- <para>
- Pointer to the top of the stack.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__ss_limit__phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__ss_limit__phrase___code_"><code><phrase
- role="identifier">ss_limit</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Member:</term>
- <listitem>
- <para>
- Pointer to the bottom of the stack.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__fc_stack__phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__fc_stack__phrase___code_"><code><phrase
- role="identifier">fc_stack</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Member:</term>
- <listitem>
- <para>
- Tracks the memory for the context's stack.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__fc_link__phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__fc_link__phrase___code_"><code><phrase
- role="identifier">fc_link</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Member:</term>
- <listitem>
- <para>
- The address of the next context link in a chain, if any.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__boost_fcontext_start__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase_____phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__boost_fcontext_start__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase_____phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="identifier">intptr_t</phrase> <phrase role="identifier">boost_fcontext_start</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
- <phrase role="special">*</phrase> <phrase role="identifier">ofc</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
- <phrase role="special">*</phrase> <phrase role="identifier">nfc</phrase><phrase
- role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Stores the current context data (stack pointer, instruction pointer,
- and CPU registers) to <code><phrase role="special">*</phrase><phrase
- role="identifier">ofc</phrase></code> and restores the context data
- from <code><phrase role="special">*</phrase><phrase role="identifier">nfc</phrase></code>,
- which implies jumping to <code><phrase role="special">*</phrase><phrase
- role="identifier">nfc</phrase></code>'s execution context. This function
- must be called when first entering <code><phrase role="special">*</phrase><phrase
- role="identifier">nfc</phrase></code>'s execution context.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- The result of calling <code><phrase role="identifier">boost_fcontext_jump</phrase><phrase
- role="special">()</phrase></code>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.capi.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__boost_fcontext_jump__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.capi.boost_fcontext._code__phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__boost_fcontext_jump__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__ofc__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__nfc__phrase__phrase_role__special_____phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="identifier">intptr_t</phrase> <phrase role="identifier">boost_fcontext_jump</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
- <phrase role="special">*</phrase> <phrase role="identifier">ofc</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
- <phrase role="special">*</phrase> <phrase role="identifier">nfc</phrase><phrase
- role="special">,</phrase> <phrase role="identifier">intptr_t</phrase> <phrase
- role="identifier">p</phrase><phrase role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Stores the current context data (stack pointer, instruction pointer,
- and CPU registers) to <code><phrase role="special">*</phrase><phrase
- role="identifier">ofc</phrase></code> and restores the context data
- from <code><phrase role="special">*</phrase><phrase role="identifier">nfc</phrase></code>,
- which implies jumping to <code><phrase role="special">*</phrase><phrase
- role="identifier">nfc</phrase></code>'s execution context. The intptr_t
- argument, <code><phrase role="identifier">p</phrase></code>, is passed
- to the current context to be returned by the most recent call to <code><phrase
- role="identifier">boost_fcontext_start</phrase><phrase role="special">()</phrase></code>
- or <code><phrase role="identifier">boost_fcontext_jump</phrase><phrase
- role="special">()</phrase></code> in the same thread.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Returns:</term>
- <listitem>
- <para>
- The third pointer argument passed to the most recent call to <code><phrase
- role="identifier">boost_fcontext_jump</phrase><phrase role="special">()</phrase></code>,
- if any.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <anchor id="context.capi.boost_fcontext._code__phrase_role__keyword__void__phrase___phrase_role__identifier__boost_fcontext_make__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__fc__phrase__phrase_role__special_____phrase___phrase_role__keyword__void__phrase__phrase_role__special______phrase__phrase_role__identifier__fn__phrase__phrase_role__special______phrase__phrase_role__identifier__intptr_t__phrase__phrase_role__special______phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___code_"/>
- <bridgehead renderas="sect4">
- <link linkend="context.capi.boost_fcontext._code__phrase_role__keyword__void__phrase___phrase_role__identifier__boost_fcontext_make__phrase__phrase_role__special_____phrase___phrase_role__identifier__boost_fcontext_t__phrase___phrase_role__special_____phrase___phrase_role__identifier__fc__phrase__phrase_role__special_____phrase___phrase_role__keyword__void__phrase__phrase_role__special______phrase__phrase_role__identifier__fn__phrase__phrase_role__special______phrase__phrase_role__identifier__intptr_t__phrase__phrase_role__special______phrase___phrase_role__identifier__intptr_t__phrase___phrase_role__identifier__p__phrase__phrase_role__special_____phrase___code_"><code><phrase
- role="keyword">void</phrase> <phrase role="identifier">boost_fcontext_make</phrase><phrase
- role="special">(</phrase> <phrase role="identifier">boost_fcontext_t</phrase>
- <phrase role="special">*</phrase> <phrase role="identifier">fc</phrase><phrase
- role="special">,</phrase> <phrase role="keyword">void</phrase><phrase role="special">(*</phrase><phrase
- role="identifier">fn</phrase><phrase role="special">)(</phrase><phrase role="identifier">intptr_t</phrase><phrase
- role="special">),</phrase> <phrase role="identifier">intptr_t</phrase> <phrase
- role="identifier">p</phrase><phrase role="special">)</phrase></code></link>
- </bridgehead>
- <variablelist>
- <title></title>
- <varlistentry>
- <term>Precondition:</term>
- <listitem>
- <para>
- A stack is applied to <code><phrase role="special">*</phrase><phrase
- role="identifier">fc</phrase></code> before <code><phrase role="identifier">boost_fcontext_make</phrase><phrase
- role="special">()</phrase></code> is called. If a successor context
- should be executed after <code><phrase role="special">*</phrase><phrase
- role="identifier">fc</phrase></code> finishes the address of the successor
- context must be stored ir <code><phrase role="identifier">fc</phrase><phrase
- role="special">-></phrase><phrase role="identifier">fc_link</phrase></code>.
- The application exits otherwise.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Effects:</term>
- <listitem>
- <para>
- Modifies <code><phrase role="special">*</phrase><phrase role="identifier">fc</phrase></code>
- in order to execute <code><phrase role="identifier">fn</phrase></code>
- with argument <code><phrase role="identifier">p</phrase></code> when
- the context is activated next.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </section>
- </section>
- <section id="context.examples">
- <title><link linkend="context.examples">Examples</link></title>
- <section id="context.examples.enumerator">
- <title><link linkend="context.examples.enumerator">Enumerator</link></title>
- <para>
- Class <code><phrase role="identifier">power</phrase></code> computes the
- power of <code><phrase role="identifier">number</phrase></code> for the exponents
- in the range from <code><phrase role="number">1</phrase></code> to <code><phrase
- role="identifier">number</phrase></code> (constructor arguments).
- </para>
-
-<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">power</phrase>
-<phrase role="special">{</phrase>
-<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">power</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">number</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">exponent</phrase><phrase role="special">);</phrase>
-
- <phrase role="keyword">bool</phrase> <phrase role="identifier">get</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="special">&</phrase> <phrase role="identifier">data</phrase><phrase role="special">);</phrase>
-<phrase role="special">};</phrase>
-</programlisting>
- <para>
- Each call to <code><phrase role="identifier">power</phrase><phrase role="special">::</phrase><phrase
- role="identifier">get</phrase><phrase role="special">()</phrase></code> returns
- a boolean indicating a vaild result. The reference argument <code><phrase
- role="identifier">data</phrase></code> contains the computed result.
- </para>
-
-<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">()</phrase>
-<phrase role="special">{</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">power</phrase> <phrase role="identifier">pw</phrase><phrase role="special">(</phrase> <phrase role="number">2</phrase><phrase role="special">,</phrase> <phrase role="number">8</phrase><phrase role="special">);</phrase>
- <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase>
- <phrase role="comment">// pw.get() returns the computed result
-</phrase> <phrase role="comment">// for each value from 1 to 8
-</phrase> <phrase role="comment">// return value of pw.get() indicates that
-</phrase> <phrase role="comment">// a valid result
-</phrase> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">pw</phrase><phrase role="special">.</phrase><phrase role="identifier">get</phrase><phrase role="special">(</phrase> <phrase role="identifier">i</phrase><phrase role="special">)</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase>
- <phrase role="special">}</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"\nDone"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
- <phrase role="number">2</phrase> <phrase role="number">4</phrase> <phrase role="number">8</phrase> <phrase role="number">16</phrase> <phrase role="number">32</phrase> <phrase role="number">64</phrase> <phrase role="number">128</phrase> <phrase role="number">256</phrase>
- <phrase role="identifier">Done</phrase>
-</programlisting>
- <para>
- In <code><phrase role="identifier">main</phrase><phrase role="special">()</phrase></code>
- an instance of <code><phrase role="identifier">power</phrase></code> is constructed,
- computing the power of 2 for exponents in the range from 1 to 8 by each call
- to <code><phrase role="identifier">power</phrase><phrase role="special">::</phrase><phrase
- role="identifier">get</phrase><phrase role="special">()</phrase></code>.
- </para>
- <para>
- It is intended to compute the numbers in a loop and transfer each result
- to the caller without disrupting the loop.
- </para>
- <para>
- <emphasis role="bold">Boost.Context</emphasis> can be used to implement an
- equivalent to C#'s <code><phrase role="identifier">yield</phrase></code>
- facility (C# provides the keywords <code><phrase role="identifier">yield</phrase>
- <phrase role="keyword">return</phrase></code> and <code><phrase role="identifier">yield</phrase>
- <phrase role="keyword">break</phrase></code>). For this purpose helper-template
- <code><phrase role="identifier">enumerator</phrase></code> is defined containing
- the private member <code><phrase role="identifier">ctx_</phrase></code> executing
- <code><phrase role="identifier">enumerate</phrase><phrase role="special">()</phrase></code>
- as <emphasis>context-function</emphasis>.
- </para>
-
-<programlisting><phrase role="keyword">template</phrase><phrase role="special"><</phrase> <phrase role="keyword">typename</phrase> <phrase role="identifier">T</phrase> <phrase role="special">></phrase>
-<phrase role="keyword">class</phrase> <phrase role="identifier">enumerator</phrase> <phrase role="special">{</phrase>
-<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">bool</phrase> <phrase role="identifier">complete_</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">bool</phrase> <phrase role="identifier">do_unwind_</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">bool</phrase> <phrase role="identifier">started_</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">static</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">run</phrase><phrase role="special">(</phrase> <phrase role="identifier">enumerator</phrase> <phrase role="special">*</phrase> <phrase role="identifier">self</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase> <phrase role="identifier">self</phrase><phrase role="special">-></phrase><phrase role="identifier">enumerate</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
-
-<phrase role="keyword">protected</phrase><phrase role="special">:</phrase>
- <phrase role="keyword">virtual</phrase> <phrase role="keyword">void</phrase> <phrase role="identifier">enumerate</phrase><phrase role="special">()</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">yield_return</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">v</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="keyword">reinterpret_cast</phrase><phrase role="special"><</phrase> <phrase role="identifier">intptr_t</phrase> <phrase role="special">>(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">v</phrase><phrase role="special">);</phrase>
- <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">(</phrase> <phrase role="identifier">vp</phrase><phrase role="special">);</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">yield_break</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">complete_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-
-<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">enumerator</phrase><phrase role="special">(</phrase> <phrase role="keyword">bool</phrase> <phrase role="identifier">do_unwind</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">):</phrase>
- <phrase role="identifier">ctx_</phrase><phrase role="special">(</phrase>
- <phrase role="special">&</phrase> <phrase role="identifier">enumerator</phrase><phrase role="special">::</phrase><phrase role="identifier">run</phrase><phrase role="special">,</phrase> <phrase role="keyword">this</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">),</phrase>
- <phrase role="identifier">complete_</phrase><phrase role="special">(</phrase> <phrase role="keyword">false</phrase><phrase role="special">),</phrase>
- <phrase role="identifier">do_unwind_</phrase><phrase role="special">(</phrase> <phrase role="identifier">do_unwind</phrase><phrase role="special">),</phrase>
- <phrase role="identifier">started_</phrase><phrase role="special">(</phrase> <phrase role="keyword">false</phrase><phrase role="special">)</phrase>
- <phrase role="special">{}</phrase>
-
- <phrase role="special">~</phrase><phrase role="identifier">enumerator</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase>
- <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">do_unwind_</phrase> <phrase role="special">&&</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase>
- <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">unwind_stack</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="keyword">bool</phrase> <phrase role="identifier">get</phrase><phrase role="special">(</phrase> <phrase role="identifier">T</phrase> <phrase role="special">&</phrase> <phrase role="identifier">result</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">intptr_t</phrase> <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">started_</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">started_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
- <phrase role="keyword">else</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">vp</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
- <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">vp</phrase><phrase role="special">)</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="special">*</phrase> <phrase role="keyword">reinterpret_cast</phrase><phrase role="special"><</phrase> <phrase role="identifier">T</phrase> <phrase role="special">*</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">vp</phrase><phrase role="special">);</phrase>
- <phrase role="keyword">return</phrase> <phrase role="special">!</phrase> <phrase role="special">(</phrase> <phrase role="identifier">complete_</phrase> <phrase role="special">||</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
- <phrase role="special">}</phrase>
-<phrase role="special">};</phrase>
-</programlisting>
- <para>
- Member-function <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
- starts / resumes <code><phrase role="identifier">context</phrase> </code>ctx_<code>
- <phrase role="identifier">by</phrase> <phrase role="identifier">calling</phrase>
- <emphasis>context::start()</emphasis> <phrase role="special">/</phrase>
- <emphasis>context::resume()</emphasis> <phrase role="identifier">so</phrase>
- <phrase role="identifier">that</phrase> </code>enumerate()` is (re-)entered.
- Functions <emphasis>context::start()</emphasis> / <emphasis>context::resume()</emphasis>
- return the computed values.
- </para>
- <para>
- <code><phrase role="identifier">yield_return</phrase><phrase role="special">()</phrase></code>
- (equivalent to C# <code><phrase role="identifier">yield</phrase> <phrase
- role="keyword">return</phrase></code>) jumps to <code><phrase role="identifier">get</phrase><phrase
- role="special">()</phrase></code> transfering the execution control and computed
- value back. With <code><phrase role="identifier">yield_break</phrase><phrase
- role="special">()</phrase></code> (equivalent to C# <code><phrase role="identifier">yield</phrase>
- <phrase role="keyword">break</phrase></code>) the control is unconditionally
- returned to <code><phrase role="identifier">get</phrase><phrase role="special">()</phrase></code>
- to signal the end of iteration.
- </para>
- <para>
- Class <code><phrase role="identifier">power</phrase></code> derives from
- <code><phrase role="identifier">enumerate</phrase><phrase role="special"><</phrase>
- <phrase role="keyword">int</phrase> <phrase role="special">></phrase></code>
- and its implementation of <code><phrase role="identifier">enumerate</phrase><phrase
- role="special">()</phrase></code> computes the power in a local loop. Each
- computed result is transfered to <code><phrase role="identifier">get</phrase><phrase
- role="special">()</phrase></code> by calling <code><phrase role="identifier">yield_return</phrase><phrase
- role="special">()</phrase></code>.
- </para>
-
-<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">power</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">enumerator</phrase><phrase role="special"><</phrase> <phrase role="keyword">int</phrase> <phrase role="special">></phrase>
-<phrase role="special">{</phrase>
-<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
- <phrase role="keyword">void</phrase> <phrase role="identifier">enumerate</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase>
- <phrase role="keyword">int</phrase> <phrase role="identifier">counter</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">int</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="number">1</phrase><phrase role="special">;</phrase>
- <phrase role="comment">// local scoped while loop
-</phrase> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="identifier">counter</phrase><phrase role="special">++</phrase> <phrase role="special"><</phrase> <phrase role="identifier">exponent_</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="comment">// compute the value
-</phrase> <phrase role="identifier">result</phrase> <phrase role="special">=</phrase> <phrase role="identifier">result</phrase> <phrase role="special">*</phrase> <phrase role="identifier">number_</phrase><phrase role="special">;</phrase>
-
- <phrase role="comment">// return the value by jumping to calling context
-</phrase> <phrase role="comment">// == jump to while-loop in main()
-</phrase> <phrase role="identifier">yield_return</phrase><phrase role="special">(</phrase> <phrase role="identifier">result</phrase><phrase role="special">);</phrase>
- <phrase role="special">}</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="keyword">int</phrase> <phrase role="identifier">number_</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">int</phrase> <phrase role="identifier">exponent_</phrase><phrase role="special">;</phrase>
-
-<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">power</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">number</phrase><phrase role="special">,</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">exponent</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
- <phrase role="identifier">number_</phrase><phrase role="special">(</phrase> <phrase role="identifier">number</phrase><phrase role="special">),</phrase> <phrase role="identifier">exponent_</phrase><phrase role="special">(</phrase> <phrase role="identifier">exponent</phrase><phrase role="special">)</phrase>
- <phrase role="special">{}</phrase>
-<phrase role="special">};</phrase>
-</programlisting>
- </section>
- <section id="context.examples.continuation">
- <title><link linkend="context.examples.continuation">Continuation</link></title>
- <para>
- Adapted from <ulink url="https://code.google.com/p/jyield/wiki/Samples">the
- Java continuation</ulink> documentation example.
- </para>
- <para>
- Class <code><phrase role="identifier">continuation</phrase></code> provides
- the ability for a functor to suspend itself. The functor is required to accept
- a const reference to its own <code><phrase role="identifier">continuation</phrase></code>
- instance.
- </para>
-
-<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">continuation</phrase>
-<phrase role="special">{</phrase>
-<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special"><</phrase> <phrase role="keyword">void</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&)</phrase> <phrase role="special">></phrase> <phrase role="identifier">fn_</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">bool</phrase> <phrase role="identifier">started_</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">trampoline_</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase> <phrase role="identifier">fn_</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase role="special">);</phrase> <phrase role="special">}</phrase>
-
-<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">continuation</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special"><</phrase> <phrase role="keyword">void</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&)</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
- <phrase role="identifier">ctx_</phrase><phrase role="special">(</phrase>
- <phrase role="special">&</phrase> <phrase role="identifier">continuation</phrase><phrase role="special">::</phrase><phrase role="identifier">trampoline_</phrase><phrase role="special">,</phrase> <phrase role="keyword">this</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">),</phrase>
- <phrase role="keyword">false</phrase><phrase role="special">),</phrase>
- <phrase role="identifier">fn_</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">),</phrase> <phrase role="identifier">started_</phrase><phrase role="special">(</phrase> <phrase role="keyword">false</phrase><phrase role="special">)</phrase>
- <phrase role="special">{}</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">resume</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase>
- <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">started_</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">started_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
- <phrase role="keyword">else</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
-
- <phrase role="keyword">bool</phrase> <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase>
- <phrase role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
-<phrase role="special">};</phrase>
-</programlisting>
- <para>
- The functions <code><phrase role="identifier">first</phrase><phrase role="special">()</phrase></code>
- and <code><phrase role="identifier">second</phrase><phrase role="special">()</phrase></code>
- are so-called coroutines running 'quasi parallel'. Please note that the variables
- in the for-loops have local scope.
- </para>
-
-<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">first</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"started first! "</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase> <phrase role="comment">// jump back to main()
-</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"a"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase> <phrase role="comment">// output
-</phrase> <phrase role="special">}</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="keyword">void</phrase> <phrase role="identifier">second</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&</phrase> <phrase role="identifier">c</phrase><phrase role="special">)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"started second! "</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">for</phrase> <phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">i</phrase> <phrase role="special">=</phrase> <phrase role="number">0</phrase><phrase role="special">;</phrase> <phrase role="identifier">i</phrase> <phrase role="special"><</phrase> <phrase role="number">10</phrase><phrase role="special">;</phrase> <phrase role="special">++</phrase><phrase role="identifier">i</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">c</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase> <phrase role="comment">// jump back to main()
-</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"b"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">i</phrase><phrase role="special">;</phrase> <phrase role="comment">// output
-</phrase> <phrase role="special">}</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
-<phrase role="special">{</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">continuation</phrase> <phrase role="identifier">c1</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">first</phrase><phrase role="special">,</phrase> <phrase role="identifier">_1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
- <phrase role="identifier">continuation</phrase> <phrase role="identifier">c2</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="identifier">second</phrase><phrase role="special">,</phrase> <phrase role="identifier">_1</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
- <phrase role="comment">// loop until coroutines c1 and c2 are complete
-</phrase> <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">c1</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">&&</phrase> <phrase role="special">!</phrase> <phrase role="identifier">c2</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase> <phrase role="special">{</phrase>
- <phrase role="identifier">c1</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase> <phrase role="comment">// call coroutine c1 -> first()
-</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">c2</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase> <phrase role="comment">// call coroutine c2 -> second()
-</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">" "</phrase><phrase role="special">;</phrase>
- <phrase role="special">}</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"\nDone"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-
-<phrase role="identifier">output</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">started</phrase> <phrase role="identifier">first</phrase><phrase role="special">!</phrase> <phrase role="identifier">started</phrase> <phrase role="identifier">second</phrase><phrase role="special">!</phrase> <phrase role="identifier">a0</phrase> <phrase role="identifier">b0</phrase> <phrase role="identifier">a1</phrase> <phrase role="identifier">b1</phrase> <phrase role="identifier">a2</phrase> <phrase role="identifier">b2</phrase> <phrase role="identifier">a3</phrase> <phrase role="identifier">b3</phrase> <phrase role="identifier">a4</phrase> <phrase role="identifier">b4</phrase> <phrase role="identifier">a5</phrase> <phrase role="identifier">b5</phrase> <phrase role="identifier">a6</phrase> <phrase role="identifier">b6</phrase> <phrase role="identifier">a7</phrase> <phrase role="identifier">b7</phrase> <phrase role="identifier">a8</phrase> <phrase role="identifier">b8</phrase> <phrase role="identifier">a9</phrase> <phrase role="identifier">b9</phrase>
- <phrase role="identifier">Done</phrase>
-</programlisting>
- </section>
- <section id="context.examples.asio">
- <title><link linkend="context.examples.asio">ASIO</link></title>
- <para>
- Adapted from <ulink url="http://blog.think-async.com/2009/08/secret-sauce-revealed.html">Thinking
- Asynchronously in C++</ulink> using boost.asio to implement a simple echo
- server.
- </para>
- <para>
- Chris Kohlhoff uses stackless coroutines based on preprocessor-based switch
- statements to implement an echo server using boost.asio. Class <code><phrase
- role="identifier">continuation</phrase></code> provides a simple coroutine
- implemenatation using boost.context.
- </para>
-
-<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">continuation</phrase>
-<phrase role="special">{</phrase>
-<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">context</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special"><</phrase> <phrase role="keyword">void</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&)</phrase> <phrase role="special">></phrase> <phrase role="identifier">fn_</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">bool</phrase> <phrase role="identifier">started_</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">trampoline_</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase> <phrase role="identifier">fn_</phrase><phrase role="special">(</phrase> <phrase role="special">*</phrase> <phrase role="keyword">this</phrase><phrase role="special">);</phrase> <phrase role="special">}</phrase>
-
-<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">continuation</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">function</phrase><phrase role="special"><</phrase> <phrase role="keyword">void</phrase><phrase role="special">(</phrase> <phrase role="identifier">continuation</phrase> <phrase role="special">&)</phrase> <phrase role="special">></phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">fn</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
- <phrase role="identifier">ctx_</phrase><phrase role="special">(</phrase>
- <phrase role="special">&</phrase> <phrase role="identifier">continuation</phrase><phrase role="special">::</phrase><phrase role="identifier">trampoline_</phrase><phrase role="special">,</phrase> <phrase role="keyword">this</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">default_stacksize</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">no_stack_unwind</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">contexts</phrase><phrase role="special">::</phrase><phrase role="identifier">return_to_caller</phrase><phrase role="special">),</phrase>
- <phrase role="identifier">fn_</phrase><phrase role="special">(</phrase> <phrase role="identifier">fn</phrase><phrase role="special">),</phrase> <phrase role="identifier">started_</phrase><phrase role="special">(</phrase> <phrase role="keyword">false</phrase><phrase role="special">)</phrase>
- <phrase role="special">{}</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">resume</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase>
- <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">started_</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">started_</phrase> <phrase role="special">=</phrase> <phrase role="keyword">true</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">start</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
- <phrase role="keyword">else</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">suspend</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
-
- <phrase role="keyword">bool</phrase> <phrase role="identifier">is_complete</phrase><phrase role="special">()</phrase> <phrase role="keyword">const</phrase>
- <phrase role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">ctx_</phrase><phrase role="special">.</phrase><phrase role="identifier">is_complete</phrase><phrase role="special">();</phrase> <phrase role="special">}</phrase>
-<phrase role="special">};</phrase>
-</programlisting>
- <para>
- The operator <code><phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase
- role="keyword">operator</phrase><phrase role="special">()</phrase></code>
- is called by the asio reactor and jumps to coroutine (which is entering or
- resuming in function <code><phrase role="identifier">server</phrase><phrase
- role="special">::</phrase><phrase role="identifier">do_</phrase><phrase role="special">()</phrase></code>).
- In function <code><phrase role="identifier">sever</phrase><phrase role="special">::</phrase><phrase
- role="identifier">do_</phrase><phrase role="special">()</phrase></code> the
- control flow is all in one place and easy to follow; *this is queued for
- accepting a connection before control flow is passed back to the reactor
- via <code><phrase role="identifier">suspend</phrase><phrase role="special">()</phrase></code>.
- If <code><phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase
- role="identifier">do_</phrase><phrase role="special">()</phrase></code> is
- reentered, a local buffer is created and an asynch. read operation is queued
- into the reactor. The control flow is then returned to the reactor for io-multiplexing
- again. After some bytes were received <code><phrase role="identifier">server</phrase><phrase
- role="special">::</phrase><phrase role="identifier">do_</phrase><phrase role="special">()</phrase></code>
- is reentred again starting a asynch. write operation.
- </para>
- <para>
- The advantage over the ordinary <code><phrase role="identifier">bind</phrase><phrase
- role="special">()</phrase></code> version is that the state of execution
- is preserved so that variables used by the read/write operations may have
- local scope. Stackfull coroutines (as boost.context provides) enable application-protocol
- stacks which can be more easily implemented. For instance, if only part of
- a message is received (some bytes are outstanding before message can be parsed
- or serviced), then the current state can be easily suspended/preserved (even
- from nested functions of the protocol stack) until the remaining bytes are
- received.
- </para>
-
-<programlisting><phrase role="keyword">class</phrase> <phrase role="identifier">server</phrase> <phrase role="special">:</phrase> <phrase role="keyword">public</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">enable_shared_from_this</phrase><phrase role="special"><</phrase> <phrase role="identifier">server</phrase> <phrase role="special">>,</phrase>
- <phrase role="keyword">private</phrase> <phrase role="identifier">continuation</phrase>
-<phrase role="special">{</phrase>
-<phrase role="keyword">private</phrase><phrase role="special">:</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">ip</phrase><phrase role="special">::</phrase><phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">acceptor</phrase> <phrase role="identifier">acceptor_</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">size_t</phrase> <phrase role="identifier">n_</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="identifier">do_</phrase><phrase role="special">()</phrase>
- <phrase role="special">{</phrase>
- <phrase role="keyword">for</phrase> <phrase role="special">(;;)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">ip</phrase><phrase role="special">::</phrase><phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">socket</phrase> <phrase role="identifier">socket</phrase><phrase role="special">(</phrase> <phrase role="identifier">acceptor_</phrase><phrase role="special">.</phrase><phrase role="identifier">get_io_service</phrase><phrase role="special">()</phrase> <phrase role="special">);</phrase>
- <phrase role="comment">// accept connection request and enque *this for reading data from conenction
-</phrase> <phrase role="identifier">acceptor_</phrase><phrase role="special">.</phrase><phrase role="identifier">async_accept</phrase><phrase role="special">(</phrase> <phrase role="identifier">socket</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">(),</phrase> <phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase role="identifier">shared_from_this</phrase><phrase role="special">(),</phrase> <phrase role="identifier">_1</phrase><phrase role="special">,</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
- <phrase role="comment">// suspend() jumps back to operator() which returns to asio reactor
-</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
-
- <phrase role="keyword">while</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="comment">// buffer has local scope!
-</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">array</phrase><phrase role="special"><</phrase> <phrase role="keyword">char</phrase><phrase role="special">,</phrase> <phrase role="number">1024</phrase> <phrase role="special">></phrase> <phrase role="identifier">buffer</phrase><phrase role="special">;</phrase>
-
- <phrase role="comment">// enqueue *this to read some bytes from the connection into buffer
-</phrase> <phrase role="identifier">socket</phrase><phrase role="special">.</phrase><phrase role="identifier">async_read_some</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">buffer</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">(),</phrase> <phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase role="identifier">shared_from_this</phrase><phrase role="special">(),</phrase> <phrase role="identifier">_1</phrase><phrase role="special">,</phrase> <phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
- <phrase role="comment">// suspend() jumps back to operator(); asio reactor
-</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
-
- <phrase role="comment">// finish and return
-</phrase> <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">ec_</phrase><phrase role="special">)</phrase> <phrase role="keyword">break</phrase><phrase role="special">;</phrase>
-
- <phrase role="comment">// enqueue *this to write data from buffer to connection
-</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">async_write</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">socket</phrase><phrase role="special">,</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">buffer</phrase><phrase role="special">(</phrase> <phrase role="identifier">buffer</phrase><phrase role="special">,</phrase> <phrase role="identifier">n_</phrase><phrase role="special">),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">(),</phrase> <phrase role="keyword">this</phrase><phrase role="special">-></phrase><phrase role="identifier">shared_from_this</phrase><phrase role="special">(),</phrase> <phrase role="identifier">_1</phrase><phrase role="special">,</phrase> <phrase role="identifier">_2</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
- <phrase role="comment">// suspend() jumps back to operator(); asio reactor
-</phrase> <phrase role="identifier">suspend</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
- <phrase role="special">}</phrase>
- <phrase role="special">}</phrase>
-
- <phrase role="identifier">server</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="keyword">short</phrase> <phrase role="identifier">port</phrase><phrase role="special">)</phrase> <phrase role="special">:</phrase>
- <phrase role="identifier">continuation</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase> <phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="identifier">do_</phrase><phrase role="special">,</phrase> <phrase role="keyword">this</phrase><phrase role="special">)</phrase> <phrase role="special">),</phrase>
- <phrase role="identifier">acceptor_</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">ip</phrase><phrase role="special">::</phrase><phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">endpoint</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">ip</phrase><phrase role="special">::</phrase><phrase role="identifier">tcp</phrase><phrase role="special">::</phrase><phrase role="identifier">v4</phrase><phrase role="special">(),</phrase> <phrase role="identifier">port</phrase><phrase role="special">)</phrase> <phrase role="special">),</phrase>
- <phrase role="identifier">ec_</phrase><phrase role="special">(),</phrase> <phrase role="identifier">n_</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase>
- <phrase role="special">{}</phrase>
-
-<phrase role="keyword">public</phrase><phrase role="special">:</phrase>
- <phrase role="keyword">typedef</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">shared_ptr</phrase><phrase role="special"><</phrase> <phrase role="identifier">server</phrase> <phrase role="special">></phrase> <phrase role="identifier">ptr_t</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">static</phrase> <phrase role="identifier">ptr_t</phrase> <phrase role="identifier">create</phrase><phrase role="special">(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="special">&</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="keyword">short</phrase> <phrase role="identifier">port</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase> <phrase role="keyword">return</phrase> <phrase role="identifier">ptr_t</phrase><phrase role="special">(</phrase> <phrase role="keyword">new</phrase> <phrase role="identifier">server</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="identifier">port</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase> <phrase role="special">}</phrase>
-
- <phrase role="keyword">void</phrase> <phrase role="keyword">operator</phrase><phrase role="special">()(</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase> <phrase role="identifier">ec</phrase><phrase role="special">,</phrase> <phrase role="identifier">size_t</phrase> <phrase role="identifier">n</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">ec_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">ec</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">n_</phrase> <phrase role="special">=</phrase> <phrase role="identifier">n</phrase><phrase role="special">;</phrase>
- <phrase role="comment">// jump to coroutine (do_())
-</phrase> <phrase role="identifier">resume</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
-<phrase role="special">};</phrase>
-
-<phrase role="keyword">int</phrase> <phrase role="identifier">main</phrase><phrase role="special">(</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="keyword">char</phrase> <phrase role="special">*</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[])</phrase>
-<phrase role="special">{</phrase>
- <phrase role="keyword">try</phrase>
- <phrase role="special">{</phrase>
- <phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="identifier">argc</phrase> <phrase role="special">!=</phrase> <phrase role="number">2</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cerr</phrase> <phrase role="special"><<</phrase> <phrase role="string">"Usage: echo_server <port>\n"</phrase><phrase role="special">;</phrase>
- <phrase role="keyword">return</phrase> <phrase role="number">1</phrase><phrase role="special">;</phrase>
- <phrase role="special">}</phrase>
- <phrase role="special">{</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">asio</phrase><phrase role="special">::</phrase><phrase role="identifier">io_service</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">;</phrase>
- <phrase role="identifier">io_service</phrase><phrase role="special">.</phrase><phrase role="identifier">post</phrase><phrase role="special">(</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">bind</phrase><phrase role="special">(</phrase>
- <phrase role="special">&</phrase> <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="keyword">operator</phrase><phrase role="special">(),</phrase>
- <phrase role="identifier">server</phrase><phrase role="special">::</phrase><phrase role="identifier">create</phrase><phrase role="special">(</phrase> <phrase role="identifier">io_service</phrase><phrase role="special">,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">lexical_cast</phrase><phrase role="special"><</phrase> <phrase role="keyword">short</phrase> <phrase role="special">>(</phrase> <phrase role="identifier">argv</phrase><phrase role="special">[</phrase><phrase role="number">1</phrase><phrase role="special">])</phrase> <phrase role="special">),</phrase>
- <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">system</phrase><phrase role="special">::</phrase><phrase role="identifier">error_code</phrase><phrase role="special">(),</phrase> <phrase role="number">0</phrase><phrase role="special">)</phrase> <phrase role="special">);</phrase>
- <phrase role="identifier">io_service</phrase><phrase role="special">.</phrase><phrase role="identifier">run</phrase><phrase role="special">();</phrase>
- <phrase role="special">}</phrase>
- <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cout</phrase> <phrase role="special"><<</phrase> <phrase role="string">"Done"</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase>
-
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_SUCCESS</phrase><phrase role="special">;</phrase>
- <phrase role="special">}</phrase>
- <phrase role="keyword">catch</phrase> <phrase role="special">(</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">exception</phrase> <phrase role="keyword">const</phrase><phrase role="special">&</phrase> <phrase role="identifier">e</phrase><phrase role="special">)</phrase>
- <phrase role="special">{</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">cerr</phrase> <phrase role="special"><<</phrase> <phrase role="string">"Exception: "</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">e</phrase><phrase role="special">.</phrase><phrase role="identifier">what</phrase><phrase role="special">()</phrase> <phrase role="special"><<</phrase> <phrase role="identifier">std</phrase><phrase role="special">::</phrase><phrase role="identifier">endl</phrase><phrase role="special">;</phrase> <phrase role="special">}</phrase>
-
- <phrase role="keyword">return</phrase> <phrase role="identifier">EXIT_FAILURE</phrase><phrase role="special">;</phrase>
-<phrase role="special">}</phrase>
-</programlisting>
- </section>
- </section>
- <section id="context.performance">
- <title><link linkend="context.performance">Performance</link></title>
- <para>
- Performance of <emphasis role="bold">Boost.Context</emphasis> was measured
- on the platforms shown in the following table. Performance measurements were
- taken using <code><phrase role="identifier">rdtsc</phrase></code>, with overhead
- corrections, on x86 platforms. In each case, stack protection was active, cache
- warm-up was accounted for, and the one running thread was pinned to a single
- CPU. The code was compiled using the build options, 'variant<literal>release
- cxxflags</literal>-DBOOST_DISABLE_ASSERTS'.
- </para>
- <para>
- The numbers in the table are the number of cycles per iteration, based upon
- an average computed over 1000 iterations.
- </para>
- <table frame="all">
- <title>Perfomance of context switch</title>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>
- <para>
- Platform
- </para>
- </entry>
- <entry>
- <para>
- ucontext_t
- </para>
- </entry>
- <entry>
- <para>
- fcontext_t
- </para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>
- AMD Athlon 64 DualCore 4400+ (32bit Linux)
- </para>
- </entry>
- <entry>
- <para>
- 1771 cycles
- </para>
- </entry>
- <entry>
- <para>
- 146 cycles
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- Intel Core2 Quad (64bit Linux)
- </para>
- </entry>
- <entry>
- <para>
- 1739 cycles
- </para>
- </entry>
- <entry>
- <para>
- 117 cycles
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
- <section id="context.tested">
- <title><link linkend="context.tested">Tested Platforms</link></title>
- <informaltable frame="all">
- <tgroup cols="4">
- <thead>
- <row>
- <entry>
- <para>
- Platform
- </para>
- </entry>
- <entry>
- <para>
- OS
- </para>
- </entry>
- <entry>
- <para>
- Compiler
- </para>
- </entry>
- <entry>
- <para>
- ABI
- </para>
- </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>
- ARM (ARM926EJ-S)
- </para>
- </entry>
- <entry>
- <para>
- Debian GNU/Linux (Lenny)
- </para>
- </entry>
- <entry>
- <para>
- GCC 4.4.4
- </para>
- </entry>
- <entry>
- <para>
- ARM APCS (Linux)
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- MIPS (MIPS 24K)
- </para>
- </entry>
- <entry>
- <para>
- Debian GNU/Linux (Lenny)
- </para>
- </entry>
- <entry>
- <para>
- GCC 4.3.2
- </para>
- </entry>
- <entry>
- <para>
- O32
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- MIPS (O2 / MIPS R5000)
- </para>
- </entry>
- <entry>
- <para>
- Debian GNU/Linux (Lenny)
- </para>
- </entry>
- <entry>
- <para>
- GCC 4.3.2
- </para>
- </entry>
- <entry>
- <para>
- O32
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- PowerPC (7400)
- </para>
- </entry>
- <entry>
- <para>
- Debian GNU/Linux (Lenny)
- </para>
- </entry>
- <entry>
- <para>
- GCC 4.3.2
- </para>
- </entry>
- <entry>
- <para>
- SYSV
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- X86_64 (Intel Core2 Quad)
- </para>
- </entry>
- <entry>
- <para>
- Ubuntu GNU/Linux (Lucid Lynx)
- </para>
- </entry>
- <entry>
- <para>
- GCC 4.4.3
- </para>
- </entry>
- <entry>
- <para>
- SYSV
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- X86_64
- </para>
- </entry>
- <entry>
- <para>
- Windows 7
- </para>
- </entry>
- <entry>
- <para>
- MS VC 10.0
- </para>
- </entry>
- <entry>
- <para>
- PE
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- I386
- </para>
- </entry>
- <entry>
- <para>
- Debian GNU/Linux (Lenny)
- </para>
- </entry>
- <entry>
- <para>
- GCC 4.4.3
- </para>
- </entry>
- <entry>
- <para>
- SYSV
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- I386
- </para>
- </entry>
- <entry>
- <para>
- FreeBSD 8.0
- </para>
- </entry>
- <entry>
- <para>
- GCC 4.2.1
- </para>
- </entry>
- <entry>
- <para>
- SYSV
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- I386
- </para>
- </entry>
- <entry>
- <para>
- OpenSolaris 2009.06
- </para>
- </entry>
- <entry>
- <para>
- GCC 4.3.2
- </para>
- </entry>
- <entry>
- <para>
- SYSV
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>
- I386
- </para>
- </entry>
- <entry>
- <para>
- Windows XP
- </para>
- </entry>
- <entry>
- <para>
- MSVC 9.0
- </para>
- </entry>
- <entry>
- <para>
- PE
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </section>
- <section id="context.rationale">
- <title><link linkend="context.rationale">Rationale</link></title> <anchor id="context.rationale.nothrow_guarantee"/>
- <bridgehead renderas="sect3">
- <link linkend="context.rationale.nothrow_guarantee">NoThrow guarantee</link>
- </bridgehead>
- <para>
- Member functions of <link linkend="context.context.context"><emphasis>context</emphasis></link>
- do not thow exceptions but do require that certain preconditions are satisifed:
- context jumps can only be made by instances which are not a <emphasis>not-a-context</emphasis>
- and which are not complete.
- </para>
- <anchor id="context.rationale.pimpl_idiom"/>
- <bridgehead renderas="sect3">
- <link linkend="context.rationale.pimpl_idiom">Pimpl idiom</link>
- </bridgehead>
- <para>
- In order to support move semantics and context switching operations, the use
- of the Pimpl Idiom was necessary. A nice feature is that a <link linkend="context.context.context"><emphasis>context</emphasis></link>
- has the size of a pointer, so it fits into a register.
- </para>
- <para>
- With the current design the constructor accepts functors and its arguments
- similiar to <emphasis>thread</emphasis>.
- </para>
- <para>
- The Pimpl Idiom allows type-erasing the <emphasis>StackAllocator</emphasis>
- type.
- </para>
- <anchor id="context.rationale.unwinding"/>
- <bridgehead renderas="sect3">
- <link linkend="context.rationale.unwinding">Unwinding</link>
- </bridgehead>
- <para>
- In order to release resources allocated on the stack, unwinding the stack must
- be supported. The current implementation throws a exception in order to unwind
- the stack (jump back to invocation of <code><phrase role="identifier">suspend</phrase><phrase
- role="special">()</phrase></code>). The special exception is caught inside
- the trampoline function (first function on top of stack).
- </para>
- <anchor id="context.rationale.protecting_the_stack"/>
- <bridgehead renderas="sect3">
- <link linkend="context.rationale.protecting_the_stack">Protecting the stack</link>
- </bridgehead>
- <para>
- Because the stack's size is fixed -- there is no support for split stacks --
- it is important to protect against exceeding the stack's bounds. Otherwise,
- in the best case, overrunning the stack's memory will result in a segmentation
- fault or access violation and, in the worst case, the application's memory
- will be overwritten. <code><phrase role="identifier">stack_allocator</phrase></code>
- appends a guard page to the stack to help detect overruns. The guard page consumes
- no physical memory, but generates a segmentation fault or access violation
- on access to the virtual memory addresses within it.
- </para>
- <anchor id="context.rationale.fcontext_t"/>
- <bridgehead renderas="sect3">
- <link linkend="context.rationale.fcontext_t">fcontext_t</link>
- </bridgehead>
- <para>
- <emphasis role="bold">Boost.Context</emphasis> provides the low leve lAPI boost_fcontext_t
- which is implemented in assembler to provide context swapping operations. boost_fcontext_t
- is the part to port to new platforms.
- </para>
- <note>
- <para>
- Context switches do not preserve the signal mask on UNIX systems.
- </para>
- </note>
- <section id="context.rationale.other_apis_">
- <title><link linkend="context.rationale.other_apis_">Other APIs </link></title>
- <anchor id="context.rationale.other_apis_.setjmp___longjmp__"/>
- <bridgehead renderas="sect4">
- <link linkend="context.rationale.other_apis_.setjmp___longjmp__">setjmp()/longjmp()</link>
- </bridgehead>
- <para>
- C99 defines <code><phrase role="identifier">setjmp</phrase><phrase role="special">()</phrase></code>/<code><phrase
- role="identifier">longjmp</phrase><phrase role="special">()</phrase></code>
- to provide non-local jumps but it does not require that <emphasis>longjmp()</emphasis>
- preserves the current stack frame. Therefore, jumping into a function which
- was exited via a call to <emphasis>longjmp()</emphasis> is undefined <footnote>
- <para>
- <ulink url="boost:/libs/context/doc/pdf/iso_c99.pdf">ISO/IEC 9899:1999,
- 2005</ulink>, 7.13.2.1:2
- </para>
- </footnote>.
- </para>
- <anchor id="context.rationale.other_apis_.ucontext_t"/>
- <bridgehead renderas="sect4">
- <link linkend="context.rationale.other_apis_.ucontext_t">ucontext_t</link>
- </bridgehead>
- <para>
- Since POSIX.1-2003 <code><phrase role="identifier">ucontext_t</phrase></code>
- is deprecated and was removed in POSIX.1-2008! The function signature of
- <code><phrase role="identifier">makecontext</phrase><phrase role="special">()</phrase></code>
- is:
- </para>
-
-<programlisting><phrase role="keyword">void</phrase> <phrase role="identifier">makecontext</phrase><phrase role="special">(</phrase><phrase role="identifier">ucontext_t</phrase> <phrase role="special">*</phrase><phrase role="identifier">ucp</phrase><phrase role="special">,</phrase> <phrase role="keyword">void</phrase> <phrase role="special">(*</phrase><phrase role="identifier">func</phrase><phrase role="special">)(),</phrase> <phrase role="keyword">int</phrase> <phrase role="identifier">argc</phrase><phrase role="special">,</phrase> <phrase role="special">...);</phrase>
-</programlisting>
- <para>
- The third argument of <code><phrase role="identifier">makecontext</phrase><phrase
- role="special">()</phrase></code> specifies the number of integer arguments
- that follow which will require function pointer cast if <code><phrase role="identifier">func</phrase></code>
- will accept those arguments which is undefined in C99 <footnote>
- <para>
- <ulink url="boost:/libs/context/doc/pdf/iso_c99.pdf">ISO/IEC 9899:1999,
- 2005</ulink>, J.2
- </para>
- </footnote>.
- </para>
- <para>
- The arguments in the var-arg list are required to be integers, passing pointers
- in var-arg list is not guarantied to work, especially it will fail for architectures
- where pointers are larger than integers.
- </para>
- <para>
- <code><phrase role="identifier">ucontext_t</phrase></code> preserves signal
- mask between context switches which involes system calls consuming a lot
- of CPU cycles (ucontext_t is slower by perfomance_link[factor 13x] relative
- to <code><phrase role="identifier">boost_fcontext_t</phrase></code>).
- </para>
- <anchor id="context.rationale.other_apis_.windows_fibers"/>
- <bridgehead renderas="sect4">
- <link linkend="context.rationale.other_apis_.windows_fibers">Windows fibers</link>
- </bridgehead>
- <para>
- A drawback of Windows Fiber API is that <code><phrase role="identifier">CreateFiber</phrase><phrase
- role="special">()</phrase></code> does not accept a pointer to user allocated
- stack space preventing the reuse of stacks for other context instances. Because
- the Windows Fiber API requires to call <code><phrase role="identifier">ConvertThreadToFiber</phrase><phrase
- role="special">()</phrase></code> if <code><phrase role="identifier">SwitchFiber</phrase><phrase
- role="special">()</phrase></code> is called for a thread which has not been
- converted to a fiber. For the same reason <code><phrase role="identifier">ConvertFiberToThread</phrase><phrase
- role="special">()</phrase></code> must be called after return from <code><phrase
- role="identifier">SwitchFiber</phrase><phrase role="special">()</phrase></code>
- if the thread was forced to be converted to a fiber before (which is inefficient).
- </para>
-
-<programlisting><phrase role="keyword">if</phrase> <phrase role="special">(</phrase> <phrase role="special">!</phrase> <phrase role="identifier">is_a_fiber</phrase><phrase role="special">()</phrase> <phrase role="special">)</phrase>
-<phrase role="special">{</phrase>
- <phrase role="identifier">ConvertThreadToFiber</phrase><phrase role="special">(</phrase> <phrase role="number">0</phrase><phrase role="special">);</phrase>
- <phrase role="identifier">SwitchToFiber</phrase><phrase role="special">(</phrase> <phrase role="identifier">ctx</phrase><phrase role="special">);</phrase>
- <phrase role="identifier">ConvertFiberToThread</phrase><phrase role="special">();</phrase>
-<phrase role="special">}</phrase>
-</programlisting>
- <para>
- If the condition <code><phrase role="identifier">_WIN32_WINNT</phrase> <phrase
- role="special">>=</phrase> <phrase role="identifier">_WIN32_WINNT_VISTA</phrase></code>
- is met function <code><phrase role="identifier">IsThreadAFiber</phrase><phrase
- role="special">()</phrase></code> is provided in order to detect if the current
- thread was already converted. Unfortunately Windows XP + SP 2/3 defines
- <code><phrase role="identifier">_WIN32_WINNT</phrase> <phrase role="special">>=</phrase>
- <phrase role="identifier">_WIN32_WINNT_VISTA</phrase></code> without providing
- <code><phrase role="identifier">IsThreadAFiber</phrase><phrase role="special">()</phrase></code>.
- </para>
- </section>
- </section>
- <section id="context.reference">
- <title><link linkend="context.reference">Reference</link></title> <anchor id="context.reference.arm"/>
- <bridgehead renderas="sect3">
- <link linkend="context.reference.arm">ARM</link>
- </bridgehead>
- <itemizedlist>
- <listitem>
- <simpara>
- AAPCS ABI: <ulink url="boost:/libs/context/doc/pdf/arm-aapcs.pdf">Procedure
- Call Standard for the ARM Architecture</ulink>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- AAPCS/LINUX: <ulink url="boost:/libs/context/doc/pdf/arm-linux-aapcs.pdf">ARM
- GNU/Linux Application Binary Interface Supplement</ulink>
- </simpara>
- </listitem>
- </itemizedlist>
- <anchor id="context.reference.mips"/>
- <bridgehead renderas="sect3">
- <link linkend="context.reference.mips">MIPS</link>
- </bridgehead>
- <itemizedlist>
- <listitem>
- <simpara>
- O32 ABI: <ulink url="boost:/libs/context/doc/pdf/mips-o32.pdf">SYSTEM V
- APPLICATION BINARY INTERFACE, MIPS RISC Processor Supplement</ulink>
- </simpara>
- </listitem>
- </itemizedlist>
- <anchor id="context.reference.powerpc32"/>
- <bridgehead renderas="sect3">
- <link linkend="context.reference.powerpc32">PowerPC32</link>
- </bridgehead>
- <itemizedlist>
- <listitem>
- <simpara>
- SYSV ABI: <ulink url="boost:/libs/context/doc/pdf/ppc32-sysv.pdf">SYSTEM
- V APPLICATION BINARY INTERFACE PowerPC Processor Supplement</ulink>
- </simpara>
- </listitem>
- </itemizedlist>
- <anchor id="context.reference.powerpc64"/>
- <bridgehead renderas="sect3">
- <link linkend="context.reference.powerpc64">PowerPC64</link>
- </bridgehead>
- <itemizedlist>
- <listitem>
- <simpara>
- SYSV ABI: <ulink url="boost:/libs/context/doc/pdf/ppc64-sysv.pdf">PowerPC
- User Instruction Set Architecture, Book I</ulink>
- </simpara>
- </listitem>
- </itemizedlist>
- <anchor id="context.reference.x86_32"/>
- <bridgehead renderas="sect3">
- <link linkend="context.reference.x86_32">X86-32</link>
- </bridgehead>
- <itemizedlist>
- <listitem>
- <simpara>
- SYSV ABI: <ulink url="boost:/libs/context/doc/pdf/x86_32-sysv.pdf">SYSTEM
- V APPLICATION BINARY INTERFACE, Intel386TM Architecture Processor Supplement</ulink>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- MS PE: <ulink url="http://msdn.microsoft.com/en-us/library/k2b2ssfy.aspx">Calling
- Conventions</ulink>
- </simpara>
- </listitem>
- </itemizedlist>
- <anchor id="context.reference.x86_64"/>
- <bridgehead renderas="sect3">
- <link linkend="context.reference.x86_64">X86-64</link>
- </bridgehead>
- <itemizedlist>
- <listitem>
- <simpara>
- SYSV ABI: <ulink url="boost:/libs/context/doc/pdf/x86_64-sysv.pdf">System
- V Application Binary Interface, AMD64 Architecture Processor Supplement</ulink>
- </simpara>
- </listitem>
- <listitem>
- <simpara>
- MS PE: <ulink url="http://msdn.microsoft.com/en-us/library/7kcdt6fy%28VS.80%29.aspx">x64
- Software Conventions</ulink>
- </simpara>
- </listitem>
- </itemizedlist>
- </section>
- <section id="context.todo">
- <title><link linkend="context.todo">Todo</link></title>
- <itemizedlist>
- <listitem>
- <simpara>
- provide support for SPARC
- </simpara>
- </listitem>
- </itemizedlist>
- </section>
- <section id="context.acknowledgements">
- <title><link linkend="context.acknowledgements">Acknowledgments</link></title>
- <para>
- I'd like to thank Adreas Fett, Artyom Beilis, Fernando Pelliccioni, Giovanni
- Piero Deretta, Gordon Woodhull, Helge Bahmann, Holger Grund, Jeffrey Lee Hellrung
- (Jr.), Keith Jeffery, Phil Endecott, Robert Stewart, Vicente J. Botet Escriba.
- </para>
- </section>
-</article>
Deleted: trunk/libs/context/doc/context_ref.qbk
==============================================================================
--- trunk/libs/context/doc/context_ref.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,767 +0,0 @@
-[/
- 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
-]
-
-[section:context Context]
-
-Each instance of __context__ represents a context (CPU registers and stack
-space) of execution or __not_a_context__. Objects of type __context__ are
-moveable but not copyable and can be returned by a function.
-
- boost::contexts::context make_context();
-
- void f()
- {
- boost::contexts::context ctx( make_context() );
- ctx.resume();
- }
-
-[note __boost_move__ is used to emulate rvalue references.]
-
-[warning If contexts are used in a multithreaded application, they can migrated
-between threads, but must not reference __tls__.]
-
-[note If __fls__ is used on Windows, the user is responsible for calling
-__fls_alloc__, __fls_free__.]
-
-
-[heading Executing a context]
-
-A new context is created from a callable object (known as the __context_fn__).
-The stack size, stack unwinding behavior, and context termination behavior are
-determined by additional arguments.
-
-The __context__ constructor uses a __stack_allocator_concept__ to allocate an
-associated stack, and the destructor uses the same __stack_allocator_concept__
-to deallocate the stack. The default __stack_allocator_concept__ is
-__stack_allocator__, but a custom stack-allocator can be passed to the
-constructor.
-
-Additional arguments needed by a __context_fn__ are supplied as additional
-arguments to the context constructor.
-
- void f( int i);
-
- boost::contexts::context ctx( f, 42,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::return_to_caller);
-
-The __context_fn__, as well as its arguments, if any, are copied into the
-context's state. If a reference is required, use boost::ref.
-
-The maximum number of arguments of __context_fn__ is defined by
-BOOST_CONTEXT_ARITY (default is 10 and might be increased).
-
-Calling __context_start__ invokes the __context_fn__ in a newly created context
-complete with registers, flags, stack and instruction pointers. When control
-should be returned to the original calling context, call __context_suspend__.
-The current context information (registers, flags, and stack and instruction
-pointers) is saved and the original context information is restored. Calling
-__context_resume__ resumes execution in the second context after saving the new
-state of the original context.
-Note that __context_start__ must be called first and only once.
-
- boost::contexts::context ctx;
-
- void fn( int j)
- {
- for( int i = 0; i < j; ++i)
- {
- std::cout << "fn(): local variable i == " << i << std::endl;
-
- // save current context
- // value of local variable is preserved
- // transfer execution control back to main()
- ctx.suspend();
-
- // ctx.resume() was called
- // execution control transfered back from main()
- }
- }
-
- int main( int argc, char * argv[])
- {
- ctx = boost::contexts::context( fn, 7,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::return_to_caller);
-
- std::cout << "main() starts context ctx" << std::endl;
- // start the context ctx for the first time; enter fn()
- ctx.start();
-
- // ctx.suspend() was called so we returned from start()
- while ( ! ctx.is_complete() )
- {
- std::cout << "main() calls context ctx" << std::endl;
- // resume inside fn()
- // execution control is transfered to ctx
- ctx.resume();
-
- // ctx.suspend() was called within fn()
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main() starts context ctx
- fn(): local variable i == 0
- main() calls context ctx
- fn(): local variable i == 1
- main() calls context ctx
- fn(): local variable i == 2
- main() calls context ctx
- fn(): local variable i == 3
- main() calls context ctx
- fn(): local variable i == 4
- main() calls context ctx
- fn(): local variable i == 5
- main() calls context ctx
- fn(): local variable i == 6
- main() calls context ctx
- Done
-
-[warning Calling __context_resume__ from inside the same context results in
-undefined behaviour.]
-
-[note In contrast to threads, which are preemtive, __context__ switches are
-cooperative (programmer controls when switch will happen). The kernel is not
-involved in the context switches.]
-
-
-[heading Transfer of data]
-
-The argument passed to __context_resume__, in one context, is returned by
-__context_suspend__ in the other context. The intptr_t passed to
-__context_suspend__, in one context, is returned by __context_resume__ (or
-__context_start__, depending upon which function was called previously) in the
-other context.
-__context_start__ has no argument because it enters the start of the function,
-and there is no previous call to __context_suspend__ to return a value.
-
- boost::contexts::context ctx;
-
- void fn()
- {
- int i = 7;
- std::cout << "fn(): local variable i == " << i << std::endl;
-
- // save current context
- // transfer execution control back to caller
- // pass content of variable back
- int j = ctx.suspend( i);
- // j == 10 because x == 10 in main()
-
- std::cout << "transfered value: " << j << std::endl;
- }
-
- int main( int argc, char * argv[])
- {
- ctx = boost::contexts::context( fn,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::return_to_caller);
-
- std::cout << "main() calls context ctx" << std::endl;
-
- // start the context ctx for the first time
- // enter fn()
- int x = ctx.start();
- // x == 7 because i == 7 in fn()
-
- std::cout << "transfered value: " << x << std::endl;
-
- x = 10;
- // ctx.suspend() was called so we returned from start()
- ctx.resume( x);
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main() calls context ctx
- fn(): local variable i == 7
- transfered value: 7
- transfered value: 10
- Done
-
-
-[heading Exceptions in __context_fn__]
-
-If the __context_fn__ emits an exception, std::terminate() is called.
-
-[important Code executed by context 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 rethrow the
-pending exception.]
-
- try
- {
- // code that might throw
- }
- catch( forced_unwind)
- {
- throw;
- }
- catch(...)
- {
- // possibly not rethrow pending exception
- }
-
-
-[heading Handling execution context termination]
-
-The last context constructor argument is an enumerated type which determines
-what should happen when the context is complete (that is, when the
-__context_fn__ returns). The available values are `return_to_caller` and
-`exit_application`.
-
-When the last constructor argument is `return_to_caller`, execution control is
-transferred back to the last invocation of __context_start__ or
-__context_resume__ when the context is complete, as shown in this example:
-
- boost::contexts::context ctx;
-
- void fn( int j)
- {
- for( int i = 0; i < j; ++i)
- {
- std::cout << "fn(): local variable i == " << i << std::endl;
- ctx.suspend();
- }
-
- // fn() returns
- // execution control is transfered back to main()
- }
-
- int main( int argc, char * argv[])
- {
- ctx = boost::contexts::context( fn, 7,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::return_to_caller);
-
- ctx.start();
- while ( ! ctx.is_complete() )
- {
- std::cout << "main() calls context ctx" << std::endl;
- ctx.resume();
- }
-
- // fn() returned; the context is complete
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- fn(): local variable i == 0
- main() calls context ctx
- fn(): local variable i == 1
- main() calls context ctx
- fn(): local variable i == 2
- main() calls context ctx
- fn(): local variable i == 3
- main() calls context ctx
- fn(): local variable i == 4
- main() calls context ctx
- fn(): local variable i == 5
- main() calls context ctx
- fn(): local variable i == 6
- main() calls context ctx
- Done
-
-When the last constructor argument is `exit_application`, the application
-terminates with an exit status of zero when the context is complete, as shown in
-the following example:
-
- boost::contexts::context ctx;
-
- void fn( int j)
- {
- for( int i = 0; i < j; ++i)
- {
- std::cout << "fn(): local variable i == " << i << std::endl;
- ctx.suspend();
- }
-
- // fn() returns
- // application will terminate
- }
-
- int main( int argc, char * argv[])
- {
- ctx = boost::contexts::context( fn, 7,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::exit_application);
-
- ctx.start();
- while ( ! ctx.is_complete() )
- {
- std::cout << "main() calls context ctx" << std::endl;
- ctx.resume();
- }
-
- // never reached
- return EXIT_SUCCESS;
- }
-
- output:
- fn() calls context ctx
- fn(): local variable i == 1
- main() calls context ctx
- fn(): local variable i == 2
- main() calls context ctx
- fn(): local variable i == 3
- main() calls context ctx
- fn(): local variable i == 4
- main() calls context ctx
- fn(): local variable i == 5
- main() calls context ctx
- fn(): local variable i == 6
- main() calls context ctx
-
-
-[heading Chaining contexts]
-
-__boost_context__ provides the ability to chain context instances by passing
-a reference to another context, other than that __not_a_context__, as the
-last constructor argument.
-In this way, it is possible to create a chain of contexts. Depending on the
-`do_return` argument in the constructor of the last context in the chain, the
-application terminates or execution control is transferred back to the last
-invocation of __context_resume__. Each call of __context_suspend__, for the
-chained context instances, will return to __context_resume__.
-
- boost::contexts::context ctx2;
-
- void fn1()
- {
- std::cout << "fn1(): when this function returns fn2() will be entered" << std::endl;
- }
-
- void fn2()
- {
- std::cout << "fn2(): first time entered" << std::endl;
- ctx2.suspend();
- std::cout << "fn2(): second time entered\n";
- std::cout << "fn2(): return to main()" << std::endl;
- }
-
- int main( int argc, char * argv[])
- {
- {
- // ctx2 will return to ctx2.resume()
- ctx2 = boost::contexts::context(
- fn2,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::return_to_caller);
-
- // ctx1 defines ctx2 as its successor
- boost::contexts::context ctx1(
- fn1,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- ctx2);
-
- // transfer execution control to ctx1
- // fn1() is entered
- ctx1.start();
-
- // ctx2.suspend() was called
- }
-
- // ctx2 was already started by ctx1
- ctx2.resume();
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- fn1(): when this function returns fn2() will be entered
- fn2(): first time entered
- fn2(): second time entered
- fnd2(): return to main()
- Done
-
-[important Call __context_start__ only on the first context in a chain.]
-
-
-[heading Stack unwinding]
-
-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 next to last argument of the context constructor, `do_unwind`,
-indicates whether the destructor should unwind the stack.
-Stack unwinding can also be triggered by calling __context_unwind__.
-
-Stack unwinding assumes the following preconditions:
-
-* The context is not __not_a_context__
-* The context is not complete
-* The context is not running
-* The context owns a stack
-
-After unwinding, a __context__ is complete.
-
-
- boost::contexts::context ctx;
-
- struct X
- {
- X()
- { std::cout << "X()" << std::endl; }
-
- ~X()
- { std::cout << "~X()" << std::endl; }
- };
-
- void fn()
- {
- X x;
-
- for( int i = 0;; ++i)
- {
- std::cout << "fn(): " << i << std::endl;
- // transfer execution control back to main()
- ctx.suspend();
- }
- }
-
- int main( int argc, char * argv[])
- {
- ctx = boost::contexts::context(
- fn,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::return_to_caller);
- ctx.start();
- for ( int i = 0; i < 5; ++i)
- {
- // transfer execution control to fn()
- ctx.resume();
- }
-
- std::cout << "ctx is complete: " << std::boolalpha << ctx.is_complete() << "\n";
- std::cout << "call ctx.unwind_stack()" << std::endl;
-
- // unwind the stack
- // X::~X() will be called
- ctx.unwind_stack(); // unwind the stack
-
- std::cout << "ctx is complete: " << std::boolalpha << ctx.is_complete() << "\n";
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- X()
- fn(): 0
- fn(): 1
- fn(): 2
- fn(): 3
- fn(): 4
- fn(): 5
- ctx is complete: false
- call ctx.unwind_stack()
- ~X()
- ctx is complete: true
- Done
-
-[important You must not swallow __forced_unwind__ exceptions!]
-
-
-[section:context Class `context`]
-
- #include <boost/context/context.hpp>
-
- class context
- {
- public:
- context();
-
- template< typename Fn >
- context( Fn fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return);
-
- template< typename Fn, typename Allocator >
- context( Fn fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc);
-
- template< typename Fn >
- context( Fn fn, std::size_t size, flag_unwind_t do_unwind, context & nxt);
-
- template< typename Fn, typename Allocator >
- context( Fn fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc);
-
- template< typename Fn, typename A0 >
- context( Fn fn A0 a0, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return);
- ...
- template< typename Fn, typename A0,..., typename A9 >
- context( Fn fn A0 a0,..., A9, a9, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return);
-
- template< typename Fn, typename Allocator, typename A0 >
- context( Fn fn A0 a0, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc);
- ...
- template< typename Fn, typename Allocator, typename A0,..., typename A9 >
- context( Fn fn A0 a0,..., A9, a9, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc);
-
- template< typename Fn, typename A0 >
- context( Fn fn A0 a0, std::size_t size, flag_unwind_t do_unwind, context & nxt);
- ...
- template< typename Fn, typename A0,..., typename A9 >
- context( Fn fn A0 a0,..., A9, a9, std::size_t size, flag_unwind_t do_unwind, context & nxt);
-
- template< typename Fn, typename Allocator, typename A0 >
- context( Fn fn A0 a0, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc);
- ...
- template< typename Fn, typename Allocator, typename A0,..., typename A9 >
- context( Fn fn A0 a0,..., A9, a9, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc);
-
- template< typename Fn >
- context( Fn && fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return);
-
- template< typename Fn, typename Allocator >
- context( Fn && fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc);
-
- template< typename Fn >
- context( Fn && fn, std::size_t size, flag_unwind_t do_unwind, context & nxt);
-
- template< typename Fn, typename Allocator >
- context( Fn && fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc);
-
- ~context();
-
- context( context && other);
-
- context & operator=( context && other);
-
- operator unspecified-bool-type() const;
-
- bool operator!() const;
-
- void swap( context & other);
-
- bool is_complete() const;
-
- bool is_running() const;
-
- intptr_t start();
-
- intptr_t resume( intptr_t vp = 0);
-
- intptr_t suspend( intptr_t vp = 0);
-
- void unwind_stack();
- };
-
- void swap( context & l, context & r);
-
-[heading `context()`]
-[variablelist
-[[Effects:] [Creates a context representing a __not_a_context__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `template< typename Fn > context( Fn fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return)`]
-[variablelist
-[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize() when ! is_stack_unbound().]]
-[[Effects:] [Creates a context which will execute `fn`. If `do_unwind` is `stack_unwind` the destructor of `*this` unwinds
-the stack before destructing it. If `do_return` is `exit_application` the application exits with return code `0`, otherwise
-execution control is transfered back to the invoker (`resume()` returns).]]
-[[Throws:] [__invalid_argument__ if a precondition is not satisfied.]]
-]
-
-[heading `template< typename Fn, typename Allocator > context( Fn fn, std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc)`]
-[variablelist
-[[Effects:] [Creates a context which will execute `fn`. If `do_unwind` is `stack_unwind` the destructor of `*this` unwinds
-the stack before destructing it. If `do_return` is `exit_application` the application exits with return code `0`, otherwise
-execution control is transfered back to the invoker (`resume()` returns).]]
-[[Throws:] [depends on `alloc` if a precondition is not satisfied.]]
-]
-
-[heading `template< typename Fn > context( Fn fn, std::size_t size, flag_unwind_t do_unwind, context & nxt)`]
-[variablelist
-[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize() when ! is_stack_unbound(), `nxt` is not a __not_a_context__.]]
-[[Effects:] [Creates a context which will execute `fn`. If `do_unwind` is `stack_unwind` the destructor of `*this` unwinds
-the stack before destructing it. execution control is transfered to `nxt` if `fn` returns (`nxt` is linked).]]
-[[Throws:] [__invalid_argument__ if a precondition is not satisfied.]]
-]
-
-[heading `template< typename Fn, typename Allocator > context( Fn fn, std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocatorconst& alloc)`]
-[variablelist
-[[Preconditions:] [`nxt` is not a __not_a_context__.]]
-[[Effects:] [Creates a context which will execute `fn`. If `do_unwind` is `stack_unwind` the destructor of `*this` unwinds
-the stack before destructing it. execution control is transfered to `nxt` if `fn` returns (`nxt` is linked).]]
-[[Throws:] [depends on `alloc` if a precondition is not satisfied.]]
-]
-
-[heading `template< typename Fn, typename A0,... > context( Fn fn, A0 a0,..., std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return)`]
-[variablelist
-[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize() when ! is_stack_unbound().]]
-[[Effects:] [Creates a context which will execute `fn` (arguments `A0`,... are bound to `fn`). If `do_unwind` is `stack_unwind` the destructor of `*this` unwinds
-the stack before destructing it. If `do_return` is `exit_application` the application exits with return code `0`, otherwise
-execution control is transfered back to the invoker (`resume()` returns).]]
-[[Throws:] [__invalid_argument__ if a precondition is not satisfied.]]
-]
-
-[heading `template< typename Fn, typename Allocator, typename A0,... > context( Fn fn, A0 a0,..., std::size_t size, flag_unwind_t do_unwind, flag_return_t do_return, Allocator const& alloc)`]
-[variablelist
-[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize() when ! is_stack_unbound().]]
-[[Effects:] [Creates a context which will execute `fn` (arguments `A0`,... are bound to `fn`). If `do_unwind` is `stack_unwind` the destructor of `*this` unwinds
-the stack before destructing it. If `do_return` is `exit_application` the application exits with return code `0`, otherwise
-execution control is transfered back to the invoker (`resume()` returns).]]
-[[Throws:] [depends on `alloc` if a precondition is not satisfied.]]
-]
-
-[heading `template< typename Fn, typename A0,... > context( Fn fn, A0 a0,..., std::size_t size, flag_unwind_t do_unwind, context & nxt)`]
-[variablelist
-[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize() when ! is_stack_unbound(), `nxt` is not a __not_a_context__.]]
-[[Effects:] [Creates a context which will execute `fn` (arguments`A0`,... are bound to `fn`). If `do_unwind` is `stack_unwind` the destructor of `*this` unwinds
-the stack before destructing it. execution control is transfered to `nxt` if `fn` returns (`nxt` is linked).]]
-[[Throws:] [__invalid_argument__ if a precondition is not satisfied.]]
-]
-
-[heading `template< typename Fn, typename Allocator, typename A0,... > context( Fn fn, A0 a0,..., std::size_t size, flag_unwind_t do_unwind, context & nxt, Allocator const& alloc)`]
-[variablelist
-[[Preconditions:] [`nxt` is not a __not_a_context__.]]
-[[Effects:] [Creates a context which will execute `fn` (arguments`A0`,... are bound to `fn`). If `do_unwind` is `stack_unwind` the destructor of `*this` unwinds
-the stack before destructing it. execution control is transfered to `nxt` if `fn` returns (`nxt` is linked).]]
-[[Throws:] [depends on `alloc` if a precondition is not satisfied.]]
-]
-
-[heading `~context()`]
-[variablelist
-[[Effects:] [Destroys the instance and deallocates the stack. Unwinds the stack if it was specified in the
-constructor of `*this`.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `context( context && other)`]
-[variablelist
-[[Effects:] [Moves the internal data of `other` to `*this`.
-`other` becomes __not_a_context__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `context & operator=( context && other)`]
-[variablelist
-[[Effects:] [Destroys the internal data of `*this` and moves the
-internal data of `other` to `*this`. `other` becomes __not_a_context__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `operator unspecified-bool-type() const`]
-[variablelist
-[[Returns:] [If `*this` refers to __not_a_context__, the function returns
-false. Otherwise true.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool operator!() const`]
-[variablelist
-[[Returns:] [If `*this` refers not to __not_a_context__, the function returns
-true. Otherwise false.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `void swap( context & other)`]
-[variablelist
-[[Effects:] [Swaps the internal data from `*this` with the values
-of `other`.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool is_complete() const`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_context__.]]
-[[Effects:] [Returns `true` if context-function of `*this` has returned.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool is_running() const`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_context__.]]
-[[Effects:] [Returns `true` if `*this` is the currently active context.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool is_started() const`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_context__.]]
-[[Effects:] [Returns `true` if context-function of `*this` has started.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool is_resumed() const`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_context__.]]
-[[Effects:] [Returns `true` if context-function of `*this` has resumed.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `intptr_t start()`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_context__, `! is_complete()` and
-`! is_running()`.]]
-[[Effects:] [`start()` enters the __context_fn__ `fn` with which the context was
-constructed. Upon return, the context was either left via
-`suspend()` or the __context_fn__ returned.]]
-[[Returns:] [A intptr_t passed to `suspend()` is returned if the context
-was left with `suspend()`.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `intptr_t resume( intptr_t vp = 0)`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_context__, `! is_complete()` and
-`! is_running()`, `start()` was called before.]]
-[[Effects:] [None, if *this was not suspended by a previous call to suspend().
-Otherwise, execution control is transferred back to the caller of suspend(), thereby
-resuming *this. The argument, vp, will be returned by the previous call to suspend().]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `intptr_t suspend( intptr_t vp = 0)`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_context__, `! is_complete()` and
-`is_running()`.]]
-[[Effects:] [Transfers execution control to the caller of the most recent call to
-start() or resume(). The argument, vp, will be returned by start() or resume().]]
-[[Throws:] [__forced_unwind__ if __context_unwind__ was called.]]
-]
-
-[heading `void unwind_stack()`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_context__, `! is_complete()` and
-`! is_running()`.]]
-[[Effects:] [Destroys all objects allocated on the stack, owned by *this, in the
-reverse order of their allocation.]]
-[[Throws:] [Nothing.]]
-[[Postconditions:] [`*this` is not a __not_a_context__ and `is_complete()`.]]
-]
-
-[heading Non-member function `swap()`]
-
- void swap( context & l, context & r);
-
-[variablelist
-[[Effects:] [As if 'l.swap( r)'.]]
-]
-
-[endsect]
-
-[endsect]
Deleted: trunk/libs/context/doc/continuation.qbk
==============================================================================
--- trunk/libs/context/doc/continuation.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,103 +0,0 @@
-[/
- 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
-]
-
-[section:continuation Continuation]
-
-Adapted from [@https://code.google.com/p/jyield/wiki/Samples the Java
-continuation] documentation example.
-
-Class `continuation` provides the ability for a functor to suspend itself.
-The functor is required to accept a const reference to its own `continuation`
-instance.
-
- class continuation
- {
- private:
- boost::contexts::context ctx_;
- boost::function< void( continuation &) > fn_;
- bool started_;
-
- void trampoline_()
- { fn_( * this); }
-
- public:
- continuation( boost::function< void( continuation &) > const& fn) :
- ctx_(
- & continuation::trampoline_, this,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::return_to_caller),
- false),
- fn_( fn), started_( false)
- {}
-
- void resume()
- {
- if ( ! started_)
- {
- started_ = true;
- ctx_.start();
- }
- else ctx_.resume();
- }
-
- void suspend()
- { ctx_.suspend(); }
-
- bool is_complete() const
- { return ctx_.is_complete(); }
- };
-
-
-The functions `first()` and `second()` are so-called coroutines running 'quasi
-parallel'.
-Please note that the variables in the for-loops have local scope.
-
- void first( continuation & c)
- {
- std::cout << "started first! ";
- for ( int i = 0; i < 10; ++i)
- {
- c.suspend(); // jump back to main()
- std::cout << "a" << i; // output
- }
- }
-
- void second( continuation & c)
- {
- std::cout << "started second! ";
- for ( int i = 0; i < 10; ++i)
- {
- c.suspend(); // jump back to main()
- std::cout << "b" << i; // output
- }
- }
-
- int main( int argc, char * argv[])
- {
- {
- continuation c1( boost::bind( first, _1) );
- continuation c2( boost::bind( second, _1) );
- // loop until coroutines c1 and c2 are complete
- while ( ! c1.is_complete() && ! c2.is_complete() ) {
- c1.resume(); // call coroutine c1 -> first()
- std::cout << " ";
- c2.resume(); // call coroutine c2 -> second()
- std::cout << " ";
- }
- }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- started first! started second! a0 b0 a1 b1 a2 b2 a3 b3 a4 b4 a5 b5 a6 b6 a7 b7 a8 b8 a9 b9
- Done
-
-[endsect]
Deleted: trunk/libs/context/doc/enumerator.qbk
==============================================================================
--- trunk/libs/context/doc/enumerator.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,166 +0,0 @@
-[/
- 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
-]
-
-[section:enumerator Enumerator]
-
-Class `power` computes the power of `number` for the exponents in the range
-from `1` to `number` (constructor arguments).
-
-
- class power
- {
- public:
- power( int number, int exponent);
-
- bool get( int & data);
- };
-
-
-Each call to `power::get()` returns a boolean indicating a vaild result.
-The reference argument `data` contains the computed result.
-
-
- int main()
- {
- {
- power pw( 2, 8);
- int i;
- // pw.get() returns the computed result
- // for each value from 1 to 8
- // return value of pw.get() indicates that
- // a valid result
- while ( pw.get( i) ) {
- std::cout << i << " ";
- }
- }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- 2 4 8 16 32 64 128 256
- Done
-
-
-In `main()` an instance of `power` is constructed, computing the power of 2
-for exponents in the range from 1 to 8 by each call to `power::get()`.
-
-It is intended to compute the numbers in a loop and transfer each result to the
-caller without disrupting the loop.
-
-__boost_context__ can be used to implement an equivalent to C#'s `yield`
-facility (C# provides the keywords `yield return` and `yield break`).
-For this purpose helper-template `enumerator` is defined containing the private
-member `ctx_` executing `enumerate()` as __context_fn__.
-
- template< typename T >
- class enumerator {
- private:
- boost::contexts::context ctx_;
- bool complete_;
- bool do_unwind_;
- bool started_;
-
- static void run( enumerator * self)
- { self->enumerate(); }
-
- protected:
- virtual void enumerate() = 0;
-
- void yield_return( T const& v)
- {
- intptr_t vp = reinterpret_cast< intptr_t >( & v);
- ctx_.suspend( vp);
- }
-
- void yield_break()
- {
- complete_ = true;
- ctx_.suspend();
- }
-
- public:
- enumerator( bool do_unwind = true):
- ctx_(
- & enumerator::run, this,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::return_to_caller),
- complete_( false),
- do_unwind_( do_unwind),
- started_( false)
- {}
-
- ~enumerator()
- {
- if ( do_unwind_ && ! ctx_.is_complete() )
- ctx_.unwind_stack();
- }
-
- bool get( T & result)
- {
- intptr_t vp = 0;
- if ( ! started_)
- {
- started_ = true;
- vp = ctx_.start();
- }
- else
- {
- vp = ctx_.resume();
- }
- if ( vp) result = * reinterpret_cast< T * >( vp);
- return ! ( complete_ || ctx_.is_complete() );
- }
- };
-
-
-Member-function `get()` starts / resumes `context `ctx_` by calling
-__context_start__ / __context_resume__ so that `enumerate()` is (re-)entered.
-Functions __context_start__ / __context_resume__ return the computed values.
-
-`yield_return()` (equivalent to C# `yield return`) jumps to `get()` transfering
-the execution control and computed value back.
-With `yield_break()` (equivalent to C# `yield break`) the control is
-unconditionally returned to `get()` to signal the end of iteration.
-
-Class `power` derives from `enumerate< int >` and its implementation of
-`enumerate()` computes the power in a local loop.
-Each computed result is transfered to `get()` by calling `yield_return()`.
-
-
- class power : public enumerator< int >
- {
- private:
- void enumerate()
- {
- int counter = 0;
- int result = 1;
- // local scoped while loop
- while ( counter++ < exponent_)
- {
- // compute the value
- result = result * number_;
-
- // return the value by jumping to calling context
- // == jump to while-loop in main()
- yield_return( result);
- }
- }
-
- int number_;
- int exponent_;
-
- public:
- power( int number, int exponent) :
- number_( number), exponent_( exponent)
- {}
- };
-
-[endsect]
Deleted: trunk/libs/context/doc/examples.qbk
==============================================================================
--- trunk/libs/context/doc/examples.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,14 +0,0 @@
-[/
- 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
-]
-
-[section:examples Examples]
-
-[include enumerator.qbk]
-[include continuation.qbk]
-[include asio.qbk]
-
-[endsect]
Modified: trunk/libs/context/doc/fcontext.qbk
==============================================================================
--- trunk/libs/context/doc/fcontext.qbk (original)
+++ trunk/libs/context/doc/fcontext.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -5,125 +5,284 @@
http://www.boost.org/LICENSE_1_0.txt
]
-[section:capi Low level API (boost_fcontext_t)]
+[section:context Context]
-__boost_context__ uses and provides a low level API which implements the
-execution control transfer mechanism. The boost_fcontext_t API provides a
-similar interface like [@http://www.kernel.org/doc/man-pages/online/pages/man2/getcontext.2.html ucontext_t].
-boost_fcontext_t and its functions are located in the global namespace and the
-functions are declared as extern "C".
-
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <vector>
-
- #include <boost/cstdint.hpp>
- #include <boost/context/fcontext.hpp>
-
- boost_fcontext_t fcm, fc1, fc2;
-
- void f1( intptr_t p)
- {
- (void) p;
- fprintf(stderr,"f1() started\n");
- fprintf(stderr,"f1: call boost_fcontext_jump( & fc1, & fc2, 0)\n");
- // jump to context fc2
- boost_fcontext_jump( & fc1, & fc2, 0);
- // returned from context fc2 (function f2())
- // return from function f1()
- fprintf(stderr,"f1() returns\n");
- }
-
- void f2( intptr_t p)
- {
- (void) p;
- fprintf(stderr,"f2() started\n");
- fprintf(stderr,"f2: call boost_fcontext_jump( & fc2, & fc1, 0)\n");
- // jump to context fc1
- boost_fcontext_jump( & fc2, & fc1, 0);
- // never reached
- fprintf(stderr,"f2() returns\n");
- }
-
- int main( int argc, char * argv[])
- {
- // creat two protected stacks
- boost::contexts::protected_stack b1(262144);
- boost::contexts::protected_stack b2(262144);
-
- // let context fc1 use stack b1
- fc1.fc_stack.ss_base = b1.address();
- fc1.fc_stack.ss_limit =
- static_cast< char * >( fc1.fc_stack.ss_base) - b1.size();
- // link context fcm;
- // fcm will be invoked after fc1 terminated
- fc1.fc_link = & fcm;
- // context fc1 used f1() as context function
- boost_fcontext_make( & fc1, f1, 0);
-
- // let context fc2 use stack b2
- fc2.fc_stack.ss_base = b2.address();
- fc2.fc_stack.ss_limit =
- static_cast< char * >( fc2.fc_stack.ss_base) - b2.size();
- // context fc2 used f2() as context function
- boost_fcontext_make( & fc2, f2, 0);
-
- // start context f1; entering f1()
- fprintf(stderr,"main: call boost_fcontext_start( & fcm, & fc1)\n");
- boost_fcontext_start( & fcm, & fc1);
-
- fprintf( stderr, "main() returns\n");
- return EXIT_SUCCESS;
- }
-
- output:
- main: call boost_fcontext_start( & fcm, & fc1)
- f1() started
- f1: call boost_fcontext_jump( & fc1, & fc2, 0)
- f2() started
- f2: call boost_fcontext_jump( & fc2, & fc1, 0)
- f1() returns
- main() returns
+Each instance of __fcontext__ represents a context (CPU registers and stack
+space). Together with its related functions __start_fcontext__,
+__jump_fcontext__ and __make_fcontext__ it provides a execution control transfer
+mechanism similar interface like
+[@http://www.kernel.org/doc/man-pages/online/pages/man2/getcontext.2.html ucontext_t].
+__fcontext__ and its functions are located in __context_ns__ and the functions
+are declared as extern "C".
-Function `boost_fcontext_start()` enters the __context_fn__ `f1()` by starting
+[warning If __fcontext__ is used in a multithreaded application, it can migrated
+between threads, but must not reference __tls__.]
+
+[note If __fls__ is used on Windows, the user is responsible for calling
+__fls_alloc__, __fls_free__.]
+
+[important The low level API is the part to port to new platforms.]
+
+
+[heading Executing a context]
+
+A new context supposed to execute a __context_fn__ (returning void and accepting
+intptr_t as argument) must be initialized by function __make_fcontext__.
+
+ // context-function
+ void f( intptr);
+
+ // creates and manages a protected stack (with guard page)
+ boost::ctx::protected_stack stack( boost::ctx::default_stacksize() );
+
+ // let fcontext_t fc use stack
+ fc.fc_stack.base = stack.address();
+ fc.fc_stack.limit =
+ static_cast< char * >( fc.fc_stack.base) - stack.size();
+
+ // context fc used f() as context function
+ // 3 is the argument with which f() will be called
+ make_fcontext( & fc, f, 3);
+
+__fcontext__ requires a pointer to the top of the stack (__fc_base__) as well
+as a pointer to the lower bound of the stack (__fc_limit__).
+
+Calling __start_fcontext__ invokes the __context_fn__ in a newly created context
+complete with registers, flags, stack and instruction pointers. When control
+should be returned to the original calling context, call __jump_fcontext__.
+The current context information (registers, flags, and stack and instruction
+pointers) is saved and the original context information is restored. Calling
+__jump_fcontext__ again resumes execution in the second context after saving the
+new state of the original context.
+Note that __start_fcontext__ must be called first and only once.
+
+ namespace ctx = boost::ctx;
+
+ ctx::fcontext_t fcm, fc1, fc2;
+
+ void f1( intptr_t)
+ {
+ std::cout << "f1: entered" << std::endl;
+ std::cout << "f1: call jump_fcontext( & fc1, & fc2)" << std::endl;
+ ctx::jump_fcontext( & fc1, & fc2, 0);
+ std::cout << "f1: return" << std::endl;
+ ctx::jump_fcontext( & fc1, & fcm, 0);
+ }
+
+ void f2( intptr_t)
+ {
+ std::cout << "f2: entered" << std::endl;
+ std::cout << "f2: call jump_fcontext( & fc2, & fc1)" << std::endl;
+ ctx::jump_fcontext( & fc2, & fc1, 0);
+ BOOST_ASSERT( false && ! "f2: never returns");
+ }
+
+ int main( int argc, char * argv[])
+ {
+ ctx::stack_allocator alloc1, alloc2;
+
+ fc1.fc_stack.base = alloc1.allocate(ctx::minimum_stacksize());
+ fc1.fc_stack.limit =
+ static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc1, f1, 0);
+
+ fc2.fc_stack.base = alloc2.allocate(ctx::minimum_stacksize());
+ fc2.fc_stack.limit =
+ static_cast< char * >( fc2.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc2, f2, 0);
+
+ std::cout << "main: call start_fcontext( & fcm, & fc1)" << std::endl;
+ ctx::start_fcontext( & fcm, & fc1);
+
+ std::cout << "main: done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main: call start_fcontext( & fcm, & fc1)
+ f1: entered
+ f1: call jump_fcontext( & fc1, & fc2)
+ f2: entered
+ f2: call jump_fcontext( & fc2, & fc1)
+ f1: return
+ main: done
+
+Function `start_fcontext()` enters the __context_fn__ `f1()` by starting
context fc1 (context fcm saves the registers of `main()`). For jumping between
-context's fc1 and fc2 `boost_fcontext_jump()` is called.
+context's fc1 and fc2 `jump_fcontext()` is called.
Because context fcm is chained to fc1, `main()` is entered (returning from
-`boost_fcontext_start()`) after context fc1 becomes complete (return from
+`start_fcontext()`) after context fc1 becomes complete (return from
`f1()`).
-[important The low level API is the part to port to new platforms.]
+[warning Calling __jump_fcontext__ to the same context from inside the same
+context results in undefined behaviour.]
+
+[note In contrast to threads, which are preemtive, __fcontext__ switches are
+cooperative (programmer controls when switch will happen). The kernel is not
+involved in the context switches.]
+
+
+[heading Transfer of data]
+
+The argument passed to __jump_fcontext__, in one context, is returned by
+__jump_fcontext__ in the other context. The intptr_t passed to
+__jump_fcontext__, in one context, is returned by __jump_fcontext__ (or
+__start_fcontext__, depending upon which function was called previously) in the
+other context.
+__start_fcontext__ has no data argument because it enters the start of the function,
+and there is no previous call to __jump_fcontext__ to return a value.
+
+ namespace ctx = boost::ctx;
+
+ ctx::fcontext_t fc1, fcm;
+
+ typedef std::pair< int, int > pair_t;
+
+ void f1( intptr_t param)
+ {
+ pair_t * p = ( pair_t *) param;
+
+ p = ( pair_t *) ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) ( p->first + p->second) );
+
+ ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) ( p->first + p->second) );
+ }
+
+ int main( int argc, char * argv[])
+ {
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc1.fc_stack.limit =
+ static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ fc1.fc_link = & fcm;
+ pair_t p( std::make_pair( 2, 7) );
+ ctx::make_fcontext( & fc1, f1, ( intptr_t) & p);
+
+ int res = ( int) ctx::start_fcontext( & fcm, & fc1);
+ std::cout << p.first << " + " << p.second << " == " << res << std::endl;
+
+ p = std::make_pair( 5, 6);
+ res = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & p);
+ std::cout << p.first << " + " << p.second << " == " << res << std::endl;
+
+ std::cout << "main: done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ 2 + 7 == 9
+ 5 + 6 == 11
+ main: done
+
+
+[heading Exceptions in __context_fn__]
+
+If the __context_fn__ emits an exception, the application will terminate.
+
+
+[heading Chaining contexts]
+
+__boost_context__ provides the ability to chain context instances by passing
+a pointer to another context to __fc_link__.
+In this way, it is possible to create a chain of contexts.
+
+ namespace ctx = boost::ctx;
+
+ ctx::fcontext_t fc1, fc2;
+
+ void f1( intptr_t)
+ {
+ std::cout << "f1: entered" << std::endl;
+ std::cout << "f1: call jump_fcontext( & fc1, & fc2)" << std::endl;
+ ctx::jump_fcontext( & fc1, & fc2, 0);
+ std::cout << "f1: return" << std::endl;
+ // implizit jump back to fcm -> main()
+ }
+
+ void f2( intptr_t)
+ {
+ std::cout << "f2: entered" << std::endl;
+ std::cout << "f2: call jump_fcontext( & fc2, & fc1)" << std::endl;
+ ctx::jump_fcontext( & fc2, & fc1, 0);
+ BOOST_ASSERT( false && ! "f2: never returns");
+ }
+
+ int main( int argc, char * argv[])
+ {
+ ctx::fcontext_t fcm;
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc1.fc_stack.limit =
+ static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ // chain fc1 and fcm
+ fc1.fc_link = & fcm;
+ ctx::make_fcontext( & fc1, f1, 0);
+
+ fc2.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc2.fc_stack.limit =
+ static_cast< char * >( fc2.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc2, f2, 0);
+
+ std::cout << "main: call start_fcontext( & fcm, & fc1)" << std::endl;
+ ctx::start_fcontext( & fcm, & fc1);
+
+ std::cout << "main: done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main: call start_fcontext( & fcm, & fc1)
+ f1: entered
+ f1: call jump_fcontext( & fc1, & fc2)
+ f2: entered
+ f2: call jump_fcontext( & fc2, & fc1)
+ f1: return
+ main: done
+
+Because context fcm is chained to fc1, `main()` is entered (returning from
+`start_fcontext()`) after context fc1 becomes complete (return from
+`f1()`).
+
+
+[heading Stack unwinding]
+
+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.
-[section:boost_fcontext Struct `boost_fcontext_t` and related functions]
+[section:boost_fcontext Struct `fcontext_t` and related functions]
typedef struct boost_fcontext_stack boost_fcontext_stack_t;
struct boost_fcontext_stack
{
- void * ss_base;
- void * ss_limit;
+ void * base;
+ void * limit;
};
- typedef struct boost_fcontext boost_fcontext_t;
+ typedef struct boost_fcontext fcontext_t;
struct boost_fcontext
{
< platform specific >
boost_fcontext_stack_t fc_stack;
- boost_fcontext_t * fc_link;
+ fcontext_t * fc_link;
};
- intptr_t boost_fcontext_start( boost_fcontext_t * ofc, boost_fcontext_t const* nfc);
- intptr_t boost_fcontext_jump( boost_fcontext_t * ofc, boost_fcontext_t const* nfc, intptr_t vp);
- void boost_fcontext_make( boost_fcontext_t * fc, void(* fn)(void*), intptr_t p);
+ intptr_t start_fcontext( fcontext_t * ofc, fcontext_t const* nfc);
+ intptr_t jump_fcontext( fcontext_t * ofc, fcontext_t const* nfc, intptr_t vp);
+ void make_fcontext( fcontext_t * fc, void(* fn)(void*), intptr_t p);
-[heading `ss_base`]
+[heading `base`]
[variablelist
[[Member:] [Pointer to the top of the stack.]]
]
-[heading `ss_limit`]
+[heading `limit`]
[variablelist
[[Member:] [Pointer to the bottom of the stack.]]
]
@@ -138,31 +297,31 @@
[[Member:] [The address of the next context link in a chain, if any.]]
]
-[heading `intptr_t boost_fcontext_start( boost_fcontext_t * ofc,
- boost_fcontext_t * nfc)`]
+[heading `intptr_t start_fcontext( fcontext_t * ofc,
+ fcontext_t * nfc)`]
[variablelist
[[Effects:] [Stores the current context data (stack pointer, instruction
pointer, and CPU registers) to `*ofc` and restores the context data from `*nfc`,
which implies jumping to `*nfc`'s execution context. This function must be
called when first entering `*nfc`'s execution context.]]
-[[Returns:] [The result of calling `boost_fcontext_jump()`.]]
+[[Returns:] [The result of calling `jump_fcontext()`.]]
]
-[heading `intptr_t boost_fcontext_jump( boost_fcontext_t * ofc, boost_fcontext_t * nfc, intptr_t p)`]
+[heading `intptr_t jump_fcontext( fcontext_t * ofc, fcontext_t * nfc, intptr_t p)`]
[variablelist
[[Effects:] [Stores the current context data (stack pointer, instruction
pointer, and CPU registers) to `*ofc` and restores the context data from `*nfc`,
which implies jumping to `*nfc`'s execution context. The intptr_t argument, `p`,
is passed to the current context to be returned by the most recent call to
-`boost_fcontext_start()` or `boost_fcontext_jump()` in the same thread.]]
+`start_fcontext()` or `jump_fcontext()` in the same thread.]]
[[Returns:] [The third pointer argument passed to the most recent call to
-`boost_fcontext_jump()`, if any.]]
+`jump_fcontext()`, if any.]]
]
-[heading `void boost_fcontext_make( boost_fcontext_t * fc, void(*fn)(intptr_t), intptr_t p)`]
+[heading `void make_fcontext( fcontext_t * fc, void(*fn)(intptr_t), intptr_t p)`]
[variablelist
[[Precondition:] [A stack is applied to `*fc` before
-`boost_fcontext_make()` is called. If a successor context should be executed
+`make_fcontext()` is called. If a successor context should be executed
after `*fc` finishes the address of the successor context must be stored ir
`fc->fc_link`. The application exits otherwise.]]
[[Effects:] [Modifies `*fc` in order to execute `fn` with argument `p` when the
Modified: trunk/libs/context/doc/overview.qbk
==============================================================================
--- trunk/libs/context/doc/overview.qbk (original)
+++ trunk/libs/context/doc/overview.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -11,17 +11,17 @@
multitasking on a single thread. By providing an abstraction of the current
execution state in the current thread, including the stack (with local
variables) and stack pointer, all registers and CPU flags, and the instruction
-pointer, a __context__ instance represents a specific point in the application's
+pointer, a __fcontext__ instance represents a specific point in the application's
execution path. This is useful for building higher-level abstractions, like
__coroutines__, __coop_threads__ or an aquivalent to
[@http://msdn.microsoft.com/en-us/library/9k7k7cf0%28v=vs.80%29.aspx C# keyword __yield__]
-in C++ ([cs_example_link see enumerator example]).
+in C++.
-A __context__ provides the means to suspend the current execution path and to
-transfer execution control, thereby permitting another __context__ to run on the
-current thread. This stateful transfer mechanism enables a __context__ to
+A __fcontext__ provides the means to suspend the current execution path and to
+transfer execution control, thereby permitting another __fcontext__ to run on the
+current thread. This stateful transfer mechanism enables a __fcontext__ to
suspend execution from within nested functions and, later, to resume from where
-it was suspended. While the execution path represented by a __context__ only
+it was suspended. While the execution path represented by a __fcontext__ only
runs on a single thread, it can be migrated to another thread at any given time.
A context switch between threads requires system calls (involving the OS
@@ -39,7 +39,4 @@
All functions and classes are contained in the namespace __context_ns__.
-__boost_context__ depends on __boost_move__.
-
-
[endsect]
Modified: trunk/libs/context/doc/rationale.qbk
==============================================================================
--- trunk/libs/context/doc/rationale.qbk (original)
+++ trunk/libs/context/doc/rationale.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -7,39 +7,9 @@
[section:rationale Rationale]
-[heading NoThrow guarantee]
-
-Member functions of __context__ do not thow exceptions but do require that
-certain preconditions are satisifed:
-context jumps can only be made by instances which are not a __not_a_context__
-and which are not complete.
-
-
-[heading Pimpl idiom]
-
-In order to support move semantics and context switching operations, the use of
-the Pimpl Idiom was necessary.
-A nice feature is that a __context__ has the size of a pointer, so it fits into
-a register.
-
-With the current design the constructor accepts functors and its arguments
-similiar to __thread__.
-
-The Pimpl Idiom allows type-erasing the __stack_allocator__ type.
-
-
-[heading Unwinding]
-
-In order to release resources allocated on the stack, unwinding the stack must be
-supported.
-The current implementation throws a exception in order to unwind the stack (jump
-back to invocation of `suspend()`). The special exception is caught inside the
-trampoline function (first function on top of stack).
-
-
[heading Protecting the stack]
-Because the stack's size is fixed -- there is no support for split stacks -- it
+Because the stack's size is fixed -- there is no support for split stacks yet -- it
is important to protect against exceeding the stack's bounds. Otherwise, in the
best case, overrunning the stack's memory will result in a segmentation fault or
access violation and, in the worst case, the application's memory will be
@@ -51,9 +21,9 @@
[heading fcontext_t]
-__boost_context__ provides the low leve lAPI boost_fcontext_t which is
+__boost_context__ provides the low level API fcontext_t which is
implemented in assembler to provide context swapping operations.
-boost_fcontext_t is the part to port to new platforms.
+fcontext_t is the part to port to new platforms.
[note Context switches do not preserve the signal mask on UNIX systems.]
@@ -88,7 +58,7 @@
`ucontext_t` preserves signal mask between context switches which involes system
calls consuming a lot of CPU cycles (ucontext_t is slower by
-perfomance_link[factor 13x] relative to `boost_fcontext_t`).
+perfomance_link[factor 13x] relative to `fcontext_t`).
[heading Windows fibers]
Added: trunk/libs/context/doc/stack.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/context/doc/stack.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -0,0 +1,116 @@
+[/
+ 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
+]
+
+[section:stack Stack allocation]
+
+A __fcontext__ requires a stack which will be allocated/deallocated
+by a __stack_allocator__.
+__boost_context__ uses `stack_allocator` by default but a
+customized `stack allocator` can be passed to the context constructor
+instead.
+If a context is constructed it invokes __stack_alloc__ function and by its
+destruction the stack gets released by __stack_dealloc__.
+
+[heading __stack_allocator_concept__]
+A __stack_allocator__ must satisfy the __stack_allocator_concept__ requirements
+shown in the following table, in which `a` is an object of a
+__stack_allocator__ type, `p` is a `void *`, and `s` is a `std::size_t`:
+
+[table
+ [[expression][return type][notes]]
+ [
+ [`a.allocate( s)`]
+ [`void *`]
+ [returns a pointer to `s` bytes allocated from the stack]
+ ]
+ [
+ [`a.deallocate( p, s)`]
+ [`void`]
+ [deallocates `s` bytes of memory beginning at `p`,
+ a pointer previously returned by `a.allocate()`]
+ ]
+]
+
+[important The implementation of `allocate()` might include logic to protect
+against exceeding the context's available stack size rather than leaving it as
+undefined behaviour.]
+
+[important Calling `deallocate()` with a pointer not returned by `allocate()`
+results in undefined behaviour.]
+
+[note The stack is not required to be aligned; alignment takes place inside
+`make_fcontext()`.]
+
+
+[section:stack_allocator Class `stack_allocator`]
+
+__boost_context__ provides a __stack_allocator__ `stack_allocator` which models
+the __stack_allocator_concept__ concept.
+It appends a __guard_page__ to protect against exceeding the stack. If the guard
+page is accessed (read or write operation) a segmentation fault/access violation
+is generated by the operating system.
+
+[endsect]
+
+
+[section:stack_helper Helper functions]
+
+__boost_context__ provides easy access to the stack related limits defined by
+the environment.
+
+ std::size_t default_stacksize();
+
+ std::size_t minimum_stacksize();
+
+ std::size_t maximum_stacksize();
+
+ bool is_stack_unbound();
+
+ std::size_t pagesize();
+
+ std::size_t page_count( std::size_t stacksize);
+
+[heading `std::size_t default_stacksize()`]
+[variablelist
+[[Returns:] [Returns a default stack size, which may be platform specific.
+The present implementation returns a value of 256 kB.]]
+]
+
+[heading `std::size_t minimum_stacksize()`]
+[variablelist
+[[Returns:] [Returns the minimum size in bytes of stack defined by the environment.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `std::size_t maximum_stacksize()`]
+[variablelist
+[[Preconditions:] [`is_stack_unbound()` returns `false`.]]
+[[Returns:] [Returns the maximum size in bytes of stack defined by the environment.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool is_stack_unbound()`]
+[variablelist
+[[Returns:] [Returns `true` if the environment defines no limit for the size of a stack.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `std::size_t pagesize()`]
+[variablelist
+[[Returns:] [Returns how many bytes the operating system allocates for one page.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `std::size_t page_count( std::size_t stacksize)`]
+[variablelist
+[[Returns:] [Returns how many pages have to be allocated for a stack of `stacksize` bytes.]]
+[[Throws:] [Nothing.]]
+]
+
+[endsect]
+
+[endsect]
Deleted: trunk/libs/context/doc/stack_ref.qbk
==============================================================================
--- trunk/libs/context/doc/stack_ref.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,116 +0,0 @@
-[/
- 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
-]
-
-[section:stack Stack allocation]
-
-A __context__ requires a stack which will be allocated/deallocated
-by a __stack_allocator__.
-__boost_context__ uses `stack_allocator` by default but a
-customized `stack allocator` can be passed to the context constructor
-instead.
-If a context is constructed it invokes __stack_alloc__ function and by its
-destruction the stack gets released by __stack_dealloc__.
-
-[heading __stack_allocator_concept__]
-A __stack_allocator__ must satisfy the __stack_allocator_concept__ requirements
-shown in the following table, in which `a` is an object of a
-__stack_allocator__ type, `p` is a `void *`, and `s` is a `std::size_t`:
-
-[table
- [[expression][return type][notes]]
- [
- [`a.allocate( s)`]
- [`void *`]
- [returns a pointer to `s` bytes allocated from the stack]
- ]
- [
- [`a.deallocate( p, s)`]
- [`void`]
- [deallocates `s` bytes of memory beginning at `p`,
- a pointer previously returned by `a.allocate()`]
- ]
-]
-
-[important The implementation of `allocate()` might include logic to protect
-against exceeding the context's available stack size rather than leaving it as
-undefined behaviour.]
-
-[important Calling `deallocate()` with a pointer not returned by `allocate()`
-results in undefined behaviour.]
-
-[note The stack is not required to be aligned; alignment takes place inside
-`boost_fcontext_make()`.]
-
-
-[section:stack_allocator Class `stack_allocator`]
-
-__boost_context__ provides a __stack_allocator__ `stack_allocator` which models
-the __stack_allocator_concept__ concept.
-It appends a __guard_page__ to protect against exceeding the stack. If the guard
-page is accessed (read or write operation) a segmentation fault/access violation
-is generated by the operating system.
-
-[endsect]
-
-
-[section:stack_helper Helper functions]
-
-__boost_context__ provides easy access to the stack related limits defined by
-the environment.
-
- std::size_t default_stacksize();
-
- std::size_t minimum_stacksize();
-
- std::size_t maximum_stacksize();
-
- bool is_stack_unbound();
-
- std::size_t pagesize();
-
- std::size_t page_count( std::size_t stacksize);
-
-[heading `std::size_t default_stacksize()`]
-[variablelist
-[[Returns:] [Returns a default stack size, which may be platform specific.
-The present implementation returns a value of 256 kB.]]
-]
-
-[heading `std::size_t minimum_stacksize()`]
-[variablelist
-[[Returns:] [Returns the minimum size in bytes of stack defined by the environment.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `std::size_t maximum_stacksize()`]
-[variablelist
-[[Preconditions:] [`is_stack_unbound()` returns `false`.]]
-[[Returns:] [Returns the maximum size in bytes of stack defined by the environment.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool is_stack_unbound()`]
-[variablelist
-[[Returns:] [Returns `true` if the environment defines no limit for the size of a stack.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `std::size_t pagesize()`]
-[variablelist
-[[Returns:] [Returns how many bytes the operating system allocates for one page.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `std::size_t page_count( std::size_t stacksize)`]
-[variablelist
-[[Returns:] [Returns how many pages have to be allocated for a stack of `stacksize` bytes.]]
-[[Throws:] [Nothing.]]
-]
-
-[endsect]
-
-[endsect]
Modified: trunk/libs/context/doc/tested.qbk
==============================================================================
--- trunk/libs/context/doc/tested.qbk (original)
+++ trunk/libs/context/doc/tested.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -40,30 +40,12 @@
[SYSV]
]
[
- [X86_64 (Intel Core2 Quad)]
- [Ubuntu GNU/Linux (Lucid Lynx)]
- [Intel 12.0.2]
- [SYSV]
- ]
- [
- [X86_64 (Intel Core2 Quad)]
- [Ubuntu GNU/Linux (Lucid Lynx)]
- [PGI 12.2]
- [SYSV]
- ]
- [
[X86_64]
[Windows 7]
[MS VC 10.0]
[PE]
]
[
- [X86_64]
- [Windows 7]
- [mingw ]
- [PE]
- ]
- [
[I386]
[Debian GNU/Linux (Lenny)]
[GCC 4.4.3]
Modified: trunk/libs/context/doc/todo.qbk
==============================================================================
--- trunk/libs/context/doc/todo.qbk (original)
+++ trunk/libs/context/doc/todo.qbk 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -8,5 +8,6 @@
[section:todo Todo]
* provide support for SPARC
+* support split-stack feature from gcc/gold linker
[endsect]
Modified: trunk/libs/context/example/Jamfile.v2
==============================================================================
--- trunk/libs/context/example/Jamfile.v2 (original)
+++ trunk/libs/context/example/Jamfile.v2 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -47,66 +47,14 @@
<link>static
;
-exe base_api
- : base_api.cpp
- ;
-
-exe exit
- : exit.cpp
- ;
-
-exe do_return
- : do_return.cpp
- ;
+exe jump
+ : jump.cpp
+ ;
exe link
- : link.cpp
- ;
-
-exe swap
- : swap.cpp
- ;
-
-exe unwind
- : unwind.cpp
- ;
-
-exe float
- : float.cpp
- ;
+ : link.cpp
+ ;
exe transfer
- : transfer.cpp
- ;
-
-exe enumerate_string
- : enumerator/enumerate_string.cpp
- ;
-
-exe enumerate_tree
- : enumerator/enumerate_tree.cpp
- ;
-
-exe fringe
- : enumerator/fringe.cpp
- ;
-
-exe power
- : enumerator/power.cpp
- ;
-
-exe echo
- : continuation/echo.cpp
- ;
-
-exe parallel
- : continuation/parallel.cpp
- ;
-
-exe echo_client
- : asio/echo_client.cpp
- ;
-
-exe echo_server
- : asio/echo_server.cpp
- ;
+ : transfer.cpp
+ ;
Deleted: trunk/libs/context/example/base_api.cpp
==============================================================================
--- trunk/libs/context/example/base_api.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,55 +0,0 @@
-
-// 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)
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <vector>
-
-#include <boost/assert.hpp>
-#include <boost/context/all.hpp>
-
-boost_fcontext_t fcm, fc1, fc2;
-
-void f1( intptr_t p)
-{
- (void) p;
- fprintf(stderr,"f1() stated\n");
- fprintf(stderr,"f1: call boost_fcontext_jump( & fc1, & fc2)\n");
- boost_fcontext_jump( & fc1, & fc2, 0);
- fprintf(stderr,"f1() returns\n");
-}
-
-void f2( intptr_t p)
-{
- (void) p;
- fprintf(stderr,"f2() stated\n");
- fprintf(stderr,"f2: call boost_fcontext_jump( & fc2, & fc1)\n");
- boost_fcontext_jump( & fc2, & fc1, 0);
- BOOST_ASSERT( false && ! "f2() never returns");
-}
-
-int main( int argc, char * argv[])
-{
- boost::contexts::stack_allocator alloc;
-
- fc1.fc_stack.ss_base = alloc.allocate(262144);
- fc1.fc_stack.ss_limit =
- static_cast< char * >( fc1.fc_stack.ss_base) - 262144;
- fc1.fc_link = & fcm;
- boost_fcontext_make( & fc1, f1, 0);
-
- fc2.fc_stack.ss_base = alloc.allocate(262144);
- fc2.fc_stack.ss_limit =
- static_cast< char * >( fc2.fc_stack.ss_base) - 262144;
- boost_fcontext_make( & fc2, f2, 0);
-
- fprintf(stderr,"main: call boost_fcontext_start( & fcm, & fc1)\n");
- boost_fcontext_start( & fcm, & fc1);
-
- fprintf( stderr, "main() returns\n");
- return EXIT_SUCCESS;
-}
Deleted: trunk/libs/context/example/do_return.cpp
==============================================================================
--- trunk/libs/context/example/do_return.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,33 +0,0 @@
-
-// 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)
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-
-#include <boost/context/all.hpp>
-#include <boost/move/move.hpp>
-
-void fn()
-{
- std::cout << "inside function fn(): fn() returns return to main()" << std::endl;
-}
-
-int main( int argc, char * argv[])
-{
- {
- boost::contexts::context ctx(
- fn,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind, boost::contexts::return_to_caller);
-
- ctx.start();
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
-}
Deleted: trunk/libs/context/example/exit.cpp
==============================================================================
--- trunk/libs/context/example/exit.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,33 +0,0 @@
-
-// 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)
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-
-#include <boost/context/all.hpp>
-#include <boost/move/move.hpp>
-
-void fn()
-{
- std::cout << "inside function fn(): when fn() returns ::exit() will be called; no return to main()" << std::endl;
-}
-
-int main( int argc, char * argv[])
-{
- {
- boost::contexts::context ctx(
- fn,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind, boost::contexts::exit_application);
-
- ctx.start();
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
-}
Deleted: trunk/libs/context/example/float.cpp
==============================================================================
--- trunk/libs/context/example/float.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,31 +0,0 @@
-
-// 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)
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-
-#include <boost/context/all.hpp>
-#include <boost/move/move.hpp>
-
-void fn( double d)
-{
- d += 3.45;
- std::cout << "d == " << d << std::endl;
-}
-
-int main( int argc, char * argv[])
-{
- boost::contexts::context ctx(
- fn, 7.34,
- boost::contexts::default_stacksize(),
- boost::contexts::stack_unwind, boost::contexts::return_to_caller);
- ctx.start();
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
-}
Added: trunk/libs/context/example/jump.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/context/example/jump.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -0,0 +1,56 @@
+
+// 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)
+
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/context/all.hpp>
+
+namespace ctx = boost::ctx;
+
+ctx::fcontext_t fcm, fc1, fc2;
+
+void f1( intptr_t)
+{
+ std::cout << "f1: entered" << std::endl;
+ std::cout << "f1: call jump_fcontext( & fc1, & fc2)" << std::endl;
+ ctx::jump_fcontext( & fc1, & fc2, 0);
+ std::cout << "f1: return" << std::endl;
+ ctx::jump_fcontext( & fc1, & fcm, 0);
+}
+
+void f2( intptr_t)
+{
+ std::cout << "f2: entered" << std::endl;
+ std::cout << "f2: call jump_fcontext( & fc2, & fc1)" << std::endl;
+ ctx::jump_fcontext( & fc2, & fc1, 0);
+ BOOST_ASSERT( false && ! "f2: never returns");
+}
+
+int main( int argc, char * argv[])
+{
+ ctx::stack_allocator alloc1, alloc2;
+
+ fc1.fc_stack.base = alloc1.allocate(ctx::minimum_stacksize());
+ fc1.fc_stack.limit =
+ static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc1, f1, 0);
+
+ fc2.fc_stack.base = alloc2.allocate(ctx::minimum_stacksize());
+ fc2.fc_stack.limit =
+ static_cast< char * >( fc2.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc2, f2, 0);
+
+ std::cout << "main: call start_fcontext( & fcm, & fc1)" << std::endl;
+ ctx::start_fcontext( & fcm, & fc1);
+
+ std::cout << "main: done" << std::endl;
+
+ return EXIT_SUCCESS;
+}
Modified: trunk/libs/context/example/link.cpp
==============================================================================
--- trunk/libs/context/example/link.cpp (original)
+++ trunk/libs/context/example/link.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -5,47 +5,53 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <cstdlib>
+#include <cstring>
#include <iostream>
-#include <string>
+#include <vector>
+#include <boost/assert.hpp>
#include <boost/context/all.hpp>
-void fn1()
+namespace ctx = boost::ctx;
+
+ctx::fcontext_t fc1, fc2;
+
+void f1( intptr_t)
{
- std::cout << "inside fn1(): when fn1() returns fn2() of next context (linked) will be entered" << std::endl;
+ std::cout << "f1: entered" << std::endl;
+ std::cout << "f1: call jump_fcontext( & fc1, & fc2)" << std::endl;
+ ctx::jump_fcontext( & fc1, & fc2, 0);
+ std::cout << "f1: return" << std::endl;
}
-boost::contexts::context ctx2;
-
-void fn2()
+void f2( intptr_t)
{
- std::cout << "first time inside fn2()" << std::endl;
- ctx2.suspend();
- std::cout << "second time inside fn2(), returns to main()" << std::endl;
+ std::cout << "f2: entered" << std::endl;
+ std::cout << "f2: call jump_fcontext( & fc2, & fc1)" << std::endl;
+ ctx::jump_fcontext( & fc2, & fc1, 0);
+ BOOST_ASSERT( false && ! "f2: never returns");
}
int main( int argc, char * argv[])
{
- {
- ctx2 = boost::contexts::context(
- fn2,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind, boost::contexts::return_to_caller);
- boost::contexts::context ctx1(
- fn1,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- ctx2);
-
- ctx1.start();
- }
+ ctx::fcontext_t fcm;
+ ctx::stack_allocator alloc;
- std::cout << "main(): ctx1 is destructed\n";
+ fc1.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc1.fc_stack.limit =
+ static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ fc1.fc_link = & fcm;
+ ctx::make_fcontext( & fc1, f1, 0);
+
+ fc2.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc2.fc_stack.limit =
+ static_cast< char * >( fc2.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc2, f2, 0);
- std::cout << "main(): resume ctx2\n";
- ctx2.resume();
+ std::cout << "main: call start_fcontext( & fcm, & fc1)" << std::endl;
+ ctx::start_fcontext( & fcm, & fc1);
- std::cout << "Done" << std::endl;
+ std::cout << "main: done" << std::endl;
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
Deleted: trunk/libs/context/example/pic.sh
==============================================================================
--- trunk/libs/context/example/pic.sh 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-g++ -x assembler-with-cpp -fPIC -O3 -finline-functions -Wno-inline -Wall -march=native -DBOOST_ALL_NO_LIB=1 -DBOOST_CONTEXT_DYN_LINK=1 -DNDEBUG -I../../.. -c -o fcontext_i386_sysv_elf_gas.o ../src/asm/fcontext_i386_sysv_elf_gas.S
-
-g++ -ftemplate-depth-128 -fPIC -O3 -finline-functions -Wno-inline -Wall -march=native -DBOOST_ALL_NO_LIB=1 -DBOOST_CONTEXT_DYN_LINK=1 -DNDEBUG -I../../.. -c -o fcontext.o ../src/fcontext.cpp
-
-g++ -ftemplate-depth-128 -fPIC -O3 -finline-functions -Wno-inline -Wall -march=native -DBOOST_ALL_NO_LIB=1 -DBOOST_CONTEXT_DYN_LINK=1 -DNDEBUG -I../../.. -c -o stack_allocator_posix.o ../src/stack_allocator_posix.cpp
-
-g++ -ftemplate-depth-128 -fPIC -O3 -finline-functions -Wno-inline -Wall -march=native -DBOOST_ALL_NO_LIB=1 -DBOOST_CONTEXT_DYN_LINK=1 -DNDEBUG -I../../.. -c -o stack_utils_posix.o ../src/stack_utils_posix.cpp
-
-gcc -shared -Wl,-soname,libboost_my_lib.so -o libboost_my_lib.so fcontext.o stack_allocator_posix.o stack_utils_posix.o fcontext_i386_sysv_elf_gas.o -lc -lstdc++
-
-gcc -g ./transfer.cpp -I../../../ -L./ -Wl,-rpath=./ -lboost_my_lib -lrt
Deleted: trunk/libs/context/example/swap.cpp
==============================================================================
--- trunk/libs/context/example/swap.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,41 +0,0 @@
-
-// 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)
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-
-#include <boost/context/all.hpp>
-#include <boost/move/move.hpp>
-
-int x = 7;
-void fn( int);
-
-boost::contexts::context ctx( fn, x, boost::contexts::default_stacksize(), boost::contexts::no_stack_unwind, boost::contexts::return_to_caller);
-
-void fn( int j)
-{
- for( int i = 0; i < j; ++i)
- {
- std::cout << "fn(): local variable i == " << i << std::endl;
- ctx.suspend();
- }
-}
-
-int main( int argc, char * argv[])
-{
- std::cout << "main() calls context ctx" << std::endl;
- ctx.start();
- while ( ! ctx.is_complete() )
- {
- std::cout << "main() calls context ctx" << std::endl;
- ctx.resume();
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
-}
Modified: trunk/libs/context/example/transfer.cpp
==============================================================================
--- trunk/libs/context/example/transfer.cpp (original)
+++ trunk/libs/context/example/transfer.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -5,49 +5,48 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <cstdlib>
+#include <cstring>
#include <iostream>
-#include <string>
+#include <utility>
+#include <vector>
+#include <boost/assert.hpp>
#include <boost/context/all.hpp>
+namespace ctx = boost::ctx;
-boost::contexts::context ctx;
+ctx::fcontext_t fc1, fcm;
-void fn()
+typedef std::pair< int, int > pair_t;
+
+void f1( intptr_t param)
{
- int i = 7;
- std::cout << "fn(): local variable i == " << i << std::endl;
+ pair_t * p = ( pair_t *) param;
- // save current context
- // transfer execution control back to caller
- // pass pointer to local variable i
- intptr_t vp = ctx.suspend( i);
- int j = vp;
+ p = ( pair_t *) ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) ( p->first + p->second) );
- std::cout << "transfered value: " << j << std::endl;
+ ctx::jump_fcontext( & fc1, & fcm, ( intptr_t) ( p->first + p->second) );
}
int main( int argc, char * argv[])
{
- ctx = boost::contexts::context( fn,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind,
- boost::contexts::return_to_caller);
-
- std::cout << "main() calls context ctx" << std::endl;
-
- // start the context ctx for the first time
- // enter fn()
- intptr_t vp = ctx.start();
- int x = vp;
-
- std::cout << "transfered value: " << x << std::endl;
- x = 10;
-
- // ctx.suspend() was called so we returned from start()
- ctx.resume( x);
-
- std::cout << "Done" << std::endl;
-
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc1.fc_stack.limit =
+ static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ fc1.fc_link = & fcm;
+ pair_t p( std::make_pair( 2, 7) );
+ ctx::make_fcontext( & fc1, f1, ( intptr_t) & p);
+
+ int res = ( int) ctx::start_fcontext( & fcm, & fc1);
+ std::cout << p.first << " + " << p.second << " == " << res << std::endl;
+
+ p = std::make_pair( 5, 6);
+ res = ( int) ctx::jump_fcontext( & fcm, & fc1, ( intptr_t) & p);
+ std::cout << p.first << " + " << p.second << " == " << res << std::endl;
+
+ std::cout << "main: done" << std::endl;
+
return EXIT_SUCCESS;
}
Deleted: trunk/libs/context/example/unwind.cpp
==============================================================================
--- trunk/libs/context/example/unwind.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
+++ (empty file)
@@ -1,53 +0,0 @@
-
-// 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)
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-
-#include <boost/context/all.hpp>
-
-boost::contexts::context ctx;
-
-struct X
-{
- X()
- { std::cout << "X()" << std::endl; }
-
- ~X()
- { std::cout << "~X()" << std::endl; }
-};
-
-void fn( int n)
-{
- if ( 0 < n)
- {
- X x;
- fn ( --n);
- }
- else
- {
- ctx.suspend();
- }
-}
-
-int main( int argc, char * argv[])
-{
- ctx = boost::contexts::context(
- fn, 5,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind, boost::contexts::return_to_caller);
- ctx.start();
-
- std::cout << "ctx is complete: " << std::boolalpha << ctx.is_complete() << "\n";
- std::cout << "call ctx.unwind_stack()" << std::endl;
- ctx.unwind_stack();
- std::cout << "ctx is complete: " << std::boolalpha << ctx.is_complete() << "\n";
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
-}
Modified: trunk/libs/context/performance/performance.cpp
==============================================================================
--- trunk/libs/context/performance/performance.cpp (original)
+++ trunk/libs/context/performance/performance.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -17,43 +17,18 @@
#include "bind_processor.hpp"
#include "performance.hpp"
+namespace ctx = boost::ctx;
namespace po = boost::program_options;
-boost::contexts::context c;
+ctx::fcontext_t fc, fcm;
-void fn()
-{ c.suspend(); }
-
-void test_creation( unsigned int iterations)
+void fn( intptr_t param)
{
- cycle_t total( 0);
- cycle_t overhead( get_overhead() );
- std::cout << "overhead for rdtsc == " << overhead << " cycles" << std::endl;
-
- // cache warm-up
- {
- c = boost::contexts::context(
- fn,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind, boost::contexts::return_to_caller);
- }
-
- for ( unsigned int i = 0; i < iterations; ++i)
- {
- cycle_t start( get_cycles() );
- c = boost::contexts::context(
- fn,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind, boost::contexts::return_to_caller);
- cycle_t diff( get_cycles() - start);
- diff -= overhead;
- BOOST_ASSERT( diff >= 0);
- total += diff;
- }
- std::cout << "average of " << total/iterations << " cycles per creation" << std::endl;
+ while ( param)
+ ctx::jump_fcontext( & fc, & fcm, 0);
}
-void test_switching( unsigned int iterations)
+void test( unsigned int iterations)
{
cycle_t total( 0);
cycle_t overhead( get_overhead() );
@@ -61,22 +36,20 @@
// cache warum-up
{
- c = boost::contexts::context(
- fn,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind, boost::contexts::return_to_caller);
- c.start();
- c.resume();
+ ctx::stack_allocator alloc;
+
+ fc.fc_stack.base = alloc.allocate(ctx::minimum_stacksize());
+ fc.fc_stack.limit =
+ static_cast< char * >( fc.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc, fn, 1);
+ ctx::start_fcontext( & fcm, & fc);
+ ctx::jump_fcontext( & fcm, & fc, 1);
}
for ( unsigned int i = 0; i < iterations; ++i)
{
- c = boost::contexts::context(
- fn,
- boost::contexts::default_stacksize(),
- boost::contexts::no_stack_unwind, boost::contexts::return_to_caller);
cycle_t start( get_cycles() );
- c.start();
+ ctx::jump_fcontext( & fcm, & fc, 1);
cycle_t diff( get_cycles() - start);
// we have two jumps and two measuremt-overheads
@@ -98,8 +71,6 @@
po::options_description desc("allowed options");
desc.add_options()
("help,h", "help message")
- ("creating,c", "test creation")
- ("switching,s", "test switching")
("iterations,i", po::value< unsigned int >( & iterations), "iterations");
po::variables_map vm;
@@ -121,11 +92,7 @@
bind_to_processor( 0);
- if ( vm.count("creating") )
- test_creation( iterations);
-
- if ( vm.count("switching") )
- test_switching( iterations);
+ test( iterations);
return EXIT_SUCCESS;
}
Modified: trunk/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S (original)
+++ trunk/libs/context/src/asm/fcontext_arm_aapcs_elf_gas.S 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -53,10 +53,10 @@
* *****************************************************************/
.text
-.globl boost_fcontext_start
+.globl start_fcontext
.align 2
-.type boost_fcontext_start,%function
-boost_fcontext_start:
+.type start_fcontext,%function
+start_fcontext:
stmia a1, {v1-v8,sp-lr} @ save V1-V8,SP-LR
str lr, [a1,#40] @ save LR as PC
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
@@ -71,13 +71,13 @@
#endif
ldmia a2, {v1-v8,sp-pc} @ restore v1-V8,SP-PC
-.size boost_fcontext_start,.-boost_fcontext_start
+.size start_fcontext,.-start_fcontext
.text
-.globl boost_fcontext_jump
+.globl jump_fcontext
.align 2
-.type boost_fcontext_jump,%function
-boost_fcontext_jump:
+.type jump_fcontext,%function
+jump_fcontext:
stmia a1, {v1-v8,sp-lr} @ save V1-V8,SP-LR
str lr, [a1,#40] @ save LR as PC
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
@@ -92,21 +92,21 @@
#endif
ldmia a2, {v1-v8,sp-pc} @ restore v1-V8,SP-PC
-.size boost_fcontext_jump,.-boost_fcontext_jump
+.size jump_fcontext,.-jump_fcontext
.text
-.globl boost_fcontext_make
+.globl make_fcontext
.align 2
-.type boost_fcontext_make,%function
-boost_fcontext_make:
+.type make_fcontext,%function
+make_fcontext:
str a1, [a1,#0] @ save the address of the current context
str a2, [a1,#40] @ save address of the function supposed to be run
str a3, [a1,#8] @ save void pointer
ldr a2, [a1,#108] @ load the stack base
push {a1,lr} @ save pointer to fcontext_t
- mov a1, a2 @ stack pointer as arg for boost_fcontext_align
- bl boost_fcontext_align_at_PLT @ align stack
+ mov a1, a2 @ stack pointer as arg for align_stack
+ bl align_stack_at_PLT @ align stack
mov a2, a1 @ begin of aligned stack
pop {a1,lr} @ restore pointer to boost_fcontext_t
@@ -123,8 +123,8 @@
mov a2, v2 @ load the adddress of the next context
teq a2, #0 @ test if the address of the next context is a null pointer
- bne boost_fcontext_start_at_PLT @ install next context
+ bne start_fcontext_at_PLT @ install next context
mov a1, #0
bl _exit_at_PLT @ exit application
-.size boost_fcontext_make,.-boost_fcontext_make
+.size make_fcontext,.-make_fcontext
Modified: trunk/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm
==============================================================================
--- trunk/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm (original)
+++ trunk/libs/context/src/asm/fcontext_i386_ms_pe_masm.asm 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -44,12 +44,12 @@
.XMM
.model flat, c
_exit PROTO, value:SDWORD
-boost_fcontext_align PROTO, vp:DWORD
-boost_fcontext_seh PROTO, except:DWORD, frame:DWORD, context:DWORD, dispatch:DWORD
-boost_fcontext_start PROTO, from:DWORD, to:DWORD, vp:DWORD
+align_stack PROTO, vp:DWORD
+seh_fcontext PROTO, except:DWORD, frame:DWORD, context:DWORD, dispatch:DWORD
+start_fcontext PROTO, from:DWORD, to:DWORD, vp:DWORD
.code
-boost_fcontext_jump PROC EXPORT
+jump_fcontext PROC EXPORT
mov ecx, [esp+04h] ; load address of the first fcontext_t arg
mov [ecx], edi ; save EDI
mov [ecx+04h], esi ; save ESI
@@ -104,9 +104,9 @@
mov ecx, [ecx+014h] ; fetch the address to return to
jmp ecx ; indirect jump to context
-boost_fcontext_jump ENDP
+jump_fcontext ENDP
-boost_fcontext_make PROC EXPORT
+make_fcontext PROC EXPORT
mov eax, [esp+04h] ; load address of the fcontext_t arg0
mov [eax], eax ; save the address of current context
mov ecx, [esp+08h] ; load the address of the function supposed to run
@@ -114,16 +114,16 @@
mov edx, [eax+020h] ; load the stack base
push eax ; save pointer to fcontext_t
- push edx ; stack pointer as arg for boost_fcontext_align
- call boost_fcontext_align ; align stack
+ push edx ; stack pointer as arg for align_stack
+ call align_stack ; align stack
mov edx, eax ; begin of aligned stack
- pop eax ; remove arg for boost_fcontext_align
+ pop eax ; remove arg for align_stack
pop eax ; restore pointer to fcontext_t
lea edx, [edx-014h] ; reserve space for last frame on stack, (ESP + 4) % 16 == 0
mov [eax+010h], edx ; save the address
- mov ecx, boost_fcontext_seh ; set ECX to exception-handler
+ mov ecx, seh_fcontext ; set ECX to exception-handler
mov [edx+0ch], ecx ; save ECX as SEH handler
mov ecx, 0ffffffffh ; set ECX to -1
mov [edx+08h], ecx ; save ECX as next SEH item
@@ -136,25 +136,25 @@
mov [edx+04h], ecx ; save the address of the void pointer onto the context stack
stmxcsr [eax+018h] ; save SSE2 control word
fnstcw [eax+01ch] ; save x87 control word
- mov ecx, boost_fcontext_link ; load helper code executed after fn() returns
+ mov ecx, link_fcontext ; load helper code executed after fn() returns
mov [edx], ecx ; save helper code executed adter fn() returns
xor eax, eax ; set EAX to zero
ret
-boost_fcontext_make ENDP
+make_fcontext ENDP
-boost_fcontext_link PROC
+link_fcontext PROC
lea esp, [esp-0ch] ; adjust the stack to proper boundaries
test esi, esi ; test if a next context was given
je finish ; jump to finish
push esi ; push the address of the next context on the stack
push edi ; push the address of the current context on the stack
- call boost_fcontext_start ; install next context
+ call start_fcontext ; install next context
finish:
xor eax, eax ; set EAX to zero
push eax ; exit code is zero
call _exit ; exit application
hlt
-boost_fcontext_link ENDP
+link_fcontext ENDP
END
Modified: trunk/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S (original)
+++ trunk/libs/context/src/asm/fcontext_i386_sysv_elf_gas.S 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -39,10 +39,10 @@
* *****************************************************************/
.text
-.globl boost_fcontext_jump
+.globl jump_fcontext
.align 2
-.type boost_fcontext_jump,@function
-boost_fcontext_jump:
+.type jump_fcontext,@function
+jump_fcontext:
movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */
movl %edi, (%ecx) /* save EDI */
movl %esi, 0x4(%ecx) /* save ESI */
@@ -73,13 +73,13 @@
movl 0x14(%ecx), %ecx /* fetch the address to return to */
jmp *%ecx /* indirect jump to context */
-.size boost_fcontext_jump,.-boost_fcontext_jump
+.size jump_fcontext,.-jump_fcontext
.text
-.globl boost_fcontext_make
+.globl make_fcontext
.align 2
-.type boost_fcontext_make,@function
-boost_fcontext_make:
+.type make_fcontext,@function
+make_fcontext:
movl 0x4(%esp), %eax /* load address of the fcontext_t */
movl %eax, (%eax) /* save the address of current context */
movl 0x8(%esp), %ecx /* load the address of the function supposed to run */
@@ -88,13 +88,13 @@
pushl %eax /* save pointer to fcontext_t */
pushl %ebx /* save EBX */
- pushl %edx /* stack pointer as arg for boost_fcontext_align */
+ pushl %edx /* stack pointer as arg for align_stack */
call 1f
1: popl %ebx /* address of label 1 */
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* compute address of GOT and store it in EBX */
- call boost_fcontext_align_at_PLT /* align stack */
+ call align_stack_at_PLT /* align stack */
movl %eax, %edx /* begin of aligned stack */
- popl %eax /* remove arg for boost_fcontext_align */
+ popl %eax /* remove arg for align_stack */
popl %ebx /* restore EBX */
popl %eax /* restore pointer to fcontext_t */
@@ -126,11 +126,11 @@
pushl %esi /* push the address of the next context on the stack */
pushl %edi /* push the address of the current context to stack */
- call boost_fcontext_start_at_PLT /* jump to next context */
+ call start_fcontext_at_PLT /* jump to next context */
4:
movl %eax, %eax
pushl %eax /* exit code is zero */
call _exit_at_PLT /* exit application */
hlt
-.size boost_fcontext_make,.-boost_fcontext_make
+.size make_fcontext,.-make_fcontext
Modified: trunk/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S (original)
+++ trunk/libs/context/src/asm/fcontext_i386_sysv_macho_gas.S 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -39,9 +39,9 @@
* *****************************************************************/
.text
-.globl _boost_fcontext_jump
+.globl _jump_fcontext
.align 2
-_boost_fcontext_jump:
+_jump_fcontext:
movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */
movl %edi, (%ecx) /* save EDI */
movl %esi, 0x4(%ecx) /* save ESI */
@@ -74,9 +74,9 @@
jmp *%ecx /* indirect jump to context */
.text
-.globl _boost_fcontext_make
+.globl _make_fcontext
.align 2
-_boost_fcontext_make:
+_make_fcontext:
movl 0x4(%esp), %eax /* load address of the fcontext_t */
movl %eax, (%eax) /* save the address of current context */
movl 0x8(%esp), %ecx /* load the address of the function supposed to run */
@@ -85,13 +85,13 @@
pushl %eax /* save pointer to fcontext_t */
pushl %ebx /* save EBX */
- pushl %edx /* stack pointer as arg for boost_fcontext_align */
+ pushl %edx /* stack pointer as arg for align_stack */
call 1f
1: popl %ebx /* address of label 1 */
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* compute address of GOT and store it in EBX */
- call boost_fcontext_align_at_PLT /* align stack */
+ call align_stack_at_PLT /* align stack */
movl %eax, %edx /* begin of aligned stack */
- popl %eax /* remove arg for boost_fcontext_align */
+ popl %eax /* remove arg for align_stack */
popl %ebx /* restore EBX */
popl %eax /* restore pointer to fcontext_t */
@@ -123,7 +123,7 @@
pushl %esi /* push the address of the next context on the stack */
pushl %edi /* push the address of the current context to stack */
- call boost_fcontext_start_at_PLT /* jump to next context */
+ call start_fcontext_at_PLT /* jump to next context */
4:
movl %eax, %eax
Modified: trunk/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S (original)
+++ trunk/libs/context/src/asm/fcontext_mips32_o32_elf_gas.S 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -46,11 +46,11 @@
* *****************************************************************/
.text
-.globl boost_fcontext_jump
+.globl jump_fcontext
.align 2
-.type boost_fcontext_jump,@function
-.ent boost_fcontext_jump
-boost_fcontext_jump:
+.type jump_fcontext,@function
+.ent jump_fcontext
+jump_fcontext:
sw $s0, ($a0) # save S0
sw $s1, 8($a0) # save S1
sw $s2, 16($a0) # save S2
@@ -102,15 +102,15 @@
lw $t9, 96($a1) # load PC
jr $t9 # jump to context
-.end boost_fcontext_jump
-.size boost_fcontext_jump, .-boost_fcontext_jump
+.end jump_fcontext
+.size jump_fcontext, .-jump_fcontext
.text
-.globl boost_fcontext_make
+.globl make_fcontext
.align 2
-.type boost_fcontext_make,@function
-.ent boost_fcontext_make
-boost_fcontext_make:
+.type make_fcontext,@function
+.ent make_fcontext
+make_fcontext:
#ifdef __PIC__
.set noreorder
.cpload $t9
@@ -125,8 +125,8 @@
sub $sp, $sp, 28
sw $ra, 24($sp)
sw $a0, 20($sp)
- move $a0, $t0 # stack pointer as arg for boost_fcontext_align
- lw $t9, %call16(boost_fcontext_align)($gp) # align stack
+ move $a0, $t0 # stack pointer as arg for align_stack
+ lw $t9, %call16(align_stack)($gp) # align stack
jalr $t9
nop
move $t0, $v0 # begin of aligned stack
@@ -150,12 +150,12 @@
beqz $a1, 2f # test if a next context was given
move $a0, $s0 # set A0 to address of current context
- lw $t9, %call16(boost_fcontext_start)($gp) # install next context
+ lw $t9, %call16(start_fcontext)($gp) # install next context
jr $t9
2:
move $a0, $zero
lw $t9, %call16(_exit)($gp) # exit application
jalr $t9
-.end boost_fcontext_make
-.size boost_fcontext_make, .-boost_fcontext_make
+.end make_fcontext
+.size make_fcontext, .-make_fcontext
Modified: trunk/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S (original)
+++ trunk/libs/context/src/asm/fcontext_ppc32_sysv_elf_gas.S 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -74,10 +74,10 @@
* *****************************************************************/
.text
-.globl boost_fcontext_start
+.globl start_fcontext
.align 2
-.type boost_fcontext_start,@function
-boost_fcontext_start:
+.type start_fcontext,@function
+start_fcontext:
stw %r13, 0(%r3) # save R13
stw %r14, 4(%r3) # save R14
stw %r15, 8(%r3) # save R15
@@ -179,13 +179,13 @@
mtctr %r0 # restore CTR
bctr # start to context
-.size boost_fcontext_start, .-boost_fcontext_start
+.size start_fcontext, .-start_fcontext
.text
-.globl boost_fcontext_jump
+.globl jump_fcontext
.align 2
-.type boost_fcontext_jump,@function
-boost_fcontext_jump:
+.type jump_fcontext,@function
+jump_fcontext:
stw %r13, 0(%r3) # save R13
stw %r14, 4(%r3) # save R14
stw %r15, 8(%r3) # save R15
@@ -288,13 +288,13 @@
mtctr %r0 # restore CTR
bctr # jump to context
-.size boost_fcontext_jump, .-boost_fcontext_jump
+.size jump_fcontext, .-jump_fcontext
.text
-.globl boost_fcontext_make
+.globl make_fcontext
.align 2
-.type boost_fcontext_make,@function
-boost_fcontext_make:
+.type make_fcontext,@function
+make_fcontext:
stw %r3, 0(%r3) # save the current context
stw %r4, 88(%r3) # save the address of the function supposed to to be run
stw %r5, 8(%r3) # save void pointer
@@ -306,7 +306,7 @@
mflr %r4 # load LR
stw %r4, 20(%r1) # store LR on stack
mr. %r3, %r0 # context stack as arg to boost_fcontext_algin
- bl boost_fcontext_align_at_plt # call boost_fcontext_align
+ bl align_stack_at_plt # call align_stack
mr. %r0, %r3 # load result into R0
lwz %r4, 20(%r1) # pop LR from stack
mtlr %r4 # restore LR
@@ -334,9 +334,9 @@
mr. %r4, %r14
beq 2f # test if a next context was given
- bl boost_fcontext_start_at_plt # install next context
+ bl start_fcontext_at_plt # install next context
2:
li %r3, 0 # set return value to zero
bl _exit_at_plt # exit application
-.size boost_fcontext_make, .-boost_fcontext_make
+.size make_fcontext, .-make_fcontext
Modified: trunk/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S (original)
+++ trunk/libs/context/src/asm/fcontext_ppc64_sysv_elf_gas.S 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -89,16 +89,16 @@
.section ".text"
.align 2
-.globl boost_fcontext_start
+.globl start_fcontext
.section ".opd","aw"
.align 3
-boost_fcontext_start:
-.quad .boost_fcontext_start,.TOC._at_tocbase,0
+start_fcontext:
+.quad .start_fcontext,.TOC._at_tocbase,0
.previous
-.size boost_fcontext_start,24
-.type .boost_fcontext_start,@function
-.globl .boost_fcontext_start
-.boost_fcontext_start:
+.size start_fcontext,24
+.type .start_fcontext,@function
+.globl .start_fcontext
+.start_fcontext:
std %r13, 0(%r3) # save R13
std %r14, 8(%r3) # save R14
std %r15, 16(%r3) # save R15
@@ -200,20 +200,20 @@
mtctr %r0 # restore CTR
bctr # start to context
-.size .boost_fcontext_start, .-.boost_fcontext_start
+.size .start_fcontext, .-.start_fcontext
.section ".text"
.align 2
-.globl boost_fcontext_jump
+.globl jump_fcontext
.section ".opd","aw"
.align 3
-boost_fcontext_jump:
-.quad .boost_fcontext_jump,.TOC._at_tocbase,0
+jump_fcontext:
+.quad .jump_fcontext,.TOC._at_tocbase,0
.previous
-.size boost_fcontext_jump,24
-.type .boost_fcontext_jump,@function
-.globl .boost_fcontext_jump
-.boost_fcontext_jump:
+.size jump_fcontext,24
+.type .jump_fcontext,@function
+.globl .jump_fcontext
+.jump_fcontext:
std %r13, 0(%r3) # save R13
std %r14, 8(%r3) # save R14
std %r15, 16(%r3) # save R15
@@ -316,20 +316,20 @@
mtctr %r0 # restore CTR
bctr # jump to context
-.size .boost_fcontext_jump, .-.boost_fcontext_jump
+.size .jump_fcontext, .-.jump_fcontext
.section ".text"
.align 2
-.globl boost_fcontext_make
+.globl make_fcontext
.section ".opd","aw"
.align 3
-boost_fcontext_make:
-.quad .boost_fcontext_make,.TOC._at_tocbase,0
+make_fcontext:
+.quad .make_fcontext,.TOC._at_tocbase,0
.previous
-.size boost_fcontext_make,24
-.type .boost_fcontext_make,@function
-.globl .boost_fcontext_make
-.boost_fcontext_make:
+.size make_fcontext,24
+.type .make_fcontext,@function
+.globl .make_fcontext
+.make_fcontext:
std %r3, 0(%r3) # save the current context
std %r4, 176(%r3) # save the address of the function supposed to be run
std %r5, 16(%r3) # save void pointer
@@ -341,7 +341,7 @@
mflr %r4 # load LR
stw %r4, 40(%r1) # store LR on stack
mr. %r3, %r0 # context stack as arg to boost_fcontext_algin
- bl boost_fcontext_align_at_plt # call boost_fcontext_align
+ bl align_stack_at_plt # call align_stack
mr. %r0, %r3 # load result into R0
lwz %r4, 40(%r1) # pop LR from stack
mtlr %r4 # restore LR
@@ -369,9 +369,9 @@
mr. %r4, %r14
beq 2f # test if a next context was given
- bl boost_fcontext_start_at_plt # install next context
+ bl start_fcontext_at_plt # install next context
2:
li %r3, 0 # set return value to zero
bl _exit_at_plt # exit application
-.size .boost_fcontext_make, .-.boost_fcontext_make
+.size .make_fcontext, .-.make_fcontext
Modified: trunk/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm
==============================================================================
--- trunk/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm (original)
+++ trunk/libs/context/src/asm/fcontext_x86_64_ms_pe_masm.asm 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -55,12 +55,12 @@
; ----------------------------------------------------------------------------------
EXTERN _exit:PROC ; standard C library function
-EXTERN boost_fcontext_align:PROC ; stack alignment
-EXTERN boost_fcontext_seh:PROC ; exception handler
-EXTERN boost_fcontext_start:PROC ; start fcontext
+EXTERN align_stack:PROC ; stack alignment
+EXTERN seh_fcontext:PROC ; exception handler
+EXTERN start_fcontext:PROC ; start fcontext
.code
-boost_fcontext_jump PROC EXPORT FRAME:boost_fcontext_seh
+jump_fcontext PROC EXPORT FRAME:seh_fcontext
.endprolog
mov [rcx], r12 ; save R12
@@ -116,9 +116,9 @@
mov rax, r8 ; use third arg as return value after jump
jmp r9 ; indirect jump to caller
-boost_fcontext_jump ENDP
+jump_fcontext ENDP
-boost_fcontext_make PROC EXPORT FRAME ; generate function table entry in .pdata and unwind information in E
+make_fcontext PROC EXPORT FRAME ; generate function table entry in .pdata and unwind information in E
.endprolog ; .xdata for a function's structured exception handling unwind behavior
mov [rcx], rcx ; store the address of current context
@@ -128,9 +128,9 @@
push rcx ; save pointer to fcontext_t
sub rsp, 028h ; reserve shadow space for boost_fcontext_algin
- mov rcx, rdx ; stack pointer as arg for boost_fcontext_align
+ mov rcx, rdx ; stack pointer as arg for align_stack
mov [rsp+8], rcx
- call boost_fcontext_align ; align stack
+ call align_stack ; align stack
mov rdx, rax ; begin of aligned stack
add rsp, 028h
pop rcx ; restore pointer to fcontext_t
@@ -143,14 +143,14 @@
stmxcsr [rcx+050h] ; save SSE2 control and status word
fnstcw [rcx+054h] ; save x87 control word
- lea rax, boost_fcontext_link ; helper code executed after fn() returns
+ lea rax, link_fcontext ; helper code executed after fn() returns
mov [rdx], rax ; store address off the helper function as return address
xor rax, rax ; set RAX to zero
ret
-boost_fcontext_make ENDP
+make_fcontext ENDP
-boost_fcontext_link PROC FRAME ; generate function table entry in .pdata and unwind information in
+link_fcontext PROC FRAME ; generate function table entry in .pdata and unwind information in
.endprolog ; .xdata for a function's structured exception handling unwind behavior
sub rsp, 028h ; reserve shadow space for boost_fcontext_algin
@@ -161,12 +161,12 @@
mov rdx, r13 ; second argumnet eq. address of next context
mov [rsp+010h], rdx
mov [rsp+08h], rcx
- call boost_fcontext_start ; install next context
+ call start_fcontext ; install next context
finish:
xor rcx, rcx
mov [rsp+08h], rcx
call _exit ; exit application
hlt
-boost_fcontext_link ENDP
+link_fcontext ENDP
END
Modified: trunk/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S (original)
+++ trunk/libs/context/src/asm/fcontext_x86_64_sysv_elf_gas.S 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -46,10 +46,10 @@
* **************************************************************************************/
.text
-.globl boost_fcontext_jump
-.type boost_fcontext_jump,@function
+.globl jump_fcontext
+.type jump_fcontext,@function
.align 16
-boost_fcontext_jump:
+jump_fcontext:
movq %rbx, (%rdi) /* save RBX */
movq %r12, 0x8(%rdi) /* save R12 */
movq %r13, 0x10(%rdi) /* save R13 */
@@ -83,21 +83,21 @@
movq %r13, %rdi /* restore void pointer as argument */
jmp *%rcx /* indirect jump to context */
-.size boost_fcontext_jump,.-boost_fcontext_jump
+.size jump_fcontext,.-jump_fcontext
.text
-.globl boost_fcontext_make
-.type boost_fcontext_make,@function
+.globl make_fcontext
+.type make_fcontext,@function
.align 16
-boost_fcontext_make:
+make_fcontext:
movq %rdi, (%rdi) /* save the address of current context */
movq %rsi, 0x38(%rdi) /* save the address of the function supposed to run */
movq %rdx, 0x10(%rdi) /* save the the void pointer */
movq 0x48(%rdi), %rdx /* load the stack base */
pushq %rdi /* save pointer to fcontext_t */
- movq %rdx, %rdi /* stack pointer as arg for boost_fcontext_align */
- call boost_fcontext_align_at_PLT /* align stack */
+ movq %rdx, %rdi /* stack pointer as arg for align_stack */
+ call align_stack_at_PLT /* align stack */
movq %rax, %rdx /* begin of aligned stack */
popq %rdi /* restore pointer to fcontext_t */
@@ -118,11 +118,11 @@
je 1f /* jump to finish */
movq %rbx, %rdi /* restore current context */
- call boost_fcontext_start_at_PLT /* jump to next context */
+ call start_fcontext_at_PLT /* jump to next context */
1:
xorq %rdi, %rdi /* exit code is zero */
call _exit_at_PLT /* exit application */
hlt
-.size boost_fcontext_make,.-boost_fcontext_make
+.size make_fcontext,.-make_fcontext
Modified: trunk/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S
==============================================================================
--- trunk/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S (original)
+++ trunk/libs/context/src/asm/fcontext_x86_64_sysv_macho_gas.S 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -46,9 +46,9 @@
* **************************************************************************************/
.text
-.globl _boost_fcontext_jump
+.globl _jump_fcontext
.align 8
-_boost_fcontext_jump:
+_jump_fcontext:
movq %rbx, (%rdi) /* save RBX */
movq %r12, 0x8(%rdi) /* save R12 */
movq %r13, 0x10(%rdi) /* save R13 */
@@ -84,17 +84,17 @@
jmp *%rcx /* indirect jump to context */
.text
-.globl _boost_fcontext_make
+.globl _make_fcontext
.align 8
-_boost_fcontext_make:
+_make_fcontext:
movq %rdi, (%rdi) /* save the address of current context */
movq %rsi, 0x38(%rdi) /* save the address of the function supposed to run */
movq %rdx, 0x10(%rdi) /* save the the void pointer */
movq 0x48(%rdi), %rdx /* load the stack base */
pushq %rdi /* save pointer to fcontext_t */
- movq %rdx, %rdi /* stack pointer as arg for boost_fcontext_align */
- call boost_fcontext_align_at_PLT /* align stack */
+ movq %rdx, %rdi /* stack pointer as arg for align_stack */
+ call align_stack_at_PLT /* align stack */
movq %rax, %rdx /* begin of aligned stack */
popq %rdi /* restore pointer to fcontext_t */
@@ -115,7 +115,7 @@
je 1f /* jump to finish */
movq %rbx, %rdi /* restore current context */
- call boost_fcontext_start_at_PLT /* jump to next context */
+ call start_fcontext_at_PLT /* jump to next context */
1:
xorq %rdi, %rdi /* exit code is zero */
Modified: trunk/libs/context/src/fcontext.cpp
==============================================================================
--- trunk/libs/context/src/fcontext.cpp (original)
+++ trunk/libs/context/src/fcontext.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -15,10 +15,9 @@
#endif
namespace boost {
-namespace contexts {
+namespace ctx {
-extern "C" {
-BOOST_CONTEXT_DECL void * BOOST_CONTEXT_CALLDECL boost_fcontext_align( void * vp)
+extern "C" BOOST_CONTEXT_DECL void * BOOST_CONTEXT_CALLDECL align_stack( void * vp)
{
void * base = vp;
if ( 0 != ( ( ( uintptr_t) base) & 15) )
@@ -28,12 +27,10 @@
}
# if !defined(__arm__) && !defined(__powerpc__)
-BOOST_CONTEXT_DECL intptr_t BOOST_CONTEXT_CALLDECL boost_fcontext_start( boost_fcontext_t * ofc, boost_fcontext_t const* nfc)
-{ return boost_fcontext_jump( ofc, nfc, 0); }
+extern "C" BOOST_CONTEXT_DECL intptr_t BOOST_CONTEXT_CALLDECL start_fcontext( fcontext_t * ofc, fcontext_t const* nfc)
+{ return jump_fcontext( ofc, nfc, 0); }
#endif
-}
-
}}
#ifdef BOOST_HAS_ABI_HEADERS
Modified: trunk/libs/context/src/seh.cpp
==============================================================================
--- trunk/libs/context/src/seh.cpp (original)
+++ trunk/libs/context/src/seh.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -10,9 +10,7 @@
#include <stddef.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <excpt.h>
#include <windows.h>
#include <winnt.h>
@@ -28,11 +26,7 @@
{
const char * accessType = ( info[0]) ? "writing" : "reading";
const ULONG_PTR address = info[1];
-#if defined (__MINGW32__) || defined (__MINGW64__)
- snprintf( description, len, "Access violation %s 0x%08X", accessType, address);
-#else
_snprintf_s( description, len, _TRUNCATE, "Access violation %s 0x%08X", accessType, address);
-#endif
return description;
}
case EXCEPTION_DATATYPE_MISALIGNMENT: return "Datatype misalignment";
@@ -58,20 +52,16 @@
case EXCEPTION_INVALID_HANDLE: return "Invalid handle";
}
-#if defined (__MINGW32__) || defined (__MINGW64__)
- snprintf( description, len, "Unknown (0x%08X)", code);
-#else
_snprintf_s( description, len, _TRUNCATE, "Unknown (0x%08X)", code);
-#endif
return description;
}
-EXCEPTION_DISPOSITION boost_fcontext_seh(
+EXCEPTION_DISPOSITION seh_fcontext(
struct _EXCEPTION_RECORD * record,
- void * frame,
- struct _CONTEXT * ctx,
- void * dispatcher)
+ void *,
+ struct _CONTEXT *,
+ void *)
{
char description[255];
Modified: trunk/libs/context/src/stack_allocator_posix.cpp
==============================================================================
--- trunk/libs/context/src/stack_allocator_posix.cpp (original)
+++ trunk/libs/context/src/stack_allocator_posix.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -29,7 +29,7 @@
#endif
namespace boost {
-namespace contexts {
+namespace ctx {
void *
stack_allocator::allocate( std::size_t size) const
Modified: trunk/libs/context/src/stack_allocator_windows.cpp
==============================================================================
--- trunk/libs/context/src/stack_allocator_windows.cpp (original)
+++ trunk/libs/context/src/stack_allocator_windows.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -30,7 +30,7 @@
# endif
namespace boost {
-namespace contexts {
+namespace ctx {
void *
stack_allocator::allocate( std::size_t size) const
Modified: trunk/libs/context/src/stack_utils_posix.cpp
==============================================================================
--- trunk/libs/context/src/stack_utils_posix.cpp (original)
+++ trunk/libs/context/src/stack_utils_posix.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -38,7 +38,7 @@
}
namespace boost {
-namespace contexts {
+namespace ctx {
BOOST_CONTEXT_DECL
std::size_t default_stacksize()
Modified: trunk/libs/context/src/stack_utils_windows.cpp
==============================================================================
--- trunk/libs/context/src/stack_utils_windows.cpp (original)
+++ trunk/libs/context/src/stack_utils_windows.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -35,7 +35,7 @@
}
namespace boost {
-namespace contexts {
+namespace ctx {
BOOST_CONTEXT_DECL
std::size_t default_stacksize()
Modified: trunk/libs/context/test/test_context.cpp
==============================================================================
--- trunk/libs/context/test/test_context.cpp (original)
+++ trunk/libs/context/test/test_context.cpp 2012-04-12 14:42:36 EDT (Thu, 12 Apr 2012)
@@ -15,186 +15,179 @@
#include <boost/context/all.hpp>
+namespace ctx = boost::ctx;
+
+ctx::fcontext_t fcm, fc1, fc2;
int value1 = 0;
-std::string value2, value3;
+std::string value2;
+double value3 = 0.;
-class X : private boost::noncopyable
+void f1( intptr_t)
{
-private:
- std::string str_;
+ ++value1;
+ ctx::jump_fcontext( & fc1, & fcm, 0);
+}
-public:
- X( std::string const& str) :
- str_( str)
- {}
+void f2( intptr_t)
+{
+ ++value1;
+}
- ~X()
- { value3 = str_; }
-};
+void f3( intptr_t)
+{
+ ++value1;
+ ctx::jump_fcontext( & fc1, & fcm, 0);
+ ++value1;
+ ctx::jump_fcontext( & fc1, & fcm, 0);
+}
-boost::contexts::context gctx;
+void f4( intptr_t)
+{
+ ctx::jump_fcontext( & fc1, & fcm, 7);
+}
-void fn0()
-{}
+void f5( intptr_t arg)
+{
+ ctx::jump_fcontext( & fc1, & fcm, arg);
+}
-void fn1( int i)
-{ value1 = i; }
+void f6( intptr_t arg)
+{
+ ctx::jump_fcontext(
+ & fc1, & fcm,
+ ctx::jump_fcontext( & fc1, & fcm, arg) );
+}
-void fn2( std::string const& str)
+void f7( intptr_t arg)
{
try
- { throw std::runtime_error( str); }
+ { throw std::runtime_error( ( char *) arg); }
catch ( std::runtime_error const& e)
{ value2 = e.what(); }
}
-void fn3( std::string const& str)
+void f8( intptr_t arg)
{
- X x( str);
- intptr_t vp = gctx.suspend( value1);
- value1 = vp;
- BOOST_ASSERT( gctx.is_running() );
- gctx.suspend();
+ double d = * ( double *) arg;
+ d += 3.45;
+ value3 = d;
}
-void fn4( std::string const& str1, std::string const& str2)
+void test_start()
{
- value2 = str1;
- value3 = str2;
+ value1 = 0;
+
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc1, f1, 0);
+
+ BOOST_CHECK_EQUAL( 0, value1);
+ ctx::start_fcontext( & fcm, & fc1);
+ BOOST_CHECK_EQUAL( 1, value1);
}
-void fn5( double d)
+void test_link()
{
- d += 3.45;
- std::cout << "d == " << d << std::endl;
+ value1 = 0;
+
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ fc1.fc_link = & fcm;
+ ctx::make_fcontext( & fc1, f2, 0);
+
+ BOOST_CHECK_EQUAL( 0, value1);
+ ctx::start_fcontext( & fcm, & fc1);
+ BOOST_CHECK_EQUAL( 1, value1);
}
-void test_case_1()
+void test_jump()
{
- boost::contexts::context ctx1;
- boost::contexts::context ctx2(
- fn0,
- boost::contexts::default_stacksize(),
- boost::contexts::stack_unwind, boost::contexts::return_to_caller);
- BOOST_CHECK( ! ctx1);
- BOOST_CHECK( ctx2);
- ctx1 = boost::move( ctx2);
- BOOST_CHECK( ctx1);
- BOOST_CHECK( ! ctx2);
+ value1 = 0;
+
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc1, f3, 0);
+
+ BOOST_CHECK_EQUAL( 0, value1);
+ ctx::start_fcontext( & fcm, & fc1);
+ BOOST_CHECK_EQUAL( 1, value1);
+ ctx::jump_fcontext( & fcm, & fc1, 0);
+ BOOST_CHECK_EQUAL( 2, value1);
}
-void test_case_2()
+void test_result()
{
- boost::contexts::context ctx(
- fn0,
- boost::contexts::default_stacksize(),
- boost::contexts::stack_unwind, boost::contexts::return_to_caller);
- BOOST_CHECK( ! ctx.is_started() );
- BOOST_CHECK( ! ctx.is_complete() );
- ctx.start();
- BOOST_CHECK( ctx.is_complete() );
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ ctx::make_fcontext( & fc1, f4, 0);
+
+ int result = ( int) ctx::start_fcontext( & fcm, & fc1);
+ BOOST_CHECK_EQUAL( 7, result);
}
-void test_case_3()
+void test_arg()
{
- int i = 1;
- BOOST_CHECK_EQUAL( 0, value1);
- boost::contexts::context ctx(
- fn1, i,
- boost::contexts::default_stacksize(),
- boost::contexts::stack_unwind, boost::contexts::return_to_caller);
- BOOST_CHECK( ! ctx.is_started() );
- BOOST_CHECK( ! ctx.is_complete() );
- ctx.start();
- BOOST_CHECK( ctx.is_complete() );
- BOOST_CHECK_EQUAL( 1, value1);
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ int i = 7;
+ ctx::make_fcontext( & fc1, f5, i);
+
+ int result = ( int) ctx::start_fcontext( & fcm, & fc1);
+ BOOST_CHECK_EQUAL( i, result);
}
-void test_case_4()
+void test_transfer()
{
- BOOST_CHECK_EQUAL( std::string(""), value2);
- boost::contexts::context ctx(
- fn2, "abc",
- boost::contexts::default_stacksize(),
- boost::contexts::stack_unwind, boost::contexts::return_to_caller);
- BOOST_CHECK( ! ctx.is_started() );
- BOOST_CHECK( ! ctx.is_complete() );
- ctx.start();
- BOOST_CHECK( ctx.is_complete() );
- BOOST_CHECK_EQUAL( std::string("abc"), value2);
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ int i = 3;
+ ctx::make_fcontext( & fc1, f6, i);
+
+ int result = ( int) ctx::start_fcontext( & fcm, & fc1);
+ BOOST_CHECK_EQUAL( i, result);
+ i = 7;
+ result = ( int) ctx::jump_fcontext( & fcm, & fc1, i);
+ BOOST_CHECK_EQUAL( i, result);
}
-void test_case_5()
+void test_exception()
{
- value1 = 1;
- BOOST_CHECK_EQUAL( 1, value1);
- BOOST_CHECK_EQUAL( std::string(""), value3);
- gctx = boost::contexts::context(
- fn3, "abc",
- boost::contexts::default_stacksize(),
- boost::contexts::stack_unwind, boost::contexts::return_to_caller);
- BOOST_CHECK( ! gctx.is_started() );
- BOOST_CHECK( ! gctx.is_complete() );
- intptr_t vp = gctx.start();
- BOOST_CHECK( gctx.is_started() );
- BOOST_CHECK( ! gctx.is_resumed() );
- BOOST_CHECK( ! gctx.is_complete() );
- BOOST_CHECK_EQUAL( vp, value1);
- BOOST_CHECK_EQUAL( 1, value1);
- int x = 7;
- vp = 0;
- vp = gctx.resume( x);
- BOOST_CHECK_EQUAL( 7, value1);
- BOOST_CHECK( ! vp);
- BOOST_CHECK( ! gctx.is_complete() );
- BOOST_CHECK( gctx.is_resumed() );
- BOOST_CHECK_EQUAL( std::string(""), value3);
- gctx.unwind_stack();
- BOOST_CHECK( gctx.is_complete() );
- BOOST_CHECK_EQUAL( std::string("abc"), value3);
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ char * what = "hello world";
+ fc1.fc_link = & fcm;
+ ctx::make_fcontext( & fc1, f7, ( intptr_t) what);
+
+ ctx::start_fcontext( & fcm, & fc1);
+ BOOST_CHECK_EQUAL( std::string( what), value2);
}
-void test_case_6()
+void test_fp()
{
- value1 = 0;
- value2 = "";
- value3 = "";
- BOOST_CHECK_EQUAL( 0, value1);
- BOOST_CHECK_EQUAL( std::string(""), value2);
- BOOST_CHECK_EQUAL( std::string(""), value3);
+ ctx::stack_allocator alloc;
+
+ fc1.fc_stack.base = alloc.allocate( ctx::minimum_stacksize() );
+ fc1.fc_stack.limit = static_cast< char * >( fc1.fc_stack.base) - ctx::minimum_stacksize();
+ fc1.fc_link = & fcm;
+ double d = 7.13;
+ ctx::make_fcontext( & fc1, f8, ( intptr_t) & d);
- boost::contexts::context ctx1(
- fn4, "abc", "xyz",
- boost::contexts::default_stacksize(),
- boost::contexts::stack_unwind,
- boost::contexts::return_to_caller);
- boost::contexts::context ctx2(
- fn1, 7,
- boost::contexts::default_stacksize(),
- boost::contexts::stack_unwind,
- ctx1);
-
- BOOST_CHECK( ! ctx1.is_complete() );
- BOOST_CHECK( ! ctx2.is_complete() );
- ctx2.start();
- BOOST_CHECK( ctx1.is_complete() );
- BOOST_CHECK( ctx2.is_complete() );
-
- BOOST_CHECK_EQUAL( 7, value1);
- BOOST_CHECK_EQUAL( "abc", value2);
- BOOST_CHECK_EQUAL( "xyz", value3);
-}
-
-void test_case_7()
-{
- boost::contexts::context ctx(
- fn5, 7.34,
- boost::contexts::default_stacksize(),
- boost::contexts::stack_unwind,
- boost::contexts::return_to_caller);
- BOOST_CHECK( ! ctx.is_complete() );
- ctx.start();
- BOOST_CHECK( ctx.is_complete() );
+ ctx::start_fcontext( & fcm, & fc1);
+ BOOST_CHECK_EQUAL( 10.58, value3);
}
boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
@@ -202,13 +195,14 @@
boost::unit_test::test_suite * test =
BOOST_TEST_SUITE("Boost.Context: context test suite");
- test->add( BOOST_TEST_CASE( & test_case_1) );
- test->add( BOOST_TEST_CASE( & test_case_2) );
- test->add( BOOST_TEST_CASE( & test_case_3) );
- test->add( BOOST_TEST_CASE( & test_case_4) );
- test->add( BOOST_TEST_CASE( & test_case_5) );
- test->add( BOOST_TEST_CASE( & test_case_6) );
- test->add( BOOST_TEST_CASE( & test_case_7) );
+ test->add( BOOST_TEST_CASE( & test_start) );
+ test->add( BOOST_TEST_CASE( & test_link) );
+ test->add( BOOST_TEST_CASE( & test_jump) );
+ test->add( BOOST_TEST_CASE( & test_result) );
+ test->add( BOOST_TEST_CASE( & test_arg) );
+ test->add( BOOST_TEST_CASE( & test_transfer) );
+ test->add( BOOST_TEST_CASE( & test_exception) );
+ test->add( BOOST_TEST_CASE( & test_fp) );
return test;
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk