|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r85163 - in branches/release: boost/coroutine boost/coroutine/detail boost/coroutine/v1 boost/coroutine/v1/detail boost/coroutine/v2 boost/coroutine/v2/detail libs/coroutine libs/coroutine/build libs/coroutine/doc libs/coroutine/doc/images libs/coroutine/example libs/coroutine/example/asio libs/coroutine/example/cpp03 libs/coroutine/example/cpp11 libs/coroutine/performance libs/coroutine/src libs/coroutine/src/detail libs/coroutine/test
From: oliver.kowalke_at_[hidden]
Date: 2013-07-26 11:44:40
Author: olli
Date: 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013)
New Revision: 85163
URL: http://svn.boost.org/trac/boost/changeset/85163
Log:
coroutine: merge from trunk
Added:
branches/release/boost/coroutine/detail/stack_tuple.hpp
- copied unchanged from r85162, trunk/boost/coroutine/detail/stack_tuple.hpp
branches/release/boost/coroutine/detail/trampoline.hpp
- copied unchanged from r85162, trunk/boost/coroutine/detail/trampoline.hpp
branches/release/boost/coroutine/exceptions.hpp
- copied unchanged from r85162, trunk/boost/coroutine/exceptions.hpp
branches/release/boost/coroutine/v2/coroutine.hpp
- copied unchanged from r85162, trunk/boost/coroutine/v2/coroutine.hpp
branches/release/boost/coroutine/v2/detail/pull_coroutine_base.hpp
- copied unchanged from r85162, trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp
branches/release/boost/coroutine/v2/detail/pull_coroutine_caller.hpp
- copied unchanged from r85162, trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp
branches/release/boost/coroutine/v2/detail/pull_coroutine_object.hpp
- copied unchanged from r85162, trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp
branches/release/boost/coroutine/v2/detail/push_coroutine_base.hpp
- copied unchanged from r85162, trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp
branches/release/boost/coroutine/v2/detail/push_coroutine_caller.hpp
- copied unchanged from r85162, trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp
branches/release/boost/coroutine/v2/detail/push_coroutine_object.hpp
- copied unchanged from r85162, trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp
branches/release/libs/coroutine/doc/images/fringe.png
- copied unchanged from r85162, trunk/libs/coroutine/doc/images/fringe.png
branches/release/libs/coroutine/doc/motivation.qbk
- copied unchanged from r85162, trunk/libs/coroutine/doc/motivation.qbk
branches/release/libs/coroutine/doc/old.qbk
- copied unchanged from r85162, trunk/libs/coroutine/doc/old.qbk
branches/release/libs/coroutine/doc/unidirect.qbk
- copied unchanged from r85162, trunk/libs/coroutine/doc/unidirect.qbk
branches/release/libs/coroutine/example/cpp03/
- copied from r85162, trunk/libs/coroutine/example/cpp03/
branches/release/libs/coroutine/example/cpp11/
- copied from r85162, trunk/libs/coroutine/example/cpp11/
branches/release/libs/coroutine/src/exceptions.cpp
- copied unchanged from r85162, trunk/libs/coroutine/src/exceptions.cpp
Replaced:
branches/release/libs/coroutine/example/cpp03/Jamfile.v2
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/Jamfile.v2
branches/release/libs/coroutine/example/cpp03/chaining.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/chaining.cpp
branches/release/libs/coroutine/example/cpp03/echo.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/echo.cpp
branches/release/libs/coroutine/example/cpp03/echosse.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/echosse.cpp
branches/release/libs/coroutine/example/cpp03/fibonacci.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/fibonacci.cpp
branches/release/libs/coroutine/example/cpp03/layout.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/layout.cpp
branches/release/libs/coroutine/example/cpp03/parallel.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/parallel.cpp
branches/release/libs/coroutine/example/cpp03/power.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/power.cpp
branches/release/libs/coroutine/example/cpp03/same_fringe.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/same_fringe.cpp
branches/release/libs/coroutine/example/cpp03/segmented_stack.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/segmented_stack.cpp
branches/release/libs/coroutine/example/cpp03/tree.h
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/tree.h
branches/release/libs/coroutine/example/cpp03/unwind.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp03/unwind.cpp
branches/release/libs/coroutine/example/cpp11/Jamfile.v2
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp11/Jamfile.v2
branches/release/libs/coroutine/example/cpp11/await_emu.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp11/await_emu.cpp
branches/release/libs/coroutine/example/cpp11/fibonacci.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp11/fibonacci.cpp
branches/release/libs/coroutine/example/cpp11/layout.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp11/layout.cpp
branches/release/libs/coroutine/example/cpp11/same_fringe.cpp
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp11/same_fringe.cpp
branches/release/libs/coroutine/example/cpp11/tree.h
- copied unchanged from r85162, trunk/libs/coroutine/example/cpp11/tree.h
Deleted:
branches/release/boost/coroutine/v2/detail/coroutine_object.hpp
branches/release/boost/coroutine/v2/pull_corotuine.hpp
branches/release/boost/coroutine/v2/push_coroutine.hpp
branches/release/libs/coroutine/example/Jamfile.v2
branches/release/libs/coroutine/example/asio/
branches/release/libs/coroutine/example/echo.cpp
branches/release/libs/coroutine/example/fibonacci.cpp
branches/release/libs/coroutine/example/parallel.cpp
branches/release/libs/coroutine/example/power.cpp
branches/release/libs/coroutine/example/same_fringe.cpp
branches/release/libs/coroutine/example/segmented_stack.cpp
branches/release/libs/coroutine/example/tree.h
branches/release/libs/coroutine/example/unwind.cpp
Properties modified:
branches/release/boost/coroutine/ (props changed)
branches/release/libs/coroutine/ (props changed)
branches/release/libs/coroutine/doc/ (props changed)
Text files modified:
branches/release/boost/coroutine/all.hpp | 1
branches/release/boost/coroutine/coroutine.hpp | 2
branches/release/boost/coroutine/detail/config.hpp | 36
branches/release/boost/coroutine/detail/exceptions.hpp | 6
branches/release/boost/coroutine/detail/stack_tuple.hpp | 47
branches/release/boost/coroutine/detail/trampoline.hpp | 52
branches/release/boost/coroutine/exceptions.hpp | 105 +
branches/release/boost/coroutine/v1/coroutine.hpp | 6
branches/release/boost/coroutine/v1/detail/arg.hpp | 6
branches/release/boost/coroutine/v1/detail/coroutine_base.hpp | 6
branches/release/boost/coroutine/v1/detail/coroutine_base_resume.hpp | 8
branches/release/boost/coroutine/v1/detail/coroutine_caller.hpp | 6
branches/release/boost/coroutine/v1/detail/coroutine_get.hpp | 6
branches/release/boost/coroutine/v1/detail/coroutine_object.hpp | 51
branches/release/boost/coroutine/v1/detail/coroutine_op.hpp | 6
branches/release/boost/coroutine/v2/coroutine.hpp | 3000 ++++++++++++++++++++++++++++++++++++++++
/dev/null | 423 -----
branches/release/boost/coroutine/v2/detail/pull_coroutine_base.hpp | 337 ++++
branches/release/boost/coroutine/v2/detail/pull_coroutine_caller.hpp | 111 +
branches/release/boost/coroutine/v2/detail/pull_coroutine_object.hpp | 1124 ++++++++++++++
branches/release/boost/coroutine/v2/detail/push_coroutine_base.hpp | 354 ++++
branches/release/boost/coroutine/v2/detail/push_coroutine_caller.hpp | 56
branches/release/boost/coroutine/v2/detail/push_coroutine_object.hpp | 1208 ++++++++++++++++
/dev/null | 355 ----
/dev/null | 357 ----
branches/release/libs/coroutine/build/Jamfile.v2 | 13
branches/release/libs/coroutine/doc/coro.qbk | 9
branches/release/libs/coroutine/doc/coroutine.qbk | 798 ----------
branches/release/libs/coroutine/doc/intro.qbk | 352 ---
branches/release/libs/coroutine/doc/motivation.qbk | 177 ++
branches/release/libs/coroutine/doc/old.qbk | 809 ++++++++++
branches/release/libs/coroutine/doc/unidirect.qbk | 784 ++++++++++
/dev/null | 86 -
branches/release/libs/coroutine/example/cpp03/Jamfile.v2 | 78 +
branches/release/libs/coroutine/example/cpp03/chaining.cpp | 203 ++
branches/release/libs/coroutine/example/cpp03/echo.cpp | 84 +
branches/release/libs/coroutine/example/cpp03/echosse.cpp | 60
branches/release/libs/coroutine/example/cpp03/fibonacci.cpp | 75 +
branches/release/libs/coroutine/example/cpp03/layout.cpp | 71
branches/release/libs/coroutine/example/cpp03/parallel.cpp | 91 +
branches/release/libs/coroutine/example/cpp03/power.cpp | 86 +
branches/release/libs/coroutine/example/cpp03/same_fringe.cpp | 161 ++
branches/release/libs/coroutine/example/cpp03/segmented_stack.cpp | 81 +
branches/release/libs/coroutine/example/cpp03/tree.h | 155 ++
branches/release/libs/coroutine/example/cpp03/unwind.cpp | 81 +
branches/release/libs/coroutine/example/cpp11/Jamfile.v2 | 58
branches/release/libs/coroutine/example/cpp11/await_emu.cpp | 197 ++
branches/release/libs/coroutine/example/cpp11/fibonacci.cpp | 60
branches/release/libs/coroutine/example/cpp11/layout.cpp | 50
branches/release/libs/coroutine/example/cpp11/same_fringe.cpp | 176 ++
branches/release/libs/coroutine/example/cpp11/tree.h | 97 +
/dev/null | 46
/dev/null | 72
/dev/null | 51
/dev/null | 92 -
/dev/null | 81 -
/dev/null | 64
/dev/null | 127 -
/dev/null | 46
branches/release/libs/coroutine/performance/Jamfile.v2 | 2
branches/release/libs/coroutine/performance/performance.cpp | 83
branches/release/libs/coroutine/src/detail/coroutine_context.cpp | 2
branches/release/libs/coroutine/src/detail/segmented_stack_allocator.cpp | 2
branches/release/libs/coroutine/src/detail/standard_stack_allocator_posix.cpp | 2
branches/release/libs/coroutine/src/detail/standard_stack_allocator_windows.cpp | 2
branches/release/libs/coroutine/src/exceptions.cpp | 36
branches/release/libs/coroutine/test/Jamfile.v2 | 1
branches/release/libs/coroutine/test/test_coroutine.cpp | 544 +++++++
68 files changed, 10814 insertions(+), 3000 deletions(-)
Modified: branches/release/boost/coroutine/all.hpp
==============================================================================
--- branches/release/boost/coroutine/all.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/all.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -9,6 +9,7 @@
#include <boost/coroutine/attributes.hpp>
#include <boost/coroutine/coroutine.hpp>
+#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/flags.hpp>
#include <boost/coroutine/stack_allocator.hpp>
Modified: branches/release/boost/coroutine/coroutine.hpp
==============================================================================
--- branches/release/boost/coroutine/coroutine.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/coroutine.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -7,7 +7,7 @@
#ifndef BOOST_COROUTINES_COROUTINE_H
#define BOOST_COROUTINES_COROUTINE_H
-#ifdef BOOST_COROUTINES_V2
+#ifdef BOOST_COROUTINES_UNIDIRECT
#include <boost/coroutine/v2/coroutine.hpp>
#else
#include <boost/coroutine/v1/coroutine.hpp>
Modified: branches/release/boost/coroutine/detail/config.hpp
==============================================================================
--- branches/release/boost/coroutine/detail/config.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/detail/config.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -14,16 +14,12 @@
# undef BOOST_COROUTINES_DECL
#endif
-#if defined(BOOST_HAS_DECLSPEC)
-# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES_DYN_LINK)
-# if ! defined(BOOST_DYN_LINK)
-# define BOOST_DYN_LINK
-# endif
-# if defined(BOOST_COROUTINES_SOURCE)
-# define BOOST_COROUTINES_DECL BOOST_SYMBOL_EXPORT
-# else
-# define BOOST_COROUTINES_DECL BOOST_SYMBOL_IMPORT
-# endif
+#if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES_DYN_LINK) ) && ! defined(BOOST_COROUTINES_STATIC_LINK)
+# if defined(BOOST_COROUTINES_SOURCE)
+# define BOOST_COROUTINES_DECL BOOST_SYMBOL_EXPORT
+# define BOOST_COROUTINES_BUILD_DLL
+# else
+# define BOOST_COROUTINES_DECL BOOST_SYMBOL_IMPORT
# endif
#endif
@@ -32,7 +28,7 @@
#endif
#if ! defined(BOOST_COROUTINES_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_COROUTINES_NO_LIB)
-# define BOOST_LIB_NAME boost_context
+# define BOOST_LIB_NAME boost_coroutine
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_COROUTINES_DYN_LINK)
# define BOOST_DYN_LINK
# endif
@@ -46,8 +42,20 @@
# define BOOST_COROUTINES_SEGMENTS 10
#endif
-//#ifndef BOOST_COROUTINES_V1
-//# define BOOST_COROUTINES_V2
-//#endif
+#if defined(BOOST_COROUTINES_V2)
+# define BOOST_COROUTINES_UNIDIRECT
+#endif
+
+#if defined(BOOST_COROUTINES_V1)
+# define BOOST_COROUTINES_OLD
+#endif
+
+#if defined(BOOST_COROUTINES_BIDIRECT)
+# define BOOST_COROUTINES_OLD
+#endif
+
+#if ! defined(BOOST_COROUTINES_OLD)
+# define BOOST_COROUTINES_UNIDIRECT
+#endif
#endif // BOOST_COROUTINES_DETAIL_CONFIG_H
Modified: branches/release/boost/coroutine/detail/exceptions.hpp
==============================================================================
--- branches/release/boost/coroutine/detail/exceptions.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/detail/exceptions.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_COROUTINES_DETAIL_EXCEPTIONs_H
-#define BOOST_COROUTINES_DETAIL_EXCEPTIONs_H
+#ifndef BOOST_COROUTINES_DETAIL_EXCEPTIONS_H
+#define BOOST_COROUTINES_DETAIL_EXCEPTIONS_H
#include <boost/config.hpp>
@@ -25,4 +25,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_COROUTINES_DETAIL_EXCEPTIONs_H
+#endif // BOOST_COROUTINES_DETAIL_EXCEPTIONS_H
Copied: branches/release/boost/coroutine/detail/stack_tuple.hpp (from r85162, trunk/boost/coroutine/detail/stack_tuple.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/detail/stack_tuple.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/detail/stack_tuple.hpp)
@@ -0,0 +1,47 @@
+
+// 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_COROUTINES_DETAIL_STACK_TUPLE_H
+#define BOOST_COROUTINES_DETAIL_STACK_TUPLE_H
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/stack_context.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename StackAllocator >
+struct stack_tuple
+{
+ coroutines::stack_context stack_ctx;
+ StackAllocator stack_alloc;
+
+ stack_tuple( StackAllocator const& stack_alloc_, std::size_t size) :
+ stack_ctx(),
+ stack_alloc( stack_alloc_)
+ { stack_alloc.allocate( stack_ctx, size); }
+
+ ~stack_tuple()
+ { stack_alloc.deallocate( stack_ctx); }
+};
+
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_STACK_TUPLE_H
Copied: branches/release/boost/coroutine/detail/trampoline.hpp (from r85162, trunk/boost/coroutine/detail/trampoline.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/detail/trampoline.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/detail/trampoline.hpp)
@@ -0,0 +1,52 @@
+
+// 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_COROUTINES_DETAIL_TRAMPOLINE_H
+#define BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
+
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/tuple/tuple.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename Coroutine >
+void trampoline1( intptr_t vp)
+{
+ BOOST_ASSERT( vp);
+
+ reinterpret_cast< Coroutine * >( vp)->run();
+}
+
+template< typename Coroutine, typename Arg >
+void trampoline2( intptr_t vp)
+{
+ BOOST_ASSERT( vp);
+
+ tuple< Coroutine *, Arg > * tpl(
+ reinterpret_cast< tuple< Coroutine *, Arg > * >( vp) );
+ Coroutine * coro( get< 0 >( * tpl) );
+ Arg arg( get< 1 >( * tpl) );
+
+ coro->run( arg);
+}
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_TRAMPOLINE_H
Copied: branches/release/boost/coroutine/exceptions.hpp (from r85162, trunk/boost/coroutine/exceptions.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/exceptions.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/exceptions.hpp)
@@ -0,0 +1,105 @@
+
+// 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_COROUTINES_EXCEPTIONS_H
+#define BOOST_COROUTINES_EXCEPTIONS_H
+
+#include <stdexcept>
+#include <string>
+
+#include <boost/config.hpp>
+#include <boost/detail/scoped_enum_emulation.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+struct forced_unwind {};
+
+}
+
+BOOST_SCOPED_ENUM_DECLARE_BEGIN(coroutine_errc)
+{
+ no_data = 1
+}
+BOOST_SCOPED_ENUM_DECLARE_END(coroutine_errc)
+
+BOOST_COROUTINES_DECL system::error_category const& coroutine_category() BOOST_NOEXCEPT;
+
+}
+
+namespace system {
+
+template<>
+struct is_error_code_enum< coroutines::coroutine_errc > : public true_type
+{};
+
+#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
+template<>
+struct is_error_code_enum< coroutines::coroutine_errc::enum_type > : public true_type
+{};
+#endif
+
+inline
+error_code make_error_code( coroutines::coroutine_errc e) //BOOST_NOEXCEPT
+{
+ return error_code( underlying_cast< int >( e), coroutines::coroutine_category() );
+}
+
+inline
+error_condition make_error_condition( coroutines::coroutine_errc e) //BOOST_NOEXCEPT
+{
+ return error_condition( underlying_cast< int >( e), coroutines::coroutine_category() );
+}
+
+}
+
+namespace coroutines {
+
+class coroutine_error : public std::logic_error
+{
+private:
+ system::error_code ec_;
+
+public:
+ coroutine_error( system::error_code ec) :
+ logic_error( ec.message() ),
+ ec_( ec)
+ {}
+
+ system::error_code const& code() const BOOST_NOEXCEPT
+ { return ec_; }
+
+ const char* what() const throw()
+ { return code().message().c_str(); }
+};
+
+class invalid_result : public coroutine_error
+{
+public:
+ invalid_result() :
+ coroutine_error(
+ system::make_error_code(
+ coroutine_errc::no_data) )
+ {}
+};
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_EXCEPTIONS_H
Modified: branches/release/boost/coroutine/v1/coroutine.hpp
==============================================================================
--- branches/release/boost/coroutine/v1/coroutine.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/v1/coroutine.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_COROUTINES_V1_COROUTINE_H
-#define BOOST_COROUTINES_V1_COROUTINE_H
+#ifndef BOOST_COROUTINES_OLD_COROUTINE_H
+#define BOOST_COROUTINES_OLD_COROUTINE_H
#include <cstddef>
#include <memory>
@@ -1427,4 +1427,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_COROUTINES_V1_COROUTINE_H
+#endif // BOOST_COROUTINES_OLD_COROUTINE_H
Modified: branches/release/boost/coroutine/v1/detail/arg.hpp
==============================================================================
--- branches/release/boost/coroutine/v1/detail/arg.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/v1/detail/arg.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_COROUTINES_V1_DETAIL_ARG_H
-#define BOOST_COROUTINES_V1_DETAIL_ARG_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_ARG_H
+#define BOOST_COROUTINES_OLD_DETAIL_ARG_H
#include <boost/config.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
@@ -59,4 +59,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_COROUTINES_V1_DETAIL_ARG_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_ARG_H
Modified: branches/release/boost/coroutine/v1/detail/coroutine_base.hpp
==============================================================================
--- branches/release/boost/coroutine/v1/detail/coroutine_base.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/v1/detail/coroutine_base.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
@@ -122,4 +122,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_H
Modified: branches/release/boost/coroutine/v1/detail/coroutine_base_resume.hpp
==============================================================================
--- branches/release/boost/coroutine/v1/detail/coroutine_base_resume.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/v1/detail/coroutine_base_resume.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_RESUME_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_BASE_RESUME_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_RESUME_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_BASE_RESUME_H
#include <iterator>
@@ -22,7 +22,7 @@
#include <boost/coroutine/detail/config.hpp>
#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/detail/exceptions.hpp>
+#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/detail/holder.hpp>
#include <boost/coroutine/v1/detail/arg.hpp>
@@ -234,4 +234,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_COROUTINES_V1_DETAIL_coroutine_base_resume_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_coroutine_base_resume_H
Modified: branches/release/boost/coroutine/v1/detail/coroutine_caller.hpp
==============================================================================
--- branches/release/boost/coroutine/v1/detail/coroutine_caller.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/v1/detail/coroutine_caller.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_CALLER_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_CALLER_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_CALLER_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_CALLER_H
#include <boost/config.hpp>
#include <boost/context/fcontext.hpp>
@@ -54,4 +54,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_CALLER_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_CALLER_H
Modified: branches/release/boost/coroutine/v1/detail/coroutine_get.hpp
==============================================================================
--- branches/release/boost/coroutine/v1/detail/coroutine_get.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/v1/detail/coroutine_get.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_GET_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_GET_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_GET_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_GET_H
#include <boost/assert.hpp>
#include <boost/config.hpp>
@@ -51,4 +51,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_GET_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_GET_H
Modified: branches/release/boost/coroutine/v1/detail/coroutine_object.hpp
==============================================================================
--- branches/release/boost/coroutine/v1/detail/coroutine_object.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/v1/detail/coroutine_object.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OBJECT_H
#include <cstddef>
@@ -21,12 +21,15 @@
#include <boost/coroutine/attributes.hpp>
#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/exceptions.hpp>
+#include <boost/coroutine/exceptions.hpp>
#include <boost/coroutine/detail/flags.hpp>
#include <boost/coroutine/detail/holder.hpp>
#include <boost/coroutine/detail/param.hpp>
+#include <boost/coroutine/detail/stack_tuple.hpp>
+#include <boost/coroutine/detail/trampoline.hpp>
#include <boost/coroutine/flags.hpp>
#include <boost/coroutine/stack_context.hpp>
+#include <boost/coroutine/stack_context.hpp>
#include <boost/coroutine/v1/detail/arg.hpp>
#include <boost/coroutine/v1/detail/coroutine_base.hpp>
@@ -43,46 +46,6 @@
namespace coroutines {
namespace detail {
-template< typename Coroutine >
-void trampoline1( intptr_t vp)
-{
- BOOST_ASSERT( vp);
-
- reinterpret_cast< Coroutine * >( vp)->run();
-}
-
-template< typename Coroutine, typename Arg >
-void trampoline2( intptr_t vp)
-{
- BOOST_ASSERT( vp);
-
- tuple< Coroutine *, Arg > * tpl(
- reinterpret_cast< tuple< Coroutine *, Arg > * >( vp) );
- Coroutine * coro( get< 0 >( * tpl) );
- Arg arg( get< 1 >( * tpl) );
-
- coro->run( arg);
-}
-
-template< typename StackAllocator >
-struct stack_tuple
-{
- coroutines::stack_context stack_ctx;
- StackAllocator stack_alloc;
-
- stack_tuple( StackAllocator const& stack_alloc_, std::size_t size) :
- stack_ctx(),
- stack_alloc( stack_alloc_)
- {
- stack_alloc.allocate( stack_ctx, size);
- }
-
- ~stack_tuple()
- {
- stack_alloc.deallocate( stack_ctx);
- }
-};
-
template<
typename Signature,
typename Fn, typename StackAllocator, typename Allocator,
@@ -108,4 +71,4 @@
#pragma warning (pop)
#endif
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OBJECT_H
Modified: branches/release/boost/coroutine/v1/detail/coroutine_op.hpp
==============================================================================
--- branches/release/boost/coroutine/v1/detail/coroutine_op.hpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/boost/coroutine/v1/detail/coroutine_op.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H
+#ifndef BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OP_H
+#define BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OP_H
#include <iterator>
@@ -323,4 +323,4 @@
# include BOOST_ABI_SUFFIX
#endif
-#endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H
+#endif // BOOST_COROUTINES_OLD_DETAIL_COROUTINE_OP_H
Copied: branches/release/boost/coroutine/v2/coroutine.hpp (from r85162, trunk/boost/coroutine/v2/coroutine.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/v2/coroutine.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/v2/coroutine.hpp)
@@ -0,0 +1,3000 @@
+
+// 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_COROUTINES_UNIDIRECT_COROUTINE_H
+#define BOOST_COROUTINES_UNIDIRECT_COROUTINE_H
+
+#include <cstddef>
+#include <iterator>
+#include <memory>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/move/move.hpp>
+#include <boost/optional.hpp>
+#include <boost/range.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/type_traits/decay.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/coroutine/attributes.hpp>
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/param.hpp>
+#include <boost/coroutine/exceptions.hpp>
+#include <boost/coroutine/stack_allocator.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_base.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_caller.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_object.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_base.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_caller.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_object.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+
+template< typename Arg >
+class pull_coroutine;
+
+template< typename Arg >
+class push_coroutine
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::pull_coroutine_object;
+
+ typedef detail::push_coroutine_base< Arg > base_t;
+ typedef typename base_t::ptr_t ptr_t;
+
+ struct dummy
+ { void nonnull() {} };
+
+ typedef void ( dummy::*safe_bool)();
+
+ ptr_t impl_;
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
+
+ template< typename Allocator >
+ push_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::push_coroutine_caller<
+ Arg, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ push_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifdef BOOST_MSVC
+ typedef void ( * coroutine_fn) ( pull_coroutine< Arg > &);
+
+ explicit push_coroutine( coroutine_fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename StackAllocator >
+ explicit push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename StackAllocator, typename Allocator >
+ explicit push_coroutine(coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#else
+ template< typename Fn >
+ explicit push_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+
+ push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
+ {
+ push_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( push_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ push_coroutine & operator()( Arg const& arg)
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push( arg);
+ return * this;
+ }
+
+ push_coroutine & operator()( Arg && arg) {
+ BOOST_ASSERT( * this);
+
+ impl_->push( arg);
+ return * this;
+ }
+#else
+ push_coroutine & operator()( Arg const& arg)
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push( forward< Arg >( arg) );
+ return * this;
+ }
+
+ push_coroutine & operator()( BOOST_RV_REF( Arg) arg)
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push( forward< Arg >( arg) );
+ return * this;
+ }
+#endif
+
+ class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void >
+ {
+ private:
+ push_coroutine< Arg > * c_;
+
+ public:
+ iterator() :
+ c_( 0)
+ {}
+
+ explicit iterator( push_coroutine< Arg > * c) :
+ c_( c)
+ {}
+
+ iterator & operator=( Arg a)
+ {
+ BOOST_ASSERT( c_);
+ if ( ! ( * c_)( a) ) c_ = 0;
+ return * this;
+ }
+
+ bool operator==( iterator const& other)
+ { return other.c_ == c_; }
+
+ bool operator!=( iterator const& other)
+ { return other.c_ != c_; }
+
+ iterator & operator*()
+ { return * this; }
+
+ iterator & operator++()
+ { return * this; }
+ };
+
+ struct const_iterator;
+};
+
+template< typename Arg >
+class push_coroutine< Arg & >
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::pull_coroutine_object;
+
+ typedef detail::push_coroutine_base< Arg & > base_t;
+ typedef typename base_t::ptr_t ptr_t;
+
+ struct dummy
+ { void nonnull() {} };
+
+ typedef void ( dummy::*safe_bool)();
+
+ ptr_t impl_;
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
+
+ template< typename Allocator >
+ push_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::push_coroutine_caller<
+ Arg &, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ push_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifdef BOOST_MSVC
+ typedef void ( * coroutine_fn) ( pull_coroutine< Arg & > &);
+
+ explicit push_coroutine( coroutine_fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename StackAllocator >
+ explicit push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename StackAllocator, typename Allocator >
+ explicit push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#else
+ template< typename Fn >
+ explicit push_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+
+ push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
+ {
+ push_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( push_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ push_coroutine & operator()( Arg & arg)
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push( arg);
+ return * this;
+ }
+
+ class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void >
+ {
+ private:
+ push_coroutine< Arg & > * c_;
+
+ public:
+ iterator() :
+ c_( 0)
+ {}
+
+ explicit iterator( push_coroutine< Arg & > * c) :
+ c_( c)
+ {}
+
+ iterator & operator=( Arg & a)
+ {
+ BOOST_ASSERT( c_);
+ if ( ! ( * c_)( a) ) c_ = 0;
+ return * this;
+ }
+
+ bool operator==( iterator const& other)
+ { return other.c_ == c_; }
+
+ bool operator!=( iterator const& other)
+ { return other.c_ != c_; }
+
+ iterator & operator*()
+ { return * this; }
+
+ iterator & operator++()
+ { return * this; }
+ };
+
+ struct const_iterator;
+};
+
+template<>
+class push_coroutine< void >
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::pull_coroutine_object;
+
+ typedef detail::push_coroutine_base< void > base_t;
+ typedef base_t::ptr_t ptr_t;
+
+ struct dummy
+ { void nonnull() {} };
+
+ typedef void ( dummy::*safe_bool)();
+
+ ptr_t impl_;
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
+
+ template< typename Allocator >
+ push_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::push_coroutine_caller<
+ void, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ push_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifdef BOOST_MSVC
+ typedef void ( * coroutine_fn) ( pull_coroutine< void > &);
+
+ explicit push_coroutine( coroutine_fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename StackAllocator >
+ explicit push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename StackAllocator, typename Allocator >
+ explicit push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#else
+ template< typename Fn >
+ explicit push_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc =
+ std::allocator< push_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type = 0);
+#endif
+
+ push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
+ {
+ push_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( push_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ push_coroutine & operator()()
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->push();
+ return * this;
+ }
+
+ struct iterator;
+ struct const_iterator;
+};
+
+
+
+template< typename R >
+class pull_coroutine
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::push_coroutine_object;
+
+ typedef detail::pull_coroutine_base< R > base_t;
+ typedef typename base_t::ptr_t ptr_t;
+
+ struct dummy
+ { void nonnull() {} };
+
+ typedef void ( dummy::*safe_bool)();
+
+ ptr_t impl_;
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
+
+ template< typename Allocator >
+ pull_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc,
+ optional< R > const& result) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_caller<
+ R, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a, result) );
+ }
+
+public:
+ pull_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifdef BOOST_MSVC
+ typedef void ( * coroutine_fn) ( push_coroutine< R > &);
+
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, coroutine_fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename StackAllocator >
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, coroutine_fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, coroutine_fn, StackAllocator, Allocator,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+#endif
+ template< typename Fn >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+#else
+ template< typename Fn >
+ explicit pull_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator,
+ push_coroutine< R >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+#endif
+
+ pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
+ {
+ pull_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( pull_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ pull_coroutine & operator()()
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->pull();
+ return * this;
+ }
+
+ bool has_result() const
+ {
+ BOOST_ASSERT( ! empty() );
+
+ return impl_->has_result();
+ }
+
+ R get() const
+ {
+ BOOST_ASSERT( ! empty() );
+
+ return impl_->get();
+ }
+
+ class iterator : public std::iterator< std::input_iterator_tag, typename remove_reference< R >::type >
+ {
+ private:
+ pull_coroutine< R > * c_;
+ optional< R > val_;
+
+ void fetch_()
+ {
+ BOOST_ASSERT( c_);
+
+ if ( ! c_->has_result() )
+ {
+ c_ = 0;
+ val_ = none;
+ return;
+ }
+ val_ = c_->get();
+ }
+
+ void increment_()
+ {
+ BOOST_ASSERT( c_);
+ BOOST_ASSERT( * c_);
+
+ ( * c_)();
+ fetch_();
+ }
+
+ public:
+ typedef typename iterator::pointer pointer_t;
+ typedef typename iterator::reference reference_t;
+
+ iterator() :
+ c_( 0), val_()
+ {}
+
+ explicit iterator( pull_coroutine< R > * c) :
+ c_( c), val_()
+ { fetch_(); }
+
+ iterator( iterator const& other) :
+ c_( other.c_), val_( other.val_)
+ {}
+
+ iterator & operator=( iterator const& other)
+ {
+ if ( this == & other) return * this;
+ c_ = other.c_;
+ val_ = other.val_;
+ return * this;
+ }
+
+ bool operator==( iterator const& other)
+ { return other.c_ == c_ && other.val_ == val_; }
+
+ bool operator!=( iterator const& other)
+ { return other.c_ != c_ || other.val_ != val_; }
+
+ iterator & operator++()
+ {
+ increment_();
+ return * this;
+ }
+
+ iterator operator++( int)
+ {
+ iterator tmp( * this);
+ ++*this;
+ return tmp;
+ }
+
+ reference_t operator*() const
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return const_cast< optional< R > & >( val_).get();
+ }
+
+ pointer_t operator->() const
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return const_cast< optional< R > & >( val_).get_ptr();
+ }
+ };
+
+ class const_iterator : public std::iterator< std::input_iterator_tag, const typename remove_reference< R >::type >
+ {
+ private:
+ pull_coroutine< R > * c_;
+ optional< R > val_;
+
+ void fetch_()
+ {
+ BOOST_ASSERT( c_);
+
+ if ( ! c_->has_result() )
+ {
+ c_ = 0;
+ val_ = none;
+ return;
+ }
+ val_ = c_->get();
+ }
+
+ void increment_()
+ {
+ BOOST_ASSERT( c_);
+ BOOST_ASSERT( * c_);
+
+ ( * c_)();
+ fetch_();
+ }
+
+ public:
+ typedef typename const_iterator::pointer pointer_t;
+ typedef typename const_iterator::reference reference_t;
+
+ const_iterator() :
+ c_( 0), val_()
+ {}
+
+ explicit const_iterator( pull_coroutine< R > const* c) :
+ c_( const_cast< pull_coroutine< R > * >( c) ), val_()
+ { fetch_(); }
+
+ const_iterator( const_iterator const& other) :
+ c_( other.c_), val_( other.val_)
+ {}
+
+ const_iterator & operator=( const_iterator const& other)
+ {
+ if ( this == & other) return * this;
+ c_ = other.c_;
+ val_ = other.val_;
+ return * this;
+ }
+
+ bool operator==( const_iterator const& other)
+ { return other.c_ == c_ && other.val_ == val_; }
+
+ bool operator!=( const_iterator const& other)
+ { return other.c_ != c_ || other.val_ != val_; }
+
+ const_iterator & operator++()
+ {
+ increment_();
+ return * this;
+ }
+
+ const_iterator operator++( int)
+ {
+ const_iterator tmp( * this);
+ ++*this;
+ return tmp;
+ }
+
+ reference_t operator*() const
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return val_.get();
+ }
+
+ pointer_t operator->() const
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return val_.get_ptr();
+ }
+ };
+};
+
+template< typename R >
+class pull_coroutine< R & >
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::push_coroutine_object;
+
+ typedef detail::pull_coroutine_base< R & > base_t;
+ typedef typename base_t::ptr_t ptr_t;
+
+ struct dummy
+ { void nonnull() {} };
+
+ typedef void ( dummy::*safe_bool)();
+
+ ptr_t impl_;
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
+
+ template< typename Allocator >
+ pull_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc,
+ optional< R * > const& result) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_caller<
+ R &, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a, result) );
+ }
+
+public:
+ pull_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifdef BOOST_MSVC
+ typedef void ( * coroutine_fn) ( push_coroutine< R & > &);
+
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, coroutine_fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename StackAllocator >
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, coroutine_fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, coroutine_fn, StackAllocator, Allocator,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+#endif
+ template< typename Fn >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+#else
+ template< typename Fn >
+ explicit pull_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator,
+ push_coroutine< R & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+#endif
+
+ pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
+ {
+ pull_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( pull_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ pull_coroutine & operator()()
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->pull();
+ return * this;
+ }
+
+ bool has_result() const
+ {
+ BOOST_ASSERT( ! empty() );
+
+ return impl_->has_result();
+ }
+
+ R & get() const
+ { return impl_->get(); }
+
+ class iterator : public std::iterator< std::input_iterator_tag, R >
+ {
+ private:
+ pull_coroutine< R & > * c_;
+ optional< R & > val_;
+
+ void fetch_()
+ {
+ BOOST_ASSERT( c_);
+
+ if ( ! c_->has_result() )
+ {
+ c_ = 0;
+ val_ = none;
+ return;
+ }
+ val_ = c_->get();
+ }
+
+ void increment_()
+ {
+ BOOST_ASSERT( c_);
+ BOOST_ASSERT( * c_);
+
+ ( * c_)();
+ fetch_();
+ }
+
+ public:
+ typedef typename iterator::pointer pointer_t;
+ typedef typename iterator::reference reference_t;
+
+ iterator() :
+ c_( 0), val_()
+ {}
+
+ explicit iterator( pull_coroutine< R & > * c) :
+ c_( c), val_()
+ { fetch_(); }
+
+ iterator( iterator const& other) :
+ c_( other.c_), val_( other.val_)
+ {}
+
+ iterator & operator=( iterator const& other)
+ {
+ if ( this == & other) return * this;
+ c_ = other.c_;
+ val_ = other.val_;
+ return * this;
+ }
+
+ bool operator==( iterator const& other)
+ { return other.c_ == c_ && other.val_ == val_; }
+
+ bool operator!=( iterator const& other)
+ { return other.c_ != c_ || other.val_ != val_; }
+
+ iterator & operator++()
+ {
+ increment_();
+ return * this;
+ }
+
+ iterator operator++( int)
+ {
+ iterator tmp( * this);
+ ++*this;
+ return tmp;
+ }
+
+ reference_t operator*() const
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return const_cast< optional< R & > & >( val_).get();
+ }
+
+ pointer_t operator->() const
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return const_cast< optional< R & > & >( val_).get_ptr();
+ }
+ };
+
+ class const_iterator : public std::iterator< std::input_iterator_tag, R >
+ {
+ private:
+ pull_coroutine< R & > * c_;
+ optional< R & > val_;
+
+ void fetch_()
+ {
+ BOOST_ASSERT( c_);
+
+ if ( ! c_->has_result() )
+ {
+ c_ = 0;
+ val_ = none;
+ return;
+ }
+ val_ = c_->get();
+ }
+
+ void increment_()
+ {
+ BOOST_ASSERT( c_);
+ BOOST_ASSERT( * c_);
+
+ ( * c_)();
+ fetch_();
+ }
+
+ public:
+ typedef typename const_iterator::pointer pointer_t;
+ typedef typename const_iterator::reference reference_t;
+
+ const_iterator() :
+ c_( 0), val_()
+ {}
+
+ explicit const_iterator( pull_coroutine< R & > const* c) :
+ c_( const_cast< pull_coroutine< R & > * >( c) ), val_()
+ { fetch_(); }
+
+ const_iterator( const_iterator const& other) :
+ c_( other.c_), val_( other.val_)
+ {}
+
+ const_iterator & operator=( const_iterator const& other)
+ {
+ if ( this == & other) return * this;
+ c_ = other.c_;
+ val_ = other.val_;
+ return * this;
+ }
+
+ bool operator==( const_iterator const& other)
+ { return other.c_ == c_ && other.val_ == val_; }
+
+ bool operator!=( const_iterator const& other)
+ { return other.c_ != c_ || other.val_ != val_; }
+
+ const_iterator & operator++()
+ {
+ increment_();
+ return * this;
+ }
+
+ const_iterator operator++( int)
+ {
+ const_iterator tmp( * this);
+ ++*this;
+ return tmp;
+ }
+
+ reference_t operator*() const
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return val_.get();
+ }
+
+ pointer_t operator->() const
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return val_.get_ptr();
+ }
+ };
+};
+
+template<>
+class pull_coroutine< void >
+{
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class detail::push_coroutine_object;
+
+ typedef detail::pull_coroutine_base< void > base_t;
+ typedef base_t::ptr_t ptr_t;
+
+ struct dummy
+ { void nonnull() {} };
+
+ typedef void ( dummy::*safe_bool)();
+
+ ptr_t impl_;
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
+
+ template< typename Allocator >
+ pull_coroutine( detail::coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ Allocator const& alloc) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_caller<
+ void, Allocator
+ > caller_t;
+ typename caller_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) caller_t(
+ callee, unwind, preserve_fpu, a) );
+ }
+
+public:
+ pull_coroutine() BOOST_NOEXCEPT :
+ impl_()
+ {}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifdef BOOST_MSVC
+ typedef void ( * coroutine_fn) ( push_coroutine< void > &);
+
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, coroutine_fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename StackAllocator >
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, coroutine_fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, coroutine_fn, StackAllocator, Allocator,
+ push_coroutine< void >
+ > object_t;
+ object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+ }
+#endif
+ template< typename Fn >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, Fn, StackAllocator, Allocator,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+ }
+#else
+ template< typename Fn >
+ explicit pull_coroutine( Fn fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, Fn, StackAllocator, Allocator,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
+ stack_allocator const& stack_alloc =
+ stack_allocator(),
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, Fn, stack_allocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< pull_coroutine > const& alloc =
+ std::allocator< pull_coroutine >(),
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, Fn, StackAllocator, std::allocator< pull_coroutine >,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+
+ template< typename Fn, typename StackAllocator, typename Allocator >
+ explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, pull_coroutine >,
+ dummy *
+ >::type = 0) :
+ impl_()
+ {
+ typedef detail::pull_coroutine_object<
+ void, Fn, StackAllocator, Allocator,
+ push_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+ }
+#endif
+
+ pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
+ impl_()
+ { swap( other); }
+
+ pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
+ {
+ pull_coroutine tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ bool empty() const BOOST_NOEXCEPT
+ { return ! impl_; }
+
+ operator safe_bool() const BOOST_NOEXCEPT
+ { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return empty() || impl_->is_complete(); }
+
+ void swap( pull_coroutine & other) BOOST_NOEXCEPT
+ { impl_.swap( other.impl_); }
+
+ pull_coroutine & operator()()
+ {
+ BOOST_ASSERT( * this);
+
+ impl_->pull();
+ return * this;
+ }
+
+ struct iterator;
+ struct const_iterator;
+};
+
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#ifdef BOOST_MSVC
+template< typename Arg >
+push_coroutine< Arg >::push_coroutine( coroutine_fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, coroutine_fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename StackAllocator >
+push_coroutine< Arg >::push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, coroutine_fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename StackAllocator, typename Allocator >
+push_coroutine< Arg >::push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, coroutine_fn, StackAllocator, Allocator,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, coroutine_fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename StackAllocator >
+push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, coroutine_fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename StackAllocator, typename Allocator >
+push_coroutine< Arg & >::push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, coroutine_fn, StackAllocator, Allocator,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+}
+
+push_coroutine< void >::push_coroutine( coroutine_fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, coroutine_fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > object_t;
+ object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename StackAllocator >
+push_coroutine< void >::push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, coroutine_fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > object_t;
+ object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename StackAllocator, typename Allocator >
+push_coroutine< void >::push_coroutine( coroutine_fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ disable_if<
+ is_same< typename decay< coroutine_fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, coroutine_fn, StackAllocator, Allocator,
+ pull_coroutine< void >
+ > object_t;
+ object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< coroutine_fn >( fn), attr, stack_alloc, a) );
+}
+#endif
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Fn >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Fn, typename StackAllocator >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, Allocator,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
+}
+#else
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg >::push_coroutine( Fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg & >::push_coroutine( Fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg & >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg & >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Arg >
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< Arg & >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator,
+ pull_coroutine< Arg & >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Fn >
+push_coroutine< void >::push_coroutine( Fn fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Fn, typename StackAllocator >
+push_coroutine< void >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< void >::push_coroutine( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_convertible< Fn &, BOOST_RV_REF( Fn) >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, Allocator,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Fn >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ stack_allocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, stack_allocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Fn, typename StackAllocator >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ std::allocator< push_coroutine > const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, std::allocator< push_coroutine >,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+
+template< typename Fn, typename StackAllocator, typename Allocator >
+push_coroutine< void >::push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ Allocator const& alloc,
+ typename disable_if<
+ is_same< typename decay< Fn >::type, push_coroutine >,
+ dummy *
+ >::type) :
+ impl_()
+{
+ typedef detail::push_coroutine_object<
+ void, Fn, StackAllocator, Allocator,
+ pull_coroutine< void >
+ > object_t;
+ typename object_t::allocator_t a( alloc);
+ impl_ = ptr_t(
+ // placement new
+ ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
+}
+#endif
+
+template< typename R >
+void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT
+{ l.swap( r); }
+
+template< typename Arg >
+void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT
+{ l.swap( r); }
+
+template< typename R >
+inline
+typename pull_coroutine< R >::iterator
+range_begin( pull_coroutine< R > & c)
+{ return typename pull_coroutine< R >::iterator( & c); }
+
+template< typename R >
+inline
+typename pull_coroutine< R >::const_iterator
+range_begin( pull_coroutine< R > const& c)
+{ return typename pull_coroutine< R >::const_iterator( & c); }
+
+template< typename R >
+inline
+typename pull_coroutine< R >::iterator
+range_end( pull_coroutine< R > &)
+{ return typename pull_coroutine< R >::iterator(); }
+
+template< typename R >
+inline
+typename pull_coroutine< R >::const_iterator
+range_end( pull_coroutine< R > const&)
+{ return typename pull_coroutine< R >::const_iterator(); }
+
+template< typename Arg >
+inline
+typename push_coroutine< Arg >::iterator
+range_begin( push_coroutine< Arg > & c)
+{ return typename push_coroutine< Arg >::iterator( & c); }
+
+template< typename Arg >
+inline
+typename push_coroutine< Arg >::const_iterator
+range_begin( push_coroutine< Arg > const& c)
+{ return typename push_coroutine< Arg >::const_iterator( & c); }
+
+template< typename Arg >
+inline
+typename push_coroutine< Arg >::iterator
+range_end( push_coroutine< Arg > &)
+{ return typename push_coroutine< Arg >::iterator(); }
+
+template< typename Arg >
+inline
+typename push_coroutine< Arg >::const_iterator
+range_end( push_coroutine< Arg > const&)
+{ return typename push_coroutine< Arg >::const_iterator(); }
+
+template< typename T >
+struct coroutine
+{
+ typedef push_coroutine< T > push_type;
+ typedef pull_coroutine< T > pull_type;
+};
+
+}
+
+template< typename Arg >
+struct range_mutable_iterator< coroutines::push_coroutine< Arg > >
+{ typedef typename coroutines::push_coroutine< Arg >::iterator type; };
+
+template< typename Arg >
+struct range_const_iterator< coroutines::push_coroutine< Arg > >
+{ typedef typename coroutines::push_coroutine< Arg >::const_iterator type; };
+
+template< typename R >
+struct range_mutable_iterator< coroutines::pull_coroutine< R > >
+{ typedef typename coroutines::pull_coroutine< R >::iterator type; };
+
+template< typename R >
+struct range_const_iterator< coroutines::pull_coroutine< R > >
+{ typedef typename coroutines::pull_coroutine< R >::const_iterator type; };
+
+}
+
+namespace std {
+
+template< typename R >
+inline
+typename boost::coroutines::pull_coroutine< R >::iterator
+begin( boost::coroutines::pull_coroutine< R > & c)
+{ return boost::begin( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::pull_coroutine< R >::iterator
+end( boost::coroutines::pull_coroutine< R > & c)
+{ return boost::end( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::pull_coroutine< R >::const_iterator
+begin( boost::coroutines::pull_coroutine< R > const& c)
+{ return boost::const_begin( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::pull_coroutine< R >::const_iterator
+end( boost::coroutines::pull_coroutine< R > const& c)
+{ return boost::const_end( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::push_coroutine< R >::iterator
+begin( boost::coroutines::push_coroutine< R > & c)
+{ return boost::begin( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::push_coroutine< R >::iterator
+end( boost::coroutines::push_coroutine< R > & c)
+{ return boost::end( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::push_coroutine< R >::const_iterator
+begin( boost::coroutines::push_coroutine< R > const& c)
+{ return boost::const_begin( c); }
+
+template< typename R >
+inline
+typename boost::coroutines::push_coroutine< R >::const_iterator
+end( boost::coroutines::push_coroutine< R > const& c)
+{ return boost::const_end( c); }
+
+}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_UNIDIRECT_COROUTINE_H
Deleted: branches/release/boost/coroutine/v2/detail/coroutine_object.hpp
==============================================================================
--- branches/release/boost/coroutine/v2/detail/coroutine_object.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,423 +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_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
-#define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OBJECT_H
-
-#include <cstddef>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/exception_ptr.hpp>
-#include <boost/move/move.hpp>
-#include <boost/ref.hpp>
-#include <boost/tuple/tuple.hpp>
-#include <boost/type_traits/function_traits.hpp>
-#include <boost/utility.hpp>
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/exceptions.hpp>
-#include <boost/coroutine/detail/flags.hpp>
-#include <boost/coroutine/detail/holder.hpp>
-#include <boost/coroutine/detail/param.hpp>
-#include <boost/coroutine/flags.hpp>
-#include <boost/coroutine/stack_context.hpp>
-#include <boost/coroutine/v2/detail/arg.hpp>
-#include <boost/coroutine/v2/detail/coroutine_base.hpp>
-
-template<
- typename Arg,
- typename Fn, typename StackAllocator, typename Allocator
->
-class coroutine_object< Arg, Fn, StackAllocator, Allocator > :
- private stack_tuple< StackAllocator >,
- public coroutine_base
-{
-public:
- typedef typename Allocator::template rebind<
- coroutine_object<
- Arg, Fn, StackAllocator, Allocator
- >
- >::other allocator_t;
-
-private:
- typedef stack_tuple< StackAllocator > pbase_type;
- typedef coroutine_base base_type;
-
- Fn fn_;
- allocator_t alloc_;
-
- static void destroy_( allocator_t & alloc, coroutine_object * p)
- {
- alloc.destroy( p);
- alloc.deallocate( p, 1);
- }
-
- coroutine_object( coroutine_object const&);
- coroutine_object & operator=( coroutine_object const&);
-
- void enter_()
- {
- holder< void > * hldr_from(
- reinterpret_cast< holder< void > * >(
- this->caller_.jump(
- this->callee_,
- reinterpret_cast< intptr_t >( this),
- this->preserve_fpu() ) ) );
- this->callee_ = * hldr_from->ctx;
- this->result_ = hldr_from->data;
- if ( this->except_) rethrow_exception( this->except_);
- }
-
- void run_( Caller & c)
- {
- coroutine_context callee;
- coroutine_context caller;
- try
- {
- fn_( c);
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< void > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { this->except_ = current_exception(); }
-
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< void > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
-
- void unwind_stack_() BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! this->is_complete() );
-
- this->flags_ |= flag_unwind_stack;
- holder< void > hldr_to( & this->caller_, true);
- this->caller_.jump(
- this->callee_,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- this->flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( this->is_complete() );
- }
-
-public:
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- allocator_t const& alloc) :
- pbase_type( stack_alloc, attr.size),
- base_type(
- trampoline1< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( forward< Fn >( fn) ),
- alloc_( alloc)
- { enter_(); }
-#else
- coroutine_object( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- allocator_t const& alloc) :
- pbase_type( stack_alloc, attr.size),
- base_type(
- trampoline1< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( fn),
- alloc_( alloc)
- { enter_(); }
-
- coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- allocator_t const& alloc) :
- pbase_type( stack_alloc, attr.size),
- base_type(
- trampoline1< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( fn),
- alloc_( alloc)
- { enter_(); }
-#endif
-
- ~coroutine_object()
- {
- if ( ! this->is_complete() && this->force_unwind() )
- unwind_stack_();
- }
-
- void run()
- {
- Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
- run_( c);
- }
-
- void deallocate_object()
- { destroy_( alloc_, this); }
-};
-
-template<
- typename Arg,
- typename Fn, typename StackAllocator, typename Allocator,
- typename Caller,
- typename Result
->
-class coroutine_object< Arg, reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > :
- private stack_tuple< StackAllocator >,
- public coroutine_base< Arg >
-{
-public:
- typedef typename Allocator::template rebind<
- coroutine_object<
- Arg, Fn, StackAllocator, Allocator, Caller, Result, 0
- >
- >::other allocator_t;
-
-private:
- typedef stack_tuple< StackAllocator > pbase_type;
- typedef coroutine_base< Arg > base_type;
-
- Fn fn_;
- allocator_t alloc_;
-
- static void destroy_( allocator_t & alloc, coroutine_object * p)
- {
- alloc.destroy( p);
- alloc.deallocate( p, 1);
- }
-
- coroutine_object( coroutine_object const&);
- coroutine_object & operator=( coroutine_object const&);
-
- void enter_()
- {
- holder< Result > * hldr_from(
- reinterpret_cast< holder< Result > * >(
- this->caller_.jump(
- this->callee_,
- reinterpret_cast< intptr_t >( this),
- this->preserve_fpu() ) ) );
- this->callee_ = * hldr_from->ctx;
- this->result_ = hldr_from->data;
- if ( this->except_) rethrow_exception( this->except_);
- }
-
- void run_( Caller & c)
- {
- coroutine_context callee;
- coroutine_context caller;
- try
- {
- fn_( c);
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< Result > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { this->except_ = current_exception(); }
-
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< Result > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
-
- void unwind_stack_() BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! this->is_complete() );
-
- this->flags_ |= flag_unwind_stack;
- holder< void > hldr_to( & this->caller_, true);
- this->caller_.jump(
- this->callee_,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- this->flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( this->is_complete() );
- }
-
-public:
- coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- allocator_t const& alloc) :
- pbase_type( stack_alloc, attr.size),
- base_type(
- trampoline1< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( fn),
- alloc_( alloc)
- { enter_(); }
-
- ~coroutine_object()
- {
- if ( ! this->is_complete() && this->force_unwind() )
- unwind_stack_();
- }
-
- void run()
- {
- Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
- run_( c);
- }
-
- void deallocate_object()
- { destroy_( alloc_, this); }
-};
-
-template<
- typename Arg,
- typename Fn, typename StackAllocator, typename Allocator,
- typename Caller,
- typename Result
->
-class coroutine_object< Arg, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller, Result, 0 > :
- private stack_tuple< StackAllocator >,
- public coroutine_base< Arg >
-{
-public:
- typedef typename Allocator::template rebind<
- coroutine_object<
- Arg, Fn, StackAllocator, Allocator, Caller, Result, 0
- >
- >::other allocator_t;
-
-private:
- typedef stack_tuple< StackAllocator > pbase_type;
- typedef coroutine_base< Arg > base_type;
-
- Fn fn_;
- allocator_t alloc_;
-
- static void destroy_( allocator_t & alloc, coroutine_object * p)
- {
- alloc.destroy( p);
- alloc.deallocate( p, 1);
- }
-
- coroutine_object( coroutine_object const&);
- coroutine_object & operator=( coroutine_object const&);
-
- void enter_()
- {
- holder< Result > * hldr_from(
- reinterpret_cast< holder< Result > * >(
- this->caller_.jump(
- this->callee_,
- reinterpret_cast< intptr_t >( this),
- this->preserve_fpu() ) ) );
- this->callee_ = hldr_from->ctx;
- this->result_ = hldr_from->data;
- if ( this->except_) rethrow_exception( this->except_);
- }
-
- void run_( Caller & c)
- {
- coroutine_context callee;
- coroutine_context caller;
- try
- {
- fn_( c);
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< Result > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
- catch ( forced_unwind const&)
- {}
- catch (...)
- { this->except_ = current_exception(); }
-
- this->flags_ |= flag_complete;
- callee = c.impl_->callee_;
- holder< Result > hldr_to( & caller);
- caller.jump(
- callee,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- BOOST_ASSERT_MSG( false, "coroutine is complete");
- }
-
- void unwind_stack_() BOOST_NOEXCEPT
- {
- BOOST_ASSERT( ! this->is_complete() );
-
- this->flags_ |= flag_unwind_stack;
- holder< void > hldr_to( & this->caller_, true);
- this->caller_.jump(
- this->callee_,
- reinterpret_cast< intptr_t >( & hldr_to),
- this->preserve_fpu() );
- this->flags_ &= ~flag_unwind_stack;
-
- BOOST_ASSERT( this->is_complete() );
- }
-
-public:
- coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- allocator_t const& alloc) :
- pbase_type( stack_alloc, attr.size),
- base_type(
- trampoline1< coroutine_object >,
- & this->stack_ctx,
- stack_unwind == attr.do_unwind,
- fpu_preserved == attr.preserve_fpu),
- fn_( fn),
- alloc_( alloc)
- { enter_(); }
-
- ~coroutine_object()
- {
- if ( ! this->is_complete() && this->force_unwind() )
- unwind_stack_();
- }
-
- void run()
- {
- Caller c( & this->caller_, false, this->preserve_fpu(), alloc_);
- run_( c);
- }
-
- void deallocate_object()
- { destroy_( alloc_, this); }
-};
Copied: branches/release/boost/coroutine/v2/detail/pull_coroutine_base.hpp (from r85162, trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/v2/detail/pull_coroutine_base.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/v2/detail/pull_coroutine_base.hpp)
@@ -0,0 +1,337 @@
+
+// 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_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_BASE_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_BASE_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/context/fcontext.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+#include <boost/coroutine/detail/holder.hpp>
+#include <boost/coroutine/detail/param.hpp>
+#include <boost/coroutine/exceptions.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+
+struct stack_context;
+
+namespace detail {
+
+template< typename R >
+class pull_coroutine_base : private noncopyable
+{
+public:
+ typedef intrusive_ptr< pull_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class push_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+ optional< R > result_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ pull_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx),
+ result_()
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ pull_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ optional< R > const& result) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee),
+ result_( result)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~pull_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void pull()
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< R > hldr_to( & caller_);
+ holder< R > * hldr_from(
+ reinterpret_cast< holder< R > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ result_ = hldr_from->data;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ bool has_result() const
+ { return result_; }
+
+ R get() const
+ {
+ if ( ! has_result() )
+ boost::throw_exception(
+ invalid_result() );
+ return result_.get();
+ }
+};
+
+template< typename R >
+class pull_coroutine_base< R & > : private noncopyable
+{
+public:
+ typedef intrusive_ptr< pull_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class push_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+ optional< R * > result_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ pull_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx),
+ result_()
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ pull_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu,
+ optional< R * > const& result) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee),
+ result_( result)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~pull_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void pull()
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< R & > hldr_to( & caller_);
+ holder< R & > * hldr_from(
+ reinterpret_cast< holder< R & > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ result_ = hldr_from->data;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ bool has_result() const
+ { return result_; }
+
+ R & get() const
+ {
+ if ( ! has_result() )
+ boost::throw_exception(
+ invalid_result() );
+ return * result_.get();
+ }
+};
+
+template<>
+class pull_coroutine_base< void > : private noncopyable
+{
+public:
+ typedef intrusive_ptr< pull_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class push_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ pull_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ pull_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~pull_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( pull_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void pull()
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< void > hldr_to( & caller_);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_BASE_H
Copied: branches/release/boost/coroutine/v2/detail/pull_coroutine_caller.hpp (from r85162, trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/v2/detail/pull_coroutine_caller.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/v2/detail/pull_coroutine_caller.hpp)
@@ -0,0 +1,111 @@
+// 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_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_CALLER_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_CALLER_H
+
+#include <boost/config.hpp>
+#include <boost/context/fcontext.hpp>
+#include <boost/optional.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_base.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename R, typename Allocator >
+class pull_coroutine_caller : public pull_coroutine_base< R >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_caller< R, Allocator >
+ >::other allocator_t;
+
+ pull_coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu,
+ allocator_t const& alloc, optional< R > const& data) BOOST_NOEXCEPT :
+ pull_coroutine_base< R >( callee, unwind, preserve_fpu, data),
+ alloc_( alloc)
+ {}
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+
+private:
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_caller * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+};
+
+template< typename R, typename Allocator >
+class pull_coroutine_caller< R &, Allocator > : public pull_coroutine_base< R & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_caller< R &, Allocator >
+ >::other allocator_t;
+
+ pull_coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu,
+ allocator_t const& alloc, optional< R * > const& data) BOOST_NOEXCEPT :
+ pull_coroutine_base< R & >( callee, unwind, preserve_fpu, data),
+ alloc_( alloc)
+ {}
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+
+private:
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_caller * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+};
+
+template< typename Allocator >
+class pull_coroutine_caller< void, Allocator > : public pull_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_caller< void, Allocator >
+ >::other allocator_t;
+
+ pull_coroutine_caller( coroutine_context const& callee, bool unwind, bool preserve_fpu,
+ allocator_t const& alloc) BOOST_NOEXCEPT :
+ pull_coroutine_base< void >( callee, unwind, preserve_fpu),
+ alloc_( alloc)
+ {}
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+
+private:
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_caller * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_CALLER_H
Copied: branches/release/boost/coroutine/v2/detail/pull_coroutine_object.hpp (from r85162, trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/v2/detail/pull_coroutine_object.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/v2/detail/pull_coroutine_object.hpp)
@@ -0,0 +1,1124 @@
+
+// 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_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_OBJECT_H
+
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/move/move.hpp>
+#include <boost/ref.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/coroutine/attributes.hpp>
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/exceptions.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+#include <boost/coroutine/detail/holder.hpp>
+#include <boost/coroutine/detail/param.hpp>
+#include <boost/coroutine/detail/stack_tuple.hpp>
+#include <boost/coroutine/detail/trampoline.hpp>
+#include <boost/coroutine/flags.hpp>
+#include <boost/coroutine/stack_context.hpp>
+#include <boost/coroutine/v2/detail/pull_coroutine_base.hpp>
+
+#ifdef BOOST_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4355) // using 'this' in initializer list
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object : private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R > * hldr_from(
+ reinterpret_cast< holder< R > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ this->result_ = hldr_from->data;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ pull_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ pull_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create push_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R > * hldr_from(
+ reinterpret_cast< holder< R > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R > * hldr_from(
+ reinterpret_cast< holder< R > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R &, Fn, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R * > * hldr_from(
+ reinterpret_cast< holder< R * > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ this->result_ = hldr_from->data;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ pull_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ pull_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create push_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R &, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R * > * hldr_from(
+ reinterpret_cast< holder< R * > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename R, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< R &, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< R & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ R &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< R & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< R * > * hldr_from(
+ reinterpret_cast< holder< R * > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< R * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< R * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< void, Fn, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< void > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ pull_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ pull_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ pull_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create push_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< void, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< void > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class pull_coroutine_object< void, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public pull_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ pull_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef pull_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, pull_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ pull_coroutine_object( pull_coroutine_object &);
+ pull_coroutine_object & operator=( pull_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< void > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ pull_coroutine_object( const reference_wrapper< Fn > fn,
+ attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< pull_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~pull_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ // create pull_coroutine
+ Caller c( this->caller_, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#ifdef BOOST_MSVC
+ #pragma warning (pop)
+#endif
+
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PULL_COROUTINE_OBJECT_H
Copied: branches/release/boost/coroutine/v2/detail/push_coroutine_base.hpp (from r85162, trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/v2/detail/push_coroutine_base.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/v2/detail/push_coroutine_base.hpp)
@@ -0,0 +1,354 @@
+
+// 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_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_BASE_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_BASE_H
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/context/fcontext.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/detail/coroutine_context.hpp>
+#include <boost/coroutine/exceptions.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+
+struct stack_context;
+
+namespace detail {
+
+template< typename Arg >
+class push_coroutine_base : private noncopyable
+{
+public:
+ typedef intrusive_ptr< push_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class pull_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ push_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ push_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~push_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ void push( Arg const& arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg > hldr_to( & caller_, arg);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ void push( Arg && arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg > hldr_to( & caller_, boost::forward( arg) );
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+#else
+ void push( Arg const& arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg > hldr_to( & caller_, arg);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+
+ void push( BOOST_RV_REF( Arg) arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg > hldr_to( & caller_, arg);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+#endif
+};
+
+template< typename Arg >
+class push_coroutine_base< Arg & > : private noncopyable
+{
+public:
+ typedef intrusive_ptr< push_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class pull_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ push_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ push_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~push_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void push( Arg & arg)
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< Arg * > hldr_to( & caller_, & arg);
+ holder< Arg * > * hldr_from(
+ reinterpret_cast< holder< Arg * > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+};
+
+template<>
+class push_coroutine_base< void > : private noncopyable
+{
+public:
+ typedef intrusive_ptr< push_coroutine_base > ptr_t;
+
+private:
+ template<
+ typename X, typename Y, typename Z, typename V, typename W
+ >
+ friend class pull_coroutine_object;
+
+ unsigned int use_count_;
+
+protected:
+ int flags_;
+ exception_ptr except_;
+ coroutine_context caller_;
+ coroutine_context callee_;
+
+ virtual void deallocate_object() = 0;
+
+public:
+ push_coroutine_base( coroutine_context::ctx_fn fn,
+ stack_context * stack_ctx,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( fn, stack_ctx)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ push_coroutine_base( coroutine_context const& callee,
+ bool unwind, bool preserve_fpu) :
+ use_count_( 0),
+ flags_( 0),
+ except_(),
+ caller_(),
+ callee_( callee)
+ {
+ if ( unwind) flags_ |= flag_force_unwind;
+ if ( preserve_fpu) flags_ |= flag_preserve_fpu;
+ }
+
+ virtual ~push_coroutine_base()
+ {}
+
+ bool force_unwind() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_force_unwind); }
+
+ bool unwind_requested() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_unwind_stack); }
+
+ bool preserve_fpu() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_preserve_fpu); }
+
+ bool is_complete() const BOOST_NOEXCEPT
+ { return 0 != ( flags_ & flag_complete); }
+
+ friend inline void intrusive_ptr_add_ref( push_coroutine_base * p) BOOST_NOEXCEPT
+ { ++p->use_count_; }
+
+ friend inline void intrusive_ptr_release( push_coroutine_base * p) BOOST_NOEXCEPT
+ { if ( --p->use_count_ == 0) p->deallocate_object(); }
+
+ void push()
+ {
+ BOOST_ASSERT( ! is_complete() );
+
+ holder< void > hldr_to( & caller_);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ hldr_to.ctx->jump(
+ callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ callee_ = * hldr_from->ctx;
+ if ( hldr_from->force_unwind) throw forced_unwind();
+ if ( except_) rethrow_exception( except_);
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_BASE_H
Copied: branches/release/boost/coroutine/v2/detail/push_coroutine_caller.hpp (from r85162, trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/v2/detail/push_coroutine_caller.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/v2/detail/push_coroutine_caller.hpp)
@@ -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)
+
+#ifndef BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_CALLER_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_CALLER_H
+
+#include <boost/config.hpp>
+#include <boost/context/fcontext.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_base.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename Arg, typename Allocator >
+class push_coroutine_caller : public push_coroutine_base< Arg >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_caller< Arg, Allocator >
+ >::other allocator_t;
+
+ push_coroutine_caller( coroutine_context const& callee, bool unwind,
+ bool preserve_fpu, allocator_t const& alloc) BOOST_NOEXCEPT :
+ push_coroutine_base< Arg >( callee, unwind, preserve_fpu),
+ alloc_( alloc)
+ {}
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+
+private:
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_caller * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_CALLER_H
Copied: branches/release/boost/coroutine/v2/detail/push_coroutine_object.hpp (from r85162, trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/coroutine/v2/detail/push_coroutine_object.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/boost/coroutine/v2/detail/push_coroutine_object.hpp)
@@ -0,0 +1,1208 @@
+
+// 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_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_OBJECT_H
+#define BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_OBJECT_H
+
+#include <cstddef>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/exception_ptr.hpp>
+#include <boost/move/move.hpp>
+#include <boost/ref.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/function_traits.hpp>
+#include <boost/utility.hpp>
+
+#include <boost/coroutine/attributes.hpp>
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/exceptions.hpp>
+#include <boost/coroutine/detail/flags.hpp>
+#include <boost/coroutine/detail/holder.hpp>
+#include <boost/coroutine/detail/param.hpp>
+#include <boost/coroutine/detail/stack_tuple.hpp>
+#include <boost/coroutine/detail/trampoline.hpp>
+#include <boost/coroutine/flags.hpp>
+#include <boost/coroutine/stack_context.hpp>
+#include <boost/coroutine/v2/detail/push_coroutine_base.hpp>
+
+#ifdef BOOST_MSVC
+ #pragma warning (push)
+ #pragma warning (disable: 4355) // using 'this' in initializer list
+#endif
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object : private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ push_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ push_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg > * hldr_from(
+ reinterpret_cast< holder< Arg > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg &, Fn, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ push_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ push_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg * > * hldr_from(
+ reinterpret_cast< holder< Arg * > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg &, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg &, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg * > * hldr_from(
+ reinterpret_cast< holder< Arg * > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Arg, typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< Arg &, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< Arg & >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ Arg, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< Arg & > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< Arg * > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< Arg * > * hldr_from(
+ reinterpret_cast< holder< Arg * > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+ BOOST_ASSERT( hldr_from->data);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_, hldr_from->data);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< Arg * > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< void, Fn, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< void > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ push_coroutine_object( Fn && fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( forward< Fn >( fn) ),
+ alloc_( alloc)
+ { enter_(); }
+#else
+ push_coroutine_object( Fn fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+#endif
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< void, reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< void > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+template<
+ typename Fn,
+ typename StackAllocator, typename Allocator,
+ typename Caller
+>
+class push_coroutine_object< void, const reference_wrapper< Fn >, StackAllocator, Allocator, Caller > :
+ private stack_tuple< StackAllocator >,
+ public push_coroutine_base< void >
+{
+public:
+ typedef typename Allocator::template rebind<
+ push_coroutine_object<
+ void, Fn, StackAllocator, Allocator, Caller
+ >
+ >::other allocator_t;
+
+private:
+ typedef stack_tuple< StackAllocator > pbase_type;
+ typedef push_coroutine_base< void > base_type;
+
+ Fn fn_;
+ allocator_t alloc_;
+
+ static void destroy_( allocator_t & alloc, push_coroutine_object * p)
+ {
+ alloc.destroy( p);
+ alloc.deallocate( p, 1);
+ }
+
+ push_coroutine_object( push_coroutine_object &);
+ push_coroutine_object & operator=( push_coroutine_object const&);
+
+ void enter_()
+ {
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( this),
+ this->preserve_fpu() ) ) );
+ this->callee_ = * hldr_from->ctx;
+ if ( this->except_) rethrow_exception( this->except_);
+ }
+
+ void unwind_stack_() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT( ! this->is_complete() );
+
+ this->flags_ |= flag_unwind_stack;
+ holder< void > hldr_to( & this->caller_, true);
+ this->caller_.jump(
+ this->callee_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ this->flags_ &= ~flag_unwind_stack;
+
+ BOOST_ASSERT( this->is_complete() );
+ }
+
+public:
+ push_coroutine_object( const reference_wrapper< Fn > fn, attributes const& attr,
+ StackAllocator const& stack_alloc,
+ allocator_t const& alloc) :
+ pbase_type( stack_alloc, attr.size),
+ base_type(
+ trampoline1< push_coroutine_object >,
+ & this->stack_ctx,
+ stack_unwind == attr.do_unwind,
+ fpu_preserved == attr.preserve_fpu),
+ fn_( fn),
+ alloc_( alloc)
+ { enter_(); }
+
+ ~push_coroutine_object()
+ {
+ if ( ! this->is_complete() && this->force_unwind() )
+ unwind_stack_();
+ }
+
+ void run()
+ {
+ coroutine_context callee;
+ coroutine_context caller;
+
+ {
+ holder< void > hldr_to( & caller);
+ holder< void > * hldr_from(
+ reinterpret_cast< holder< void > * >(
+ caller.jump(
+ this->caller_,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() ) ) );
+ BOOST_ASSERT( hldr_from->ctx);
+
+ // create pull_coroutine
+ Caller c( * hldr_from->ctx, false, this->preserve_fpu(), alloc_);
+ try
+ { fn_( c); }
+ catch ( forced_unwind const&)
+ {}
+ catch (...)
+ { this->except_ = current_exception(); }
+ callee = c.impl_->callee_;
+ }
+
+ this->flags_ |= flag_complete;
+ holder< void > hldr_to( & caller);
+ caller.jump(
+ callee,
+ reinterpret_cast< intptr_t >( & hldr_to),
+ this->preserve_fpu() );
+ BOOST_ASSERT_MSG( false, "push_coroutine is complete");
+ }
+
+ void deallocate_object()
+ { destroy_( alloc_, this); }
+};
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#ifdef BOOST_MSVC
+ #pragma warning (pop)
+#endif
+
+#endif // BOOST_COROUTINES_UNIDIRECT_DETAIL_PUSH_COROUTINE_OBJECT_H
Deleted: branches/release/boost/coroutine/v2/pull_corotuine.hpp
==============================================================================
--- branches/release/boost/coroutine/v2/pull_corotuine.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,355 +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_COROUTINES_V2_PULL_COROUTINE_H
-#define BOOST_COROUTINES_V2_PULL_COROUTINE_H
-
-#include <cstddef>
-#include <memory>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-#include <boost/range.hpp>
-#include <boost/type_traits/decay.hpp>
-#include <boost/type_traits/function_traits.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/utility/result_of.hpp>
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/stack_allocator.hpp>
-#include <boost/coroutine/v2/pull_coroutine_base.hpp.hpp>
-#include <boost/coroutine/v2/pull_coroutine_object.hpp.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename R >
-class pull_coroutine
-{
-private:
- typedef detail::pull_coroutine_base< R > base_t;
- typedef typename base_t::ptr_t ptr_t;
-
- struct dummy
- { void nonnull() {} };
-
- typedef void ( dummy::*safe_bool)();
-
- ptr_t impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( pull_coroutine)
-
-public:
- pull_coroutine() BOOST_NOEXCEPT :
- impl_()
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- template< typename Fn >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< pull_coroutine > const& alloc =
- std::allocator< pull_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, pull_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::pull_coroutine_object<
- R, Fn, stack_allocator, std::allocator< pull_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< pull_coroutine > const& alloc =
- std::allocator< pull_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, pull_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::pull_coroutine_object<
- R, Fn, StackAllocator, std::allocator< pull_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator, typename Allocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, pull_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::pull_coroutine_object<
- R, Fn, StackAllocator, Allocator
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
- }
-#else
- template< typename Fn >
- explicit pull_coroutine( Fn fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< pull_coroutine > const& alloc =
- std::allocator< pull_coroutine >(),
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::pull_coroutine_object<
- R, Fn, stack_allocator, std::allocator< pull_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< pull_coroutine > const& alloc =
- std::allocator< pull_coroutine >(),
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::pull_coroutine_object<
- R, Fn, StackAllocator, std::allocator< pull_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator, typename Allocator >
- explicit pull_coroutine( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::pull_coroutine_object<
- R, Fn, StackAllocator, Allocator
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< pull_coroutine > const& alloc =
- std::allocator< pull_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, pull_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::pull_coroutine_object<
- R, Fn, stack_allocator, std::allocator< pull_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< pull_coroutine > const& alloc =
- std::allocator< pull_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, pull_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::pull_coroutine_object<
- R, Fn, StackAllocator, std::allocator< pull_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator, typename Allocator >
- explicit pull_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, pull_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::pull_coroutine_object<
- R, Fn, StackAllocator, Allocator
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-#endif
-
- pull_coroutine( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT :
- impl_()
- { swap( other); }
-
- pull_coroutine & operator=( BOOST_RV_REF( pull_coroutine) other) BOOST_NOEXCEPT
- {
- pull_coroutine tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- bool empty() const BOOST_NOEXCEPT
- { return ! impl_; }
-
- operator safe_bool() const BOOST_NOEXCEPT
- { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
-
- bool operator!() const BOOST_NOEXCEPT
- { return empty() || impl_->is_complete(); }
-
- void swap( pull_coroutine & other) BOOST_NOEXCEPT
- { impl_.swap( other.impl_); }
-
- void operator()()
- {
- BOOST_ASSERT( * this);
-
- impl_->resume();
- }
-
- bool has_result() const
- {
- BOOST_ASSERT( * this);
-
- return impl_->has_result();
- }
-
- R get() const
- {
- BOOST_ASSERT( * this);
-
- return impl_->get();
- }
-};
-
-template< typename R >
-void swap( pull_coroutine< R > & l, pull_coroutine< R > & r) BOOST_NOEXCEPT
-{ l.swap( r); }
-#if 0
-template< typename R >
-inline
-typename pull_coroutine< R >::iterator
-range_begin( pull_coroutine< R > & c)
-{ return typename pull_coroutine< R >::iterator( & c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::const_iterator
-range_begin( pull_coroutine< R > const& c)
-{ return typename pull_coroutine< R >::const_iterator( & c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::iterator
-range_end( pull_coroutine< R > &)
-{ return typename pull_coroutine< R >::iterator(); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::const_iterator
-range_end( pull_coroutine< R > const&)
-{ return typename pull_coroutine< R >::const_iterator(); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::iterator
-begin( pull_coroutine< R > & c)
-{ return boost::begin( c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::iterator
-end( pull_coroutine< R > & c)
-{ return boost::end( c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::const_iterator
-begin( pull_coroutine< R > const& c)
-{ return boost::const_begin( c); }
-
-template< typename R >
-inline
-typename pull_coroutine< R >::const_iterator
-end( pull_coroutine< R > const& c)
-{ return boost::const_end( c); }
-
-}
-
-template< typename R >
-struct range_mutable_iterator< coroutines::coroutine< R > >
-{ typedef typename coroutines::coroutine< R >::iterator type; };
-
-template< typename R >
-struct range_const_iterator< coroutines::coroutine< R > >
-{ typedef typename coroutines::coroutine< R >::const_iterator type; };
-#endif
-}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_V2_PULL_COROUTINE_H
Deleted: branches/release/boost/coroutine/v2/push_coroutine.hpp
==============================================================================
--- branches/release/boost/coroutine/v2/push_coroutine.hpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,357 +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_COROUTINES_V2_PUSH_COROUTINE_H
-#define BOOST_COROUTINES_V2_PUSH_COROUTINE_H
-
-#include <cstddef>
-#include <memory>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/move/move.hpp>
-#include <boost/range.hpp>
-#include <boost/type_traits/decay.hpp>
-#include <boost/type_traits/function_traits.hpp>
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/utility/enable_if.hpp>
-#include <boost/utility/result_of.hpp>
-
-#include <boost/coroutine/attributes.hpp>
-#include <boost/coroutine/detail/config.hpp>
-#include <boost/coroutine/detail/coroutine_context.hpp>
-#include <boost/coroutine/stack_allocator.hpp>
-#include <boost/coroutine/v2/push_coroutine_base.hpp>
-#include <boost/coroutine/v2/push_coroutine_object.hpp.hpp>
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_PREFIX
-#endif
-
-namespace boost {
-namespace coroutines {
-namespace detail {
-
-template< typename Arg >
-class push_coroutine
-{
-private:
- typedef detail::push_coroutine_base< Arg > base_t;
- typedef typename base_t::ptr_t ptr_t;
-
- struct dummy
- { void nonnull() {} };
-
- typedef void ( dummy::*safe_bool)();
-
- ptr_t impl_;
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE( push_coroutine)
-
-public:
- push_coroutine() BOOST_NOEXCEPT :
- impl_()
- {}
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, stack_allocator, std::allocator< push_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, std::allocator< push_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator, typename Allocator >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, Allocator
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
- }
-#else
- template< typename Fn >
- explicit push_coroutine( Fn fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, stack_allocator, std::allocator< push_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, std::allocator< push_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator, typename Allocator >
- explicit push_coroutine( Fn fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_convertible< Fn &, BOOST_RV_REF( Fn) >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, Allocator
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
- stack_allocator const& stack_alloc =
- stack_allocator(),
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, stack_allocator, std::allocator< push_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- std::allocator< push_coroutine > const& alloc =
- std::allocator< push_coroutine >(),
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, std::allocator< push_coroutine >
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-
- template< typename Fn, typename StackAllocator, typename Allocator >
- explicit push_coroutine( BOOST_RV_REF( Fn) fn, attributes const& attr,
- StackAllocator const& stack_alloc,
- Allocator const& alloc,
- typename disable_if<
- is_same< typename decay< Fn >::type, push_coroutine >,
- dummy *
- >::type = 0) :
- impl_()
- {
- typedef detail::push_coroutine_object<
- Arg, Fn, StackAllocator, Allocator
- > object_t;
- typename object_t::allocator_t a( alloc);
- impl_ = ptr_t(
- // placement new
- ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
- }
-#endif
-
- push_coroutine( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT :
- impl_()
- { swap( other); }
-
- push_coroutine & operator=( BOOST_RV_REF( push_coroutine) other) BOOST_NOEXCEPT
- {
- push_coroutine tmp( boost::move( other) );
- swap( tmp);
- return * this;
- }
-
- bool empty() const BOOST_NOEXCEPT
- { return ! impl_; }
-
- operator safe_bool() const BOOST_NOEXCEPT
- { return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
-
- bool operator!() const BOOST_NOEXCEPT
- { return empty() || impl_->is_complete(); }
-
- void swap( push_coroutine & other) BOOST_NOEXCEPT
- { impl_.swap( other.impl_); }
-
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- void operator()( Arg && arg)
- {
- BOOST_ASSERT( * this);
-
- impl_->resume( boost::forward< Arg >( arg) );
- }
-#else
- void operator()( BOOST_RV_REF( Arg) arg)
- {
- BOOST_ASSERT( * this);
-
- impl_->resume( boost::forward< Arg >( arg) );
- }
-#endif
-
- void operator()( Arg arg)
- {
- BOOST_ASSERT( * this);
-
- impl_->resume( arg);
- }
-};
-
-template< typename Arg >
-void swap( push_coroutine< Arg > & l, push_coroutine< Arg > & r) BOOST_NOEXCEPT
-{ l.swap( r); }
-#if 0
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::iterator
-range_begin( push_coroutine< Arg > & c)
-{ return typename push_coroutine< Arg >::iterator( & c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::const_iterator
-range_begin( push_coroutine< Arg > const& c)
-{ return typename push_coroutine< Arg >::const_iterator( & c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::iterator
-range_end( push_coroutine< Arg > &)
-{ return typename push_coroutine< Arg >::iterator(); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::const_iterator
-range_end( push_coroutine< Arg > const&)
-{ return typename push_coroutine< Arg >::const_iterator(); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::iterator
-begin( push_coroutine< Arg > & c)
-{ return boost::begin( c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::iterator
-end( push_coroutine< Arg > & c)
-{ return boost::end( c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::const_iterator
-begin( push_coroutine< Arg > const& c)
-{ return boost::const_begin( c); }
-
-template< typename Arg >
-inline
-typename push_coroutine< Arg >::const_iterator
-end( push_coroutine< Arg > const& c)
-{ return boost::const_end( c); }
-
-}
-
-template< typename Arg >
-struct range_mutable_iterator< coroutines::coroutine< Arg > >
-{ typedef typename coroutines::coroutine< Arg >::iterator type; };
-
-template< typename Arg >
-struct range_const_iterator< coroutines::coroutine< Arg > >
-{ typedef typename coroutines::coroutine< Arg >::const_iterator type; };
-#endif
-}
-
-#ifdef BOOST_HAS_ABI_HEADERS
-# include BOOST_ABI_SUFFIX
-#endif
-
-#endif // BOOST_COROUTINES_V2_PUSH_COROUTINE_H
Modified: branches/release/libs/coroutine/build/Jamfile.v2
==============================================================================
--- branches/release/libs/coroutine/build/Jamfile.v2 Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/build/Jamfile.v2 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -18,11 +18,11 @@
<toolset>gcc-4.7,<segmented-stacks>on:<linkflags>"-static-libgcc"
<toolset>gcc-4.8,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>gcc-4.8,<segmented-stacks>on:<linkflags>"-static-libgcc"
- <link>static
- <threading>multi
- : source-location ../src
+ <link>shared:<define>BOOST_COROUTINES_DYN_LINK=1
+ <define>BOOST_COROUTINES_SOURCE
: usage-requirements
- <link>shared:<define>BOOST_COROUTINES_DYN_LINK=1
+ <link>shared:<define>BOOST_COROUTINES_DYN_LINK=1
+ : source-location ../src
;
alias allocator_sources
@@ -40,13 +40,12 @@
: detail/standard_stack_allocator_posix.cpp
;
-explicit yield_sources ;
+explicit allocator_sources ;
lib boost_coroutine
: allocator_sources
detail/coroutine_context.cpp
- : <link>shared:<define>BOOST_COROUTINES_DYN_LINK=1
- :
+ exceptions.cpp
: <link>shared:<library>../../context/build//boost_context
;
Modified: branches/release/libs/coroutine/doc/coro.qbk
==============================================================================
--- branches/release/libs/coroutine/doc/coro.qbk Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/doc/coro.qbk 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -19,6 +19,7 @@
]
+[def __boost_asio__ [*Boost.Asio]]
[def __boost_build__ [*Boost.Build]]
[def __boost_context__ [*Boost.Context]]
[def __boost_coroutine__ [*Boost.Coroutine]]
@@ -39,6 +40,8 @@
[def __ctx__ ['context]]
[def __coro__ ['coroutine]]
+[def __push_coro__ ['coroutine<>::push_type]]
+[def __pull_coro__ ['coroutine<>::pull_type]]
[def __coro_fn__ ['coroutine-function]]
[def __coros__ ['coroutines]]
[def __not_a_coro__ ['not-a-coroutine]]
@@ -66,6 +69,10 @@
[def __getline__ ['std::getline()]]
[def __handle_read__ ['session::handle_read()]]
[def __io_service__ ['boost::asio::io_sevice]]
+[def __pull_coro_get__ ['boost::coroutines::coroutine<>::pull_type::get()]]
+[def __pull_coro_it__ ['boost::coroutines::coroutine<>::pull_type::iterator]]
+[def __pull_coro_op__ ['boost::coroutines::coroutine<>::pull_type::operator()]]
+[def __push_coro_op__ ['boost::coroutines::coroutine<>::push_type::operator()]]
[def __server__ ['server]]
[def __session__ ['session]]
[def __stack_context__ ['boost::coroutines::stack_context]]
@@ -74,9 +81,11 @@
[def __tie__ ['boost::tie]]
[def __tuple__ ['boost::tuple<>]]
[def __underflow__ ['stream_buf::underflow()]]
+[def __yield_context__ ['boost::asio::yield_context]]
[include overview.qbk]
[include intro.qbk]
+[include motivation.qbk]
[include coroutine.qbk]
[include attributes.qbk]
[include stack.qbk]
Modified: branches/release/libs/coroutine/doc/coroutine.qbk
==============================================================================
--- branches/release/libs/coroutine/doc/coroutine.qbk Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/doc/coroutine.qbk 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -7,800 +7,10 @@
[section:coroutine Coroutine]
-Each instance of __coro__ has its own context of execution (CPU registers and
-stack space) or represents __not_a_coro__ (similar to __thread__).
-Objects of type __coro__ are moveable but not copyable and can be returned by a
-function.
+__boost_coroutine__ provides two interfaces - one with uni- and one with bidirectional
+data transfer (deprecated).
- boost::coroutines::coroutine< void() > f();
-
- void g()
- {
- boost::coroutines::coroutine< void() > c( f() );
- c();
- }
-
-[note __boost_move__ is used to emulate rvalue references.]
-
-
-[heading Creating a coroutine]
-
-A new __coro__ is created from a __coro_fn__ (function or functor) which will be
-executed in a new __ctx__ (CPU registers and stack space).
-
-[note __coro_fn__ is required to return ['void] and accept a reference of type
-__coro_caller__.]
-
-The template argument __signature__ determines the data-types transferred to
-__coro_fn__ and from __coro_fn__ by calling __coro_op__ and __coro_get__.
-
- typedef boost::coroutines::coroutine< int( std::string const&) > coro_t;
-
- // void f( boost::coroutine< std::string const&( int) > & ca)
- void f( coro_t::caller_type & ca)
- {
- ...
- // access argument
- std::string str( ca.get() );
- ...
- ca( 7);
- ...
- }
-
- std::string str;
- ...
- coro_t c( f);
- // pass argument
- c( str);
- // returned value
- int res = c.get();
-
-
-The __coro_fn__ is started at __coro__ construction (similar to __thread__)
-in a newly created __coro__ complete with registers, flags, stack and
-instruction pointer.
-If __coro_fn__ requires some arguments (types defined by __signature__)
-on start-up those parameters must be applied to the __coro__ constructor.
-A single arguments can be passed as it is:
-
- typedef boost::coroutines::coroutine< int( std::string const&) > coro_t;
-
- // void f( boost::coroutine< std::string const&( int) > & ca)
- void f( coro_t::caller_type & ca);
-
- std::string str("abc");
- coro_t c( f, str);
-
-
-For multiple arguments __args__ must be used (it is a typedef of __tuple__):
-
- typedef boost::coroutines::coroutine< int( int, std::string const&) > coro_t;
-
- // void f( boost::coroutine< boost::tuple< int, std::string const& >( int) > & ca)
- void f( coro_t::caller_type & ca);
-
- std::string str("abc");
- coro_t c( f, coro_t::arguments( 7, str) );
-
-
-[note The maximum number of arguments is limited to 10 (limit defined by
-__boost_tuple__).]
-
-[note Parameters bound with __bind__ to __coro_fn__ will not be part of the
-__coro_op__ signature.]
-
-__attrs__, an additional constructor argument of __coro__, defines the stack
-size, stack unwinding and floating-point preserving behaviour used for __ctx__
-construction.
-
-The __coro__ constructor uses the __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.
-
-
-[heading Calling a coroutine]
-
-The execution control is transferred to __coro__ at construction (__coro_fn__
-entered) - when control should be returned to the original calling routine,
-invoke __coro_op__ on the first argument of type __coro_caller__ inside
-__coro_fn__. __coro_caller__ is a typedef of __coro__ with an inverted
-__signature__. Inverted __signature__ means that the return type becomes an
-argument and vice versa. Multiple arguments are wrapped into __tuple__.
-
- void f( boost::coroutines::coroutine< std::string const&( int) & ca);
- boost::coroutines::coroutine< int( std::string const&) > c1( f);
-
- void g( boost::coroutines::coroutine< boost::tuple< X, Y >( int) & ca);
- boost::coroutines::coroutine< int( X, X) > c2( g);
-
-
-The current coroutine information (registers, flags, and stack and instruction
-pointer) is saved and the original context information is restored. Calling
-__coro_op__ resumes execution in the coroutine after saving the new state of the
-original routine.
-
- typedef boost::coroutines::coroutine< void() > coro_t;
-
- // void fn( boost::coroutines::coroutine< void() > & ca, int j)
- void fn( coro_t::caller_type & ca, int j)
- {
- for( int i = 0; i < j; ++i)
- {
- std::cout << "fn(): local variable i == " << i << std::endl;
-
- // save current coroutine
- // value of local variable is preserved
- // transfer execution control back to main()
- ca();
-
- // coroutine<>::operator()() was called
- // execution control transferred back from main()
- }
- }
-
- int main( int argc, char * argv[])
- {
- // bind parameter '7' to coroutine-fn
- coro_t c( boost::bind( fn, _1, 7) );
-
- std::cout << "main() starts coroutine c" << std::endl;
-
- while ( c)
- {
- std::cout << "main() calls coroutine c" << std::endl;
- // execution control is transferred to c
- c();
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main() starts coroutine c
- fn(): local variable i == 0
- main() calls coroutine c
- fn(): local variable i == 1
- main() calls coroutine c
- fn(): local variable i == 2
- main() calls coroutine c
- fn(): local variable i == 3
- main() calls coroutine c
- fn(): local variable i == 4
- main() calls coroutine c
- fn(): local variable i == 5
- main() calls coroutine c
- fn(): local variable i == 6
- main() calls coroutine c
- Done
-
-[warning Calling __coro_op__ from inside the [_same] coroutine results in
-undefined behaviour.]
-
-
-[heading Transfer of data]
-
-__signature__, the template argument of __coro__, defines the types transferred
-to and returned from the __coro_fn__, e.g. it determines the signature of
-__coro_op__ and the return-type of __coro_get__.
-
-[note __coro_caller__ is not part of __signature__ and __coro_fn__ is required
-to return void and accept __coro_caller__ as argument.]
-
-__coro_op__ accepts arguments as defined in __signature__ and returns a
-reference to __coro__. The arguments passed to __coro_op__, in one coroutine,
-is returned (as a __tuple__) by __coro_get__ in the other coroutine.
-If __coro__ is constructed and arguments are passed to the constructor, the
-__coro_fn__ will be entered and the arguments are accessed thorough __coro_get__
-in __coro_fn__ on entry.
-
-The value given to __coro_op__ of __coro_caller__, in one coroutine, is returned by
-__coro_get__ in the other routine.
-
- typedef boost::coroutines::coroutine< int( int) > coro_t;
-
- // void fn( boost::coroutines::coroutine< int( int) > & ca)
- void fn( coro_t::caller_type & ca)
- {
- // access the integer argument given to coroutine ctor
- int i = ca.get();
- std::cout << "fn(): local variable i == " << i << std::endl;
-
- // save current coroutine context and
- // transfer execution control back to caller
- // pass content of variable 'i' to caller
- // after execution control is returned back coroutine<>::operator()
- // returns and the transferred integer s accessed via coroutine<>::get()
- i = ca( i).get();
-
- // i == 10 because c( 10) in main()
- std::cout << "fn(): local variable i == " << i << std::endl;
- ca( i);
- }
-
- int main( int argc, char * argv[])
- {
- std::cout << "main(): call coroutine c" << std::endl;
- coro_t c( fn, 7);
-
- int x = c.get();
- std::cout << "main(): transferred value: " << x << std::endl;
-
- x = c( 10).get();
- std::cout << "main(): transferred value: " << x << std::endl;
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main(): call coroutine c
- fn(): local variable i == 7
- main(): transferred value: 7
- fn(): local variable i == 10
- main(): transferred value: 10
- Done
-
-
-[heading __coro_fn__ with multiple arguments]
-
-If __coro_fn__ has more than one argument __coro_op__ has the same size of
-arguments and __coro_get__ from __coro_caller__ returns a __tuple__ corresponding
-to the arguments of __signature__. __tie__ helps to access the values stored in
-the __tuple__ returned by __coro_get__.
-
- typedef boost::coroutines::coroutine< int(int,int) > coro_t;
-
- // void fn( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca)
- void fn( coro_t::caller_type & ca)
- {
- int a, b;
- boost::tie( a, b) = ca.get();
- boost::tie( a, b) = ca( a + b).get();
- ca( a + b);
- }
-
- int main( int argc, char * argv[])
- {
- std::cout << "main(): call coroutine c" << std::endl;
- coro_t coro( fn, coro_t::arguments( 3, 7) );
-
- int res = coro.get();
- std::cout << "main(): 3 + 7 == " << res << std::endl;
-
- res = coro( 5, 7).get();
- std::cout << "main(): 5 + 7 == " << res << std::endl;
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main(): call coroutine c
- main(): 3 + 7 == 10
- main(): 5 + 7 == 12
- Done
-
-
-[heading Transfer of pointers and references]
-
-You can transfer references and pointers from and to coroutines but as usual
-you must take care (scope, no re-assignment of const references etc.).
-In the following code `x` points to `local` which is allocated on stack of
-`c`. When `c` goes out of scope the stack becomes deallocated. Using `x`
-after `c` is gone will fail!
-
- struct X
- {
- void g();
- };
-
- typedef boost::coroutines::coroutine< X*() > coro_t;
-
- // void fn( boost::coroutines::coroutine< void( X*) > & ca)
- void fn( coro_t::caller_t & ca) {
- X local;
- ca( & local);
- }
-
- int main() {
- X * x = 0;
- {
- coro_t c( fn);
- x = c.get(); // let x point to X on stack owned by c
- // stack gets unwound -> X will be destructed
- }
- x->g(); // segmentation fault!
- return EXIT_SUCCESS;
- }
-
-
-[heading Range iterators]
-
-__boost_coroutine__ provides output- and input-iterators using __boost_range__.
-`coroutine< T() >` can be used via output-iterators using __begin__ and __end__.
-
- typedef boost::coroutines::coroutine< int() > coro_t;
- typedef boost::range_iterator< coro_t >::type iterator_t;
-
- // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent)
- void power( coro_t::caller_type & ca, int number, int exponent)
- {
- int counter = 0;
- int result = 1;
- while ( counter++ < exponent)
- {
- result = result * number;
- ca( result);
- }
- }
-
- int main()
- {
- coro_t c( boost::bind( power, _1, 2, 8) );
- iterator_t e( boost::end( c) );
- for ( iterator_t i( boost::begin( c) ); i != e; ++i)
- std::cout << * i << " ";
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- 2 4 8 16 32 64 128 256
- Done
-
-`BOOST_FOREACH` can be used to iterate over the coroutine range too.
-
- typedef boost::coroutines::coroutine< int() > coro_t;
- typedef boost::range_iterator< coro_t >::type iterator_t;
-
- // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent)
- void power( coro_t::caller_type & ca, int number, int exponent)
- {
- int counter = 0;
- int result = 1;
- while ( counter++ < exponent)
- {
- result = result * number;
- ca( result);
- }
- }
-
- int main()
- {
- coro_t c( boost::bind( power, _1, 2, 8) );
- BOOST_FOREACH( int i, c)
- { std::cout << i << " "; }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- 2 4 8 16 32 64 128 256
- Done
-
-
-Input iterators are created from coroutines of type `coroutine< void( T) >`.
-
-
-
-[heading Exit a __coro_fn__]
-
-__coro_fn__ is exited with a simple return statement jumping back to the calling
-routine. The __coro__ becomes complete, e.g. __coro_bool__ will return 'false'.
-
- typedef boost::coroutines::coroutine< int(int,int) > coro_t;
-
- // void power( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca, int number, int exponent)
- void fn( coro_t::caller_type & ca)
- {
- int a, b;
- boost::tie( a, b) = ca.get();
- boost::tie( a, b) = ca( a + b).get();
- ca( a + b);
- }
-
- int main( int argc, char * argv[])
- {
- std::cout << "main(): call coroutine c" << std::endl;
- coro_t coro( fn, coro_t::arguments( 3, 7) );
-
- BOOST_ASSERT( coro);
- int res = coro.get();
- std::cout << "main(): 3 + 7 == " << res << std::endl;
-
- res = coro( 5, 7).get();
- BOOST_ASSERT( ! coro);
- std::cout << "main(): 5 + 7 == " << res << std::endl;
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- main(): call coroutine c
- main(): 3 + 7 == 10
- main(): 5 + 7 == 12
- Done
-
-[important After returning from __coro_fn__ the __coro__ is complete (can not
-resumed with __coro_op__).]
-
-
-[heading Exceptions in __coro_fn__]
-
-An exception thrown inside __coro_fn__ will transferred via exception-pointer
-(see __boost_exception__ for details) and re-thrown by constructor or
-__coro_op__.
-
- typedef boost::coroutines::coroutine< void() > coro_t;
-
- // void fn( boost::coroutines::coroutine< void() > & ca)
- void fn( coro_t::caller_type & ca)
- {
- ca();
- throw std::runtime_error("abc");
- }
-
- int main( int argc, char * argv[])
- {
- coro_t c( f);
- try
- {
- c();
- }
- catch ( std::exception const& e)
- {
- std::cout << "exception catched:" << e.what() << std::endl;
- return EXIT_FAILURE;
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
- }
-
- output:
- exception catched: abc
-
-[important Code executed by coroutine must not prevent the propagation of the
-__forced_unwind__ exception. Absorbing that exception will cause stack
-unwinding to fail. Thus, any code that catches all exceptions must re-throw the
-pending exception.]
-
- try
- {
- // code that might throw
- }
- catch( forced_unwind)
- {
- throw;
- }
- catch(...)
- {
- // possibly not re-throw pending exception
- }
-
-
-[heading Stack unwinding]
-
-Sometimes it is necessary to unwind the stack of an unfinished coroutine to
-destroy local stack variables so they can release allocated resources (RAII
-pattern). The third argument of the coroutine constructor, `do_unwind`,
-indicates whether the destructor should unwind the stack (stack is unwound by
-default).
-
-Stack unwinding assumes the following preconditions:
-
-* The coroutine is not __not_a_coro__
-* The coroutine is not complete
-* The coroutine is not running
-* The coroutine owns a stack
-
-After unwinding, a __coro__ is complete.
-
-
- typedef boost::coroutines::coroutine< void() > coro_t;
-
- struct X
- {
- X()
- { std::cout << "X()" << std::endl; }
-
- ~X()
- { std::cout << "~X()" << std::endl; }
- };
-
- // void fn( boost::coroutines::coroutine< void() > & ca)
- void fn( coro_t::caller_type & ca)
- {
- X x;
-
- for ( int = 0;; ++i)
- {
- std::cout << "fn(): " << i << std::endl;
- // transfer execution control back to main()
- ca();
- }
- }
-
- int main( int argc, char * argv[])
- {
- {
- coro_t c( fn,
- boost::coroutines::attributes(
- boost::ctx::default_stacksize(),
- boost::coroutines::stack_unwind) );
-
- c();
- c();
- c();
- c();
- c();
-
- std::cout << "c is complete: " << std::boolalpha << c.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
- c is complete: false
- ~X()
- Done
-
-[important You must not swallow __forced_unwind__ exceptions!]
-
-
-[heading FPU preserving]
-
-Some applications do not use floating-point registers and can disable preserving
-fpu registers for performance reasons.
-
-[note According to the calling convention the FPU registers are preserved by default.]
-
-
-[section:coroutine Class `coroutine`]
-
- #include <boost/coroutine/coroutine.hpp>
-
- template< typename Signature >
- class coroutine;
-
- template<
- typename R,
- typename ArgTypes...
- >
- class coroutine< R ( ArgTypes...) >
- {
- public:
- typedef unspec-type caller_type;
- typedef unspec-type arguments;
-
- coroutine();
-
- template<
- typename Fn,
- typename StackAllocator = stack_allocator,
- typename Allocator = std::allocator< coroutine >
- >
- coroutine( Fn fn, attributes const& attr = attributes(),
- StackAllocator const& stack_alloc = StackAllocator(),
- Allocator const& alloc = Allocator() );
-
- template<
- typename Fn,
- typename StackAllocator = stack_allocator,
- typename Allocator = std::allocator< coroutine >
- >
- coroutine( Fn fn, arguments const& args,
- attributes const& attr = attributes(),
- StackAllocator const& stack_alloc = StackAllocator(),
- Allocator const& alloc = Allocator() );
-
- template<
- typename Fn,
- typename StackAllocator = stack_allocator,
- typename Allocator = std::allocator< coroutine >
- >
- coroutine( Fn && fn, attributes const& attr = attributes(),
- StackAllocator stack_alloc = StackAllocator(),
- Allocator const& alloc = Allocator() );
-
- template<
- typename Fn,
- typename StackAllocator = stack_allocator,
- typename Allocator = std::allocator< coroutine >
- >
- coroutine( Fn && fn arguments const& args,
- attributes const& attr = attributes(),
- StackAllocator stack_alloc = StackAllocator(),
- Allocator const& alloc = Allocator() );
-
- coroutine( coroutine && other);
-
- coroutine & operator=( coroutine && other);
-
- operator unspecified-bool-type() const;
-
- bool operator!() const;
-
- void swap( coroutine & other);
-
- bool empty() const;
-
- coroutine & operator()(A0 a0, ..., A9 a9);
-
- R get() const;
- };
-
- template< typename Signature >
- void swap( coroutine< Signature > & l, coroutine< Signature > & r);
-
- template< typename T >
- range_iterator< coroutine< T() > >::type begin( coroutine< T() > &);
- template< typename T >
- range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &);
-
- template< typename T >
- range_iterator< coroutine< T() > >::type end( coroutine< T() > &);
- template< typename T >
- range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &);
-
-[heading `coroutine()`]
-[variablelist
-[[Effects:] [Creates a coroutine representing __not_a_coro__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `template< typename Fn, typename StackAllocator, typename Allocator >
- coroutine( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
-[variablelist
-[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
-when ! is_stack_unbound().]]
-[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
-determines stack clean-up and preserving floating-point registers.
-For allocating/deallocating the stack `stack_alloc` is used and internal
-data are allocated by Allocator.]]
-]
-
-[heading `template< typename Fn, typename StackAllocator, typename Allocator >
- coroutine( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
-[variablelist
-[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
-when ! is_stack_unbound().]]
-[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
-determines stack clean-up and preserving floating-point registers.
-For allocating/deallocating the stack `stack_alloc` is used and internal
-data are allocated by Allocator.]]
-]
-
-[heading `coroutine( coroutine && other)`]
-[variablelist
-[[Effects:] [Moves the internal data of `other` to `*this`.
-`other` becomes __not_a_coro__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `coroutine & operator=( coroutine && other)`]
-[variablelist
-[[Effects:] [Destroys the internal data of `*this` and moves the
-internal data of `other` to `*this`. `other` becomes __not_a_coro__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `operator unspecified-bool-type() const`]
-[variablelist
-[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
-has returned (completed), the function returns false. Otherwise true.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool operator!() const`]
-[variablelist
-[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
-has returned (completed), the function returns true. Otherwise false.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `bool empty()`]
-[variablelist
-[[Returns:] [If `*this` refers to __not_a_coro__, the function returns true.
-Otherwise false.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `coroutine<> & operator()(A0 a0, A9 a9)`]
-[variablelist
-[[Preconditions:] [operator unspecified-bool-type() returns true for `*this`.]
-[[Effects:] [Execution control is transferred to __coro_fn__ and the arguments
-`a0`,..., are passed to the coroutine-function.]]
-[[Throws:] [Exceptions thrown inside __coro_fn__.]]
-]
-
-[heading `R get()()`]
-[variablelist
-[[Preconditions:] [`*this` is not a __not_a_coro__, `! is_complete()`.]]
-[[Returns:] [Returns data transferred from coroutine-function via __coro_op__
-of __coro_caller__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `void swap( coroutine & other)`]
-[variablelist
-[[Effects:] [Swaps the internal data from `*this` with the values
-of `other`.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading `T caller_type::operator()( R)`]
-[variablelist
-[[Effects:] [Gives execution control back to calling context by returning
-a value of type R. The return type of this function is a __tuple__ containing
-the arguments passed to __coro_op__.]]
-[[Throws:] [Nothing.]]
-]
-
-[heading Non-member function `swap()`]
-
- template< typename Signature >
- void swap( coroutine< Signature > & l, coroutine< Signature > & r);
-
-[variablelist
-[[Effects:] [As if 'l.swap( r)'.]]
-]
-
-[heading Non-member function `begin( coroutine< T() > &)`]
- template< typename T >
- range_iterator< coroutine< T() > >::type begin( coroutine< T() > &);
-
-[variablelist
-[[Returns:] [Returns a range-iterator (input-iterator).]]
-]
-
-[heading Non-member function `begin( coroutine< void(T) > &)`]
- template< typename T >
- range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &);
-
-[variablelist
-[[Returns:] [Returns a range-iterator (output-iterator).]]
-]
-
-[heading Non-member function `end( coroutine< T() > &)`]
- template< typename T >
- range_iterator< coroutine< T() > >::type end( coroutine< T() > &);
-
-[variablelist
-[[Returns:] [Returns a end range-iterator (input-iterator).]]
-]
-
-[heading Non-member function `end( coroutine< void(T) > &)`]
- template< typename T >
- range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &);
-
-[variablelist
-[[Returns:] [Returns a end range-iterator (output-iterator).]]
-]
-
-[endsect]
+[include unidirect.qbk]
+[include old.qbk]
[endsect]
Copied: branches/release/libs/coroutine/doc/images/fringe.png (from r85162, trunk/libs/coroutine/doc/images/fringe.png)
==============================================================================
Binary file (source and/or target). No diff available.
Modified: branches/release/libs/coroutine/doc/intro.qbk
==============================================================================
--- branches/release/libs/coroutine/doc/intro.qbk Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/doc/intro.qbk 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -9,17 +9,18 @@
[heading Definition]
-In computer science routines are defined as a sequence of operations.
-The execution of routines form a parent-child relationship and the child
-terminates always before the parent.
-Coroutines are a generalization of routines.
-The principal difference between coroutines and routines is that a coroutine
-enables explicit suspend and resume of their progress via additional operations by
-preserving local state, e.g. a coroutine is a kind of continuation.
-A continuation is a object representing a suspended execution (registers,
-stack). Each coroutine has its own stack and local variables, sub-routine calls
-etc.
-In this sense coroutines are (actually) a language concept.
+In computer science routines are defined as a sequence of operations. The
+execution of routines forms a parent-child relationship and the child terminates
+always before the parent. Coroutines (the term was introduced by Melvin
+Conway [footnote Conway, Melvin E.. "Design of a Separable Transition-Diagram Compiler".
+Commun. ACM, Volume 6 Issue 7, July 1963, Articale No. 7]),
+are a generalization of routines (Donald Knuth [footnote Knuth, Donald Ervin (1997).
+"Fundamental Algorithms. The Art of Computer Programming 1", (3rd ed.)].
+The principal difference between coroutines and routines
+is that a coroutine enables explicit suspend and resume of its progress via
+additional operations by preserving execution state and thus provides an
+[*enhanced control flow] (maintaining the execution context).
+
[heading How it works]
@@ -41,8 +42,6 @@
The registers of the newly activated coroutine must be restored from its
associated control-block before it can continue with their work.
-[$../../../../libs/coroutine/doc/images/foo_bar_seq.png [align center]]
-
The context switch requires no system privileges and provides cooperative
multitasking on the level of language. Coroutines provide quasi parallelism.
When a program is supposed to do several things at the same time, coroutines
@@ -52,284 +51,57 @@
function, such as traversal of binary trees (see example 'same fringe').
-[heading Example: asio::io_stream with std::stream]
+[heading characteristics]
+Characteristics [footnote Moura, Ana Lucia De and Ierusalimschy, Roberto.
+"Revisiting coroutines". ACM Trans. Program. Lang. Syst., Volume 31 Issue 2,
+February 2009, Article No. 6] of a coroutine are:
+
+* values of local data persist between successive calls (context switches)
+* execution is suspended as control leaves coroutine and resumed at certain time later
+* symmetric or asymmetric control-transfer mechanism
+* first-class object (can be passed as argument, returned by procedures,
+ stored in a data structure to be used later or freely manipulated by
+ the developer)
+* stackful or stackless
+
+Coroutines are useful in simulation, artificial intelligence, concurrent
+programming, text processing and data manipulation, supporting
+the implementation of components such as cooperative tasks (fibers), iterators,
+generators, infinite lists, pipes etc.
+
+
+[heading execution-transfer mechanism]
+Two categories of coroutines exist: symmetric and asymmetric coroutines.
+A symmetric coroutine transfers the execution control only via one operation.
+The target coroutine must be explicitly specified in the transfer operation.
+Asymmetric coroutines provide two transfer operations:
+the ['suspend]-operation returns to the invoker by preserving the
+execution context and the ['resume]-operation restores the execution
+context, e.g. re-enters the coroutine at the same point as it was suspended
+before.
+
+[$../../../../libs/coroutine/doc/images/foo_bar_seq.png [align center]]
+
+Both concepts are equivalent and a coroutine library can provide either
+symmetric or asymmetric coroutines.
-This section demonstrates how stackfull coroutines help to use standard C++
-IO-streams together with IO-demultiplexer like __io_service__ (using
-non-blocking IO).
-
- int main( int argc, char * argv[])
- {
- ...
- {
- boost::asio::io_service io_service;
- io_service.post(
- boost::bind(
- & server::start,
- server::create(
- io_service, port) ) );
- io_service.run();
- }
- ...
- }
-
-
-__server__ accepts connection-requests made by clients, creates for each new
-connection an instance of type __session__ and invokes __start__ on it.
-
- class server : public boost::enable_shared_from_this< server >
- {
- private:
- boost::asio::io_service & io_service_;
- boost::asio::ip::tcp::acceptor acceptor_;
-
- void handle_accept_( session * new_session, boost::system::error_code const& error)
- {
- if ( ! error)
- {
- // start asynchronous read
- new_session->start();
-
- // start asynchronous accept
- start();
- }
- }
-
- server( boost::asio::io_service & io_service, short port) :
- io_service_( io_service),
- acceptor_(
- io_service_,
- boost::asio::ip::tcp::endpoint( boost::asio::ip::tcp::v4(), port) )
- {}
-
- 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 start()
- {
- // create new session which gets started if asynchronous
- // accept completes
- session * new_session( new session( io_service_) );
- acceptor_.async_accept(
- new_session->socket(),
- boost::bind( & server::handle_accept_, this->shared_from_this(),
- new_session, boost::asio::placeholders::error) );
- }
- };
-
-
-Each __session__ communicates with the connected client and handles the
-requests.
-The application protocol in this example uses TCP-sockets as channel and
-'newline' to separate the messages in the byte stream.
-An application protocol is a set of rules for the order in which messages are
-exchanged.
-['std::istream] is used to extract the messages from the character stream .
-Message 'exit' terminates the session.
-
- class session : private boost::noncopyable
- {
- private:
- void handle_read_( coro_t::caller_type & self)
- {
- // create stream-buffer reading from socket
- inbuf buf( socket_);
- std::istream s( & buf);
-
- // messages are separated by 'newline'
- std::string msg;
- std::getline( s, msg);
- std::cout << msg << std::endl;
-
- // terminate session for message 'exit'
- // else do asynchronous read
- if ( "exit" == msg)
- io_service_.post(
- boost::bind(
- & session::destroy_, this) );
- else
- start();
- }
-
- void destroy_()
- { delete this; }
-
- boost::asio::io_service & io_service_;
- boost::asio::ip::tcp::socket socket_;
-
- public:
- session( boost::asio::io_service & io_service) :
- io_service_( io_service),
- socket_( io_service_)
- { std::cout << "service(): " << socket_.remote_endpoint() << std::endl; }
-
- ~session()
- { std::cout << "~service(): " << socket_.remote_endpoint() << std::endl; }
-
- boost::asio::ip::tcp::socket & socket()
- { return socket_; }
-
- void start()
- {
- // register on io_service for asynchronous read
- io_service_.async_read(
- socket_,
- boost::bind(
- & session::handle_read_, this->shared_from_this(), _1, _2) );
- }
- };
-
-
-Function __getline__ returns only if a 'newline' was read from the socket.
-Therefore the application will block until 'newline' is received by the socket.
-The stream-buffer used by the stream maintains an internal buffer which gets
-(re-)filled by its function __underflow__. __underflow__ does the
-read-operation on the socket. The C++ IO-streams framework does not provide an
-easy way to create an continuation which represents reading bytes from the socket.
-
-
-Coroutines help in this case to make the application non-blocking even if no
-'newline' was received.
-Class ['session] creates a coroutine which uses __handle_read__ as
-__coro_fn__. On a new created ['session] ['start()] called starting the
-coroutine. In the __coro_fn__ __handle_read__ the messages are received
-via __getline__ in a loop until 'exit' is delivered.
-
- class session : private boost::noncopyable
- {
- private:
- void handle_read_( coro_t::caller_type & ca)
- {
- // create stream-buffer with coroutine
- inbuf buf( socket_, coro_, ca);
- std::istream s( & buf);
-
- std::string msg;
- do
- {
- // read message
- // we not block if no newline was received yet
- std::getline( s, msg);
- std::cout << msg << std::endl;
- } while ( msg != "exit");
- io_service_.post(
- boost::bind(
- & session::destroy_, this) );
- }
-
- void destroy_()
- { delete this; }
-
- coro_t coro_;
- boost::asio::io_service & io_service_;
- boost::asio::ip::tcp::socket socket_;
-
- public:
- session( boost::asio::io_service & io_service) :
- coro_(),
- io_service_( io_service),
- socket_( io_service_)
- { std::cout << "service(): " << socket_.remote_endpoint() << std::endl; }
-
- ~session()
- { std::cout << "~service(): " << socket_.remote_endpoint() << std::endl; }
-
- boost::asio::ip::tcp::socket & socket()
- { return socket_; }
-
- void start()
- {
- // create and start a coroutine
- // handle_read_() is used as coroutine-function
- coro_ = coro_t( boost::bind( & session::handle_read_, this, _1) );
- }
- };
-
-
-The stream-buffer is created with __coro_caller__ and handles suspend/resume of this
-code path depending on if bytes can be read from the socket.
-
- class inbuf : public std::streambuf,
- private boost::noncopyable
- {
- private:
- static const std::streamsize pb_size;
-
- enum
- { bf_size = 16 };
-
- int fetch_()
- {
- std::streamsize num = std::min(
- static_cast< std::streamsize >( gptr() - eback() ), pb_size);
-
- std::memmove(
- buffer_ + ( pb_size - num),
- gptr() - num, num);
-
- // read bytes from the socket into internal buffer 'buffer_'
- // make coro_t::operator() as callback, invoked if some
- // bytes are read into 'buffer_'
- s_.async_read_some(
- boost::asio::buffer( buffer_ + pb_size, bf_size - pb_size),
- boost::bind( & coro_t::operator(), & coro_, _1, _2) );
- // suspend this coroutine
- ca_();
-
- // coroutine was resumed by boost::asio::io_sevice
- boost::system::error_code ec;
- std::size_t n = 0;
-
- // check arguments
- boost::tie( ec, n) = ca_.get();
-
- // check if an error occurred
- if ( ec)
- {
- setg( 0, 0, 0);
- return -1;
- }
-
- setg( buffer_ + pb_size - num, buffer_ + pb_size, buffer_ + pb_size + n);
- return n;
- }
-
- boost::asio::ip::tcp::socket & s_;
- coro_t & coro_;
- coro_t::caller_type & ca_;
- char buffer_[bf_size];
-
- protected:
- virtual int underflow()
- {
- if ( gptr() < egptr() )
- return traits_type::to_int_type( * gptr() );
-
- if ( 0 > fetch_() )
- return traits_type::eof();
- else
- return traits_type::to_int_type( * gptr() );
- }
-
- public:
- inbuf(
- boost::asio::ip::tcp::socket & s,
- coro_t & coro,
- coro_t::caller_type & ca) :
- s_( s), coro_( coro), ca_( ca), buffer_()
- { setg( buffer_ + 4, buffer_ + 4, buffer_ + 4); }
- };
- const std::streamsize inbuf::pb_size = 4;
-
-
-__fetch__ uses __coro_op__ as callback for the asynchronous read-operation on the
-socket and suspends itself (['ca_()] jumps back to __start__). If some bytes are
-available in the socket receive buffer __io_service__ copies the bytes to the
-internal buffer ['buffer_] and invokes the callback which resumes the coroutine
-(['ca_()] returns).
+[heading stackfulness]
+In contrast to a stackless coroutine a stackful coroutine allows to suspend
+from nested stackframes. The execution resumes at exact the same point in the
+code as it was suspended before.
+With a stackless coroutine, only the top-level routine may be suspended. Any
+routine called by that top-level routine may not itself suspend. This prohibits
+providing suspend/resume operations in routines within a general-purpose library.
+
+[heading first-class continuation]
+A first-class continuation can be passed as an argument, returned by a
+function and stored in a data structure to be used later.
+In some implementations (for instance C# ['yield]) the continuation can
+not be directly accessed or directly manipulated.
+
+Without stackfulness and first-class semantics some useful execution control
+flows cannot be supported (for instance cooperative multitasking or
+checkpointing).
[endsect]
Copied: branches/release/libs/coroutine/doc/motivation.qbk (from r85162, trunk/libs/coroutine/doc/motivation.qbk)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/doc/motivation.qbk 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/doc/motivation.qbk)
@@ -0,0 +1,177 @@
+[/
+ 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:motivation Motivation]
+
+In order to support a broad range of execution control behaviour __push_coro__ and
+__pull_coro__ can be used to ['escape-and-reenter] loops, to ['escape-and-reenter]
+recursive computations and for ['cooperative] multitasking
+helping to solve problems in a much simpler and more elegant way than with only
+a single flow of control.
+
+
+[heading 'same fringe' problem]
+
+The advantages can be seen particularly clearly with the use of a recursive
+function, such as traversal of trees.
+If traversing two different trees in the same deterministic order produces the
+same list of leaf nodes, then both trees have the same fringe.
+
+[$../../../../libs/coroutine/doc/images/fringe.png [align center]]
+
+Both trees in the picture have the same fringe even though the structure of the
+trees is different.
+
+The same fringe problem could be solved using coroutines by iterating over the
+leaf nodes and comparing this sequence via \cpp{std::equal()}. The range of data
+values is generated by function ['traverse()] which recursively traverses the
+tree and passes each node's data value to its __push_coro__.
+__push_coro__ suspends the recursive computation and transfers the data value to
+the main execution context.
+__pull_coro_it__, created from __pull_coro__, steps over those data values and
+delivers them to ['std::equal()] for comparison. Each increment of __pull_coro_it__
+resumes ['traverse()]. Upon return from ['iterator::operator++()], either
+a new data value is available, or tree traversal is finished (iterator is
+invalidated).
+
+ struct node{
+ typedef std::shared_ptr<node> ptr_t;
+
+ // Each tree node has an optional left subtree,
+ // an optional right subtree and a value of its own.
+ // The value is considered to be between the left
+ // subtree and the right.
+ ptr_t left,right;
+ std::string value;
+
+ // construct leaf
+ node(const std::string& v):
+ left(),right(),value(v)
+ {}
+ // construct nonleaf
+ node(ptr_t l,const std::string& v,ptr_t r):
+ left(l),right(r),value(v)
+ {}
+
+ static ptr_t create(const std::string& v){
+ return ptr_t(new node(v));
+ }
+
+ static ptr_t create(ptr_t l,const std::string& v,ptr_t r){
+ return ptr_t(new node(l,v,r));
+ }
+ };
+
+ node::ptr_t create_left_tree_from(const std::string& root){
+ /* --------
+ root
+ / \
+ b e
+ / \
+ a c
+ -------- */
+ return node::create(
+ node::create(
+ node::create("a"),
+ "b",
+ node::create("c")),
+ root,
+ node::create("e"));
+ }
+
+ node::ptr_t create_right_tree_from(const std::string& root){
+ /* --------
+ root
+ / \
+ a d
+ / \
+ c e
+ -------- */
+ return node::create(
+ node::create("a"),
+ root,
+ node::create(
+ node::create("c"),
+ "d",
+ node::create("e")));
+ }
+
+ // recursively walk the tree, delivering values in order
+ void traverse(node::ptr_t n,
+ boost::coroutines::coroutine<std::string>::push_type& out){
+ if(n->left) traverse(n->left,out);
+ out(n->value);
+ if(n->right) traverse(n->right,out);
+ }
+
+ // evaluation
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out){
+ traverse(left_d,out);
+ });
+
+ node::ptr_t right_b(create_right_tree_from("b"));
+ boost::coroutines::coroutine<std::string>::pull_type right_b_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out){
+ traverse(right_b,out);
+ });
+
+ std::cout << "left tree from d == right tree from b? "
+ << std::boolalpha
+ << std::equal(std::begin(left_d_reader),
+ std::end(left_d_reader),
+ std::begin(right_b_reader))
+ << std::endl;
+ }
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out){
+ traverse(left_d,out);
+ });
+
+ node::ptr_t right_x(create_right_tree_from("x"));
+ boost::coroutines::coroutine<std::string>::pull_type right_x_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out){
+ traverse(right_x,out);
+ });
+
+ std::cout << "left tree from d == right tree from x? "
+ << std::boolalpha
+ << std::equal(std::begin(left_d_reader),
+ std::end(left_d_reader),
+ std::begin(right_x_reader))
+ << std::endl;
+ }
+ std::cout << "Done" << std::endl;
+
+ output:
+ left tree from d == right tree from b? true
+ left tree from d == right tree from x? false
+ Done
+
+
+[heading asynchronous operations with boost.asio]
+
+In the past the code using asio's ['asynchronous operations] was scattered by callbacks.
+__boost_asio__ provides with its new ['asynchronous result] feature a new way to simplify the
+code and make it easier to read.
+__yield_context__ uses internally __boost_coroutine__:
+
+ void echo(boost::asio::ip::tcp::socket& socket,boost::asio::yield_context yield){
+ char data[128];
+ // read asynchronous data from socket
+ // execution context will be suspended until
+ // some bytes are read from socket
+ std::size_t n=socket.async_read_some(boost::asio::buffer(data),yield);
+ // write some bytes asynchronously
+ boost::asio::async_write(socket,boost::asio::buffer(data,n),yield);
+ }
+
+[endsect]
Copied: branches/release/libs/coroutine/doc/old.qbk (from r85162, trunk/libs/coroutine/doc/old.qbk)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/doc/old.qbk 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/doc/old.qbk)
@@ -0,0 +1,809 @@
+[/
+ 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:old Bidirectional coroutine (['deprecated])]
+
+[note This interface is deprecated but can be used by compiling the code with
+compiler flag BOOST_COROUTINES_OLD.]
+
+Each instance of __coro__ has its own context of execution (CPU registers and
+stack space) or represents __not_a_coro__ (similar to __thread__).
+Objects of type __coro__ are moveable but not copyable and can be returned by a
+function.
+
+ boost::coroutines::coroutine< void() > f();
+
+ void g()
+ {
+ boost::coroutines::coroutine< void() > c( f() );
+ c();
+ }
+
+[note __boost_move__ is used to emulate rvalue references.]
+
+
+[heading Creating a coroutine]
+
+A new __coro__ is created from a __coro_fn__ (function or functor) which will be
+executed in a new __ctx__ (CPU registers and stack space).
+
+[note __coro_fn__ is required to return ['void] and accept a reference of type
+__coro_caller__.]
+
+The template argument __signature__ determines the data-types transferred to
+__coro_fn__ and from __coro_fn__ by calling __coro_op__ and __coro_get__.
+
+ typedef boost::coroutines::coroutine< int( std::string const&) > coro_t;
+
+ // void f( boost::coroutine< std::string const&( int) > & ca)
+ void f( coro_t::caller_type & ca)
+ {
+ ...
+ // access argument
+ std::string str( ca.get() );
+ ...
+ ca( 7);
+ ...
+ }
+
+ std::string str;
+ ...
+ coro_t c( f);
+ // pass argument
+ c( str);
+ // returned value
+ int res = c.get();
+
+
+The __coro_fn__ is started at __coro__ construction (similar to __thread__)
+in a newly created __coro__ complete with registers, flags, stack and
+instruction pointer.
+If __coro_fn__ requires some arguments (types defined by __signature__)
+on start-up those parameters must be applied to the __coro__ constructor.
+A single arguments can be passed as it is:
+
+ typedef boost::coroutines::coroutine< int( std::string const&) > coro_t;
+
+ // void f( boost::coroutine< std::string const&( int) > & ca)
+ void f( coro_t::caller_type & ca);
+
+ std::string str("abc");
+ coro_t c( f, str);
+
+
+For multiple arguments __args__ must be used (it is a typedef of __tuple__):
+
+ typedef boost::coroutines::coroutine< int( int, std::string const&) > coro_t;
+
+ // void f( boost::coroutine< boost::tuple< int, std::string const& >( int) > & ca)
+ void f( coro_t::caller_type & ca);
+
+ std::string str("abc");
+ coro_t c( f, coro_t::arguments( 7, str) );
+
+
+[note The maximum number of arguments is limited to 10 (limit defined by
+__boost_tuple__).]
+
+[note Parameters bound with __bind__ to __coro_fn__ will not be part of the
+__coro_op__ signature.]
+
+__attrs__, an additional constructor argument of __coro__, defines the stack
+size, stack unwinding and floating-point preserving behaviour used for __ctx__
+construction.
+
+The __coro__ constructor uses the __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.
+
+
+[heading Calling a coroutine]
+
+The execution control is transferred to __coro__ at construction (__coro_fn__
+entered) - when control should be returned to the original calling routine,
+invoke __coro_op__ on the first argument of type __coro_caller__ inside
+__coro_fn__. __coro_caller__ is a typedef of __coro__ with an inverted
+__signature__. Inverted __signature__ means that the return type becomes an
+argument and vice versa. Multiple arguments are wrapped into __tuple__.
+
+ void f( boost::coroutines::coroutine< std::string const&( int) & ca);
+ boost::coroutines::coroutine< int( std::string const&) > c1( f);
+
+ void g( boost::coroutines::coroutine< boost::tuple< X, Y >( int) & ca);
+ boost::coroutines::coroutine< int( X, X) > c2( g);
+
+
+The current coroutine information (registers, flags, and stack and instruction
+pointer) is saved and the original context information is restored. Calling
+__coro_op__ resumes execution in the coroutine after saving the new state of the
+original routine.
+
+ typedef boost::coroutines::coroutine< void() > coro_t;
+
+ // void fn( boost::coroutines::coroutine< void() > & ca, int j)
+ void fn( coro_t::caller_type & ca, int j)
+ {
+ for( int i = 0; i < j; ++i)
+ {
+ std::cout << "fn(): local variable i == " << i << std::endl;
+
+ // save current coroutine
+ // value of local variable is preserved
+ // transfer execution control back to main()
+ ca();
+
+ // coroutine<>::operator()() was called
+ // execution control transferred back from main()
+ }
+ }
+
+ int main( int argc, char * argv[])
+ {
+ // bind parameter '7' to coroutine-fn
+ coro_t c( boost::bind( fn, _1, 7) );
+
+ std::cout << "main() starts coroutine c" << std::endl;
+
+ while ( c)
+ {
+ std::cout << "main() calls coroutine c" << std::endl;
+ // execution control is transferred to c
+ c();
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main() starts coroutine c
+ fn(): local variable i == 0
+ main() calls coroutine c
+ fn(): local variable i == 1
+ main() calls coroutine c
+ fn(): local variable i == 2
+ main() calls coroutine c
+ fn(): local variable i == 3
+ main() calls coroutine c
+ fn(): local variable i == 4
+ main() calls coroutine c
+ fn(): local variable i == 5
+ main() calls coroutine c
+ fn(): local variable i == 6
+ main() calls coroutine c
+ Done
+
+[warning Calling __coro_op__ from inside the [_same] coroutine results in
+undefined behaviour.]
+
+
+[heading Transfer of data]
+
+__signature__, the template argument of __coro__, defines the types transferred
+to and returned from the __coro_fn__, e.g. it determines the signature of
+__coro_op__ and the return-type of __coro_get__.
+
+[note __coro_caller__ is not part of __signature__ and __coro_fn__ is required
+to return void and accept __coro_caller__ as argument.]
+
+__coro_op__ accepts arguments as defined in __signature__ and returns a
+reference to __coro__. The arguments passed to __coro_op__, in one coroutine,
+is returned (as a __tuple__) by __coro_get__ in the other coroutine.
+If __coro__ is constructed and arguments are passed to the constructor, the
+__coro_fn__ will be entered and the arguments are accessed thorough __coro_get__
+in __coro_fn__ on entry.
+
+The value given to __coro_op__ of __coro_caller__, in one coroutine, is returned by
+__coro_get__ in the other routine.
+
+ typedef boost::coroutines::coroutine< int( int) > coro_t;
+
+ // void fn( boost::coroutines::coroutine< int( int) > & ca)
+ void fn( coro_t::caller_type & ca)
+ {
+ // access the integer argument given to coroutine ctor
+ int i = ca.get();
+ std::cout << "fn(): local variable i == " << i << std::endl;
+
+ // save current coroutine context and
+ // transfer execution control back to caller
+ // pass content of variable 'i' to caller
+ // after execution control is returned back coroutine<>::operator()
+ // returns and the transferred integer s accessed via coroutine<>::get()
+ i = ca( i).get();
+
+ // i == 10 because c( 10) in main()
+ std::cout << "fn(): local variable i == " << i << std::endl;
+ ca( i);
+ }
+
+ int main( int argc, char * argv[])
+ {
+ std::cout << "main(): call coroutine c" << std::endl;
+ coro_t c( fn, 7);
+
+ int x = c.get();
+ std::cout << "main(): transferred value: " << x << std::endl;
+
+ x = c( 10).get();
+ std::cout << "main(): transferred value: " << x << std::endl;
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main(): call coroutine c
+ fn(): local variable i == 7
+ main(): transferred value: 7
+ fn(): local variable i == 10
+ main(): transferred value: 10
+ Done
+
+
+[heading __coro_fn__ with multiple arguments]
+
+If __coro_fn__ has more than one argument __coro_op__ has the same size of
+arguments and __coro_get__ from __coro_caller__ returns a __tuple__ corresponding
+to the arguments of __signature__. __tie__ helps to access the values stored in
+the __tuple__ returned by __coro_get__.
+
+ typedef boost::coroutines::coroutine< int(int,int) > coro_t;
+
+ // void fn( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca)
+ void fn( coro_t::caller_type & ca)
+ {
+ int a, b;
+ boost::tie( a, b) = ca.get();
+ boost::tie( a, b) = ca( a + b).get();
+ ca( a + b);
+ }
+
+ int main( int argc, char * argv[])
+ {
+ std::cout << "main(): call coroutine c" << std::endl;
+ coro_t coro( fn, coro_t::arguments( 3, 7) );
+
+ int res = coro.get();
+ std::cout << "main(): 3 + 7 == " << res << std::endl;
+
+ res = coro( 5, 7).get();
+ std::cout << "main(): 5 + 7 == " << res << std::endl;
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main(): call coroutine c
+ main(): 3 + 7 == 10
+ main(): 5 + 7 == 12
+ Done
+
+
+[heading Transfer of pointers and references]
+
+You can transfer references and pointers from and to coroutines but as usual
+you must take care (scope, no re-assignment of const references etc.).
+In the following code `x` points to `local` which is allocated on stack of
+`c`. When `c` goes out of scope the stack becomes deallocated. Using `x`
+after `c` is gone will fail!
+
+ struct X
+ {
+ void g();
+ };
+
+ typedef boost::coroutines::coroutine< X*() > coro_t;
+
+ // void fn( boost::coroutines::coroutine< void( X*) > & ca)
+ void fn( coro_t::caller_t & ca) {
+ X local;
+ ca( & local);
+ }
+
+ int main() {
+ X * x = 0;
+ {
+ coro_t c( fn);
+ x = c.get(); // let x point to X on stack owned by c
+ // stack gets unwound -> X will be destructed
+ }
+ x->g(); // segmentation fault!
+ return EXIT_SUCCESS;
+ }
+
+
+[heading Range iterators]
+
+__boost_coroutine__ provides output- and input-iterators using __boost_range__.
+`coroutine< T() >` can be used via output-iterators using __begin__ and __end__.
+
+ typedef boost::coroutines::coroutine< int() > coro_t;
+ typedef boost::range_iterator< coro_t >::type iterator_t;
+
+ // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent)
+ void power( coro_t::caller_type & ca, int number, int exponent)
+ {
+ int counter = 0;
+ int result = 1;
+ while ( counter++ < exponent)
+ {
+ result = result * number;
+ ca( result);
+ }
+ }
+
+ int main()
+ {
+ coro_t c( boost::bind( power, _1, 2, 8) );
+ iterator_t e( boost::end( c) );
+ for ( iterator_t i( boost::begin( c) ); i != e; ++i)
+ std::cout << * i << " ";
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ 2 4 8 16 32 64 128 256
+ Done
+
+`BOOST_FOREACH` can be used to iterate over the coroutine range too.
+
+ typedef boost::coroutines::coroutine< int() > coro_t;
+ typedef boost::range_iterator< coro_t >::type iterator_t;
+
+ // void power( boost::coroutines::coroutine< void( int) > & ca, int number, int exponent)
+ void power( coro_t::caller_type & ca, int number, int exponent)
+ {
+ int counter = 0;
+ int result = 1;
+ while ( counter++ < exponent)
+ {
+ result = result * number;
+ ca( result);
+ }
+ }
+
+ int main()
+ {
+ coro_t c( boost::bind( power, _1, 2, 8) );
+ BOOST_FOREACH( int i, c)
+ { std::cout << i << " "; }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ 2 4 8 16 32 64 128 256
+ Done
+
+
+Input iterators are created from coroutines of type `coroutine< void( T) >`.
+
+
+
+[heading Exit a __coro_fn__]
+
+__coro_fn__ is exited with a simple return statement jumping back to the calling
+routine. The __coro__ becomes complete, e.g. __coro_bool__ will return 'false'.
+
+ typedef boost::coroutines::coroutine< int(int,int) > coro_t;
+
+ // void power( boost::coroutines::coroutine< boost::tuple< int, int >( int) > & ca, int number, int exponent)
+ void fn( coro_t::caller_type & ca)
+ {
+ int a, b;
+ boost::tie( a, b) = ca.get();
+ boost::tie( a, b) = ca( a + b).get();
+ ca( a + b);
+ }
+
+ int main( int argc, char * argv[])
+ {
+ std::cout << "main(): call coroutine c" << std::endl;
+ coro_t coro( fn, coro_t::arguments( 3, 7) );
+
+ BOOST_ASSERT( coro);
+ int res = coro.get();
+ std::cout << "main(): 3 + 7 == " << res << std::endl;
+
+ res = coro( 5, 7).get();
+ BOOST_ASSERT( ! coro);
+ std::cout << "main(): 5 + 7 == " << res << std::endl;
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ main(): call coroutine c
+ main(): 3 + 7 == 10
+ main(): 5 + 7 == 12
+ Done
+
+[important After returning from __coro_fn__ the __coro__ is complete (can not
+resumed with __coro_op__).]
+
+
+[heading Exceptions in __coro_fn__]
+
+An exception thrown inside __coro_fn__ will transferred via exception-pointer
+(see __boost_exception__ for details) and re-thrown by constructor or
+__coro_op__.
+
+ typedef boost::coroutines::coroutine< void() > coro_t;
+
+ // void fn( boost::coroutines::coroutine< void() > & ca)
+ void fn( coro_t::caller_type & ca)
+ {
+ ca();
+ throw std::runtime_error("abc");
+ }
+
+ int main( int argc, char * argv[])
+ {
+ coro_t c( f);
+ try
+ {
+ c();
+ }
+ catch ( std::exception const& e)
+ {
+ std::cout << "exception catched:" << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+ }
+
+ output:
+ exception catched: abc
+
+[important Code executed by coroutine must not prevent the propagation of the
+__forced_unwind__ exception. Absorbing that exception will cause stack
+unwinding to fail. Thus, any code that catches all exceptions must re-throw the
+pending exception.]
+
+ try
+ {
+ // code that might throw
+ }
+ catch( forced_unwind)
+ {
+ throw;
+ }
+ catch(...)
+ {
+ // possibly not re-throw pending exception
+ }
+
+
+[heading Stack unwinding]
+
+Sometimes it is necessary to unwind the stack of an unfinished coroutine to
+destroy local stack variables so they can release allocated resources (RAII
+pattern). The third argument of the coroutine constructor, `do_unwind`,
+indicates whether the destructor should unwind the stack (stack is unwound by
+default).
+
+Stack unwinding assumes the following preconditions:
+
+* The coroutine is not __not_a_coro__
+* The coroutine is not complete
+* The coroutine is not running
+* The coroutine owns a stack
+
+After unwinding, a __coro__ is complete.
+
+
+ typedef boost::coroutines::coroutine< void() > coro_t;
+
+ struct X
+ {
+ X()
+ { std::cout << "X()" << std::endl; }
+
+ ~X()
+ { std::cout << "~X()" << std::endl; }
+ };
+
+ // void fn( boost::coroutines::coroutine< void() > & ca)
+ void fn( coro_t::caller_type & ca)
+ {
+ X x;
+
+ for ( int = 0;; ++i)
+ {
+ std::cout << "fn(): " << i << std::endl;
+ // transfer execution control back to main()
+ ca();
+ }
+ }
+
+ int main( int argc, char * argv[])
+ {
+ {
+ coro_t c( fn,
+ boost::coroutines::attributes(
+ boost::context::default_stacksize(),
+ boost::coroutines::stack_unwind) );
+
+ c();
+ c();
+ c();
+ c();
+ c();
+
+ std::cout << "c is complete: " << std::boolalpha << c.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
+ c is complete: false
+ ~X()
+ Done
+
+[important You must not swallow __forced_unwind__ exceptions!]
+
+
+[heading FPU preserving]
+
+Some applications do not use floating-point registers and can disable preserving
+fpu registers for performance reasons.
+
+[note According to the calling convention the FPU registers are preserved by default.]
+
+
+[section:coroutine Class `coroutine`]
+
+ #include <boost/coroutine/coroutine.hpp>
+
+ template< typename Signature >
+ class coroutine;
+
+ template<
+ typename R,
+ typename ArgTypes...
+ >
+ class coroutine< R ( ArgTypes...) >
+ {
+ public:
+ typedef unspec-type caller_type;
+ typedef unspec-type arguments;
+
+ coroutine();
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ coroutine( Fn fn, attributes const& attr = attributes(),
+ StackAllocator const& stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ coroutine( Fn fn, arguments const& args,
+ attributes const& attr = attributes(),
+ StackAllocator const& stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ coroutine( Fn && fn, attributes const& attr = attributes(),
+ StackAllocator stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ coroutine( Fn && fn arguments const& args,
+ attributes const& attr = attributes(),
+ StackAllocator stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ coroutine( coroutine && other);
+
+ coroutine & operator=( coroutine && other);
+
+ operator unspecified-bool-type() const;
+
+ bool operator!() const;
+
+ void swap( coroutine & other);
+
+ bool empty() const;
+
+ coroutine & operator()(A0 a0, ..., A9 a9);
+
+ R get() const;
+ };
+
+ template< typename Signature >
+ void swap( coroutine< Signature > & l, coroutine< Signature > & r);
+
+ template< typename T >
+ range_iterator< coroutine< T() > >::type begin( coroutine< T() > &);
+ template< typename T >
+ range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &);
+
+ template< typename T >
+ range_iterator< coroutine< T() > >::type end( coroutine< T() > &);
+ template< typename T >
+ range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &);
+
+[heading `coroutine()`]
+[variablelist
+[[Effects:] [Creates a coroutine representing __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ coroutine( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ coroutine( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+]
+
+[heading `coroutine( coroutine && other)`]
+[variablelist
+[[Effects:] [Moves the internal data of `other` to `*this`.
+`other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `coroutine & operator=( coroutine && other)`]
+[variablelist
+[[Effects:] [Destroys the internal data of `*this` and moves the
+internal data of `other` to `*this`. `other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `operator unspecified-bool-type() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns false. Otherwise true.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool operator!() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns true. Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool empty()`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__, the function returns true.
+Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `coroutine<> & operator()(A0 a0, A9 a9)`]
+[variablelist
+[[Preconditions:] [operator unspecified-bool-type() returns true for `*this`.]
+[[Effects:] [Execution control is transferred to __coro_fn__ and the arguments
+`a0`,..., are passed to the coroutine-function.]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `R get()()`]
+[variablelist
+[[Preconditions:] [`*this` is not a __not_a_coro__, `! is_complete()`.]]
+[[Returns:] [Returns data transferred from coroutine-function via __coro_op__
+of __coro_caller__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `void swap( coroutine & other)`]
+[variablelist
+[[Effects:] [Swaps the internal data from `*this` with the values
+of `other`.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `T caller_type::operator()( R)`]
+[variablelist
+[[Effects:] [Gives execution control back to calling context by returning
+a value of type R. The return type of this function is a __tuple__ containing
+the arguments passed to __coro_op__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading Non-member function `swap()`]
+
+ template< typename Signature >
+ void swap( coroutine< Signature > & l, coroutine< Signature > & r);
+
+[variablelist
+[[Effects:] [As if 'l.swap( r)'.]]
+]
+
+[heading Non-member function `begin( coroutine< T() > &)`]
+ template< typename T >
+ range_iterator< coroutine< T() > >::type begin( coroutine< T() > &);
+
+[variablelist
+[[Returns:] [Returns a range-iterator (input-iterator).]]
+]
+
+[heading Non-member function `begin( coroutine< void(T) > &)`]
+ template< typename T >
+ range_iterator< coroutine< void(T) > >::type begin( coroutine< void(T) > &);
+
+[variablelist
+[[Returns:] [Returns a range-iterator (output-iterator).]]
+]
+
+[heading Non-member function `end( coroutine< T() > &)`]
+ template< typename T >
+ range_iterator< coroutine< T() > >::type end( coroutine< T() > &);
+
+[variablelist
+[[Returns:] [Returns a end range-iterator (input-iterator).]]
+]
+
+[heading Non-member function `end( coroutine< void(T) > &)`]
+ template< typename T >
+ range_iterator< coroutine< void(T) > >::type end( coroutine< void(T) > &);
+
+[variablelist
+[[Returns:] [Returns a end range-iterator (output-iterator).]]
+]
+
+[endsect]
+
+[endsect]
Copied: branches/release/libs/coroutine/doc/unidirect.qbk (from r85162, trunk/libs/coroutine/doc/unidirect.qbk)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/doc/unidirect.qbk 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/doc/unidirect.qbk)
@@ -0,0 +1,784 @@
+[/
+ 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:unidirect Unidirectional coroutine]
+
+[note This is the default interface (macro BOOST_COROUTINES_UNIDIRECT).]
+
+Two coroutine types - __push_coro__ and __pull_coro__ - providing a
+unidirectional transfer of data.
+
+
+[heading __pull_coro__]
+__pull_coro__ transfers data from another execution context (== pulled-from).
+The class has only one template parameter defining the transferred parameter
+type.
+The constructor of __pull_coro__ takes a function (__coro_fn__) accepting a
+reference to a __push_coro__ as argument. Instantiating a __pull_coro__ passes
+the control of execution to __coro_fn__ and a complementary __push_coro__ is
+synthesized by the runtime and passed as reference to __coro_fn__.
+
+This kind of coroutine provides __pull_coro_op__. This method only switches
+context; it transfers no data.
+
+__pull_coro__ provides input iterators (__pull_coro_it__) and __begin__/__end__
+are overloaded. The increment-operation switches the context and transfers data.
+
+ std::coroutine<int>::pull_type source(
+ [&](std::coroutine<int>::push_type& sink){
+ int first=1,second=1;
+ sink(first);
+ sink(second);
+ for(int i=0;i<8;++i){
+ int third=first+second;
+ first=second;
+ second=third;
+ sink(third);
+ }
+ });
+
+ for(auto i:source)
+ std::cout << i << " ";
+
+ std::cout << "\nDone" << std::endl;
+
+ output:
+ 1 1 2 3 5 8 13 21 34 55
+ Done
+
+In this example a __pull_coro__ is created in the main execution context taking
+a lambda function (== __coro_fn__) which calculates Fibonacci numbers in a
+simple ['for]-loop).
+The __coro_fn__ is executed in a newly created execution context which is
+managed by the instance of __pull_coro__.
+A __push_coro__ is automatically generated by the runtime and passed as
+reference to the lambda function. Each time the lambda function calls
+__push_coro__op with another Fibonacci number, __push_coro__ transfers it back
+to the main execution context. The local state of __coro_fn__ is preserved and
+will be restored upon transferring execution control back to __coro_fn__
+to calculate the next Fibonacci number.
+Because __pull_coro__ provides input iterators and __begin__/__end__ are
+overloaded, a ['range-based for]-loop can be used to iterate over the generated
+Fibonacci numbers.
+
+
+[heading __push_coro__]
+__push_coro__ transfers data to the other execution context (== pushed-to).
+The class has only one template parameter defining the transferred parameter
+type.
+The constructor of __push_coro__ takes a function (__coro_fn__) accepting a
+reference to a __pull_coro__ as argument. In contrast to __pull_coro__,
+instantiating a __push_coro__ does not pass the control of execution to
+__coro_fn__ - instead the first call of __push_coro__op synthesizes a
+complementary __pull_coro__ and passes it as reference to __coro_fn__.
+
+The interface does not contain a ['get()]-function: you can not retrieve
+values from another execution context with this kind of coroutine.
+
+__push_coro__ provides output iterators (__push_coro__iterator) and
+__begin__/__end__ are overloaded. The increment-operation switches the context
+and transfers data.
+
+ struct FinalEOL{
+ ~FinalEOL(){
+ std::cout << std::endl;
+ }
+ };
+
+ const int num=5, width=15;
+ std::coroutine<std::string>::push_type writer(
+ [&](std::coroutine<std::string>::pull_type& in){
+ // finish the last line when we leave by whatever means
+ FinalEOL eol;
+ // pull values from upstream, lay them out 'num' to a line
+ for (;;){
+ for(int i=0;i<num;++i){
+ // when we exhaust the input, stop
+ if(!in) return;
+ std::cout << std::setw(width) << in.get();
+ // now that we've handled this item, advance to next
+ in();
+ }
+ // after 'num' items, line break
+ std::cout << std::endl;
+ }
+ });
+
+ std::vector<std::string> words{
+ "peas", "porridge", "hot", "peas",
+ "porridge", "cold", "peas", "porridge",
+ "in", "the", "pot", "nine",
+ "days", "old" };
+
+ std::copy(std::begin(words),std::end(words),std::begin(writer));
+
+ output:
+ peas porridge hot peas porridge
+ cold peas porridge in the
+ pot nine days old
+
+In this example a __push_coro__ is created in the main execution context
+accepting a lambda function (== __coro_fn__) which requests strings and lays out
+'num' of them on each line.
+This demonstrates the inversion of control permitted by coroutines. Without
+coroutines, a utility function to perform the same job would necessarily
+accept each new value as a function parameter, returning after processing that
+single value. That function would depend on a static state variable. A
+__coro_fn__, however, can request each new value as if by calling a function
+-- even though its caller also passes values as if by calling a function.
+The __coro_fn__ is executed in a newly created execution context which is
+managed by the instance of __push_coro__.
+The main execution context passes the strings to the __coro_fn__ by calling
+__push_coro__op.
+A __pull_coro__ is automatically generated by the runtime and passed as
+reference to the lambda function. The __coro_fn__ accesses the strings passed
+from the main execution context by calling __pull_coro__get and lays those
+strings out on ['std::cout] according the parameters 'num' and 'width'.
+The local state of __coro_fn__ is preserved and will be restored after
+transferring execution control back to __coro_fn__.
+Because __push_coro__ provides output iterators and __begin__/__end__ are
+overloaded, the ['std::copy] algorithm can be used to iterate over the vector
+containing the strings and pass them one by one to the coroutine.
+
+
+[heading stackful]
+Each instance of a coroutine has its own stack.
+
+In contrast to stackless coroutines, stackful coroutines allow invoking the
+suspend operation out of arbitrary sub-stackframes, enabling escape-and-reenter
+recursive operations.
+
+
+[heading move-only]
+A coroutine is moveable-only.
+
+If it were copyable, then its stack with all the objects allocated on it
+would be copied too. That would force undefined behaviour if some of these
+objects were RAII-classes (manage a resource via RAII pattern). When the first
+of the coroutine copies terminates (unwinds its stack), the RAII class
+destructors will release their managed resources. When the second copy
+terminates, the same destructors will try to doubly-release the same resources,
+leading to undefined behavior.
+
+
+[heading clean-up]
+On coroutine destruction the associated stack will be unwound.
+
+The constructor of coroutine allows to pass an customized ['stack-allocator].
+['stack-allocator] is free to deallocate the stack or cache it for future usage
+(for coroutines created later).
+
+
+[heading segmented stack]
+__push_coro__ and __pull_coro__ does support segmented stacks (growing on
+demand).
+
+It is not always possible to estimated the required stack size - in most cases
+too much memory is allocated (waste of virtual address-space).
+
+At construction a coroutine starts with a default (minimal) stack size. This
+minimal stack size is the maximum of page size and the canonical size for signal
+stack (macro SIGSTKSZ on POSIX).
+
+At this time of writing only GCC (4.7)\cite{gccsplit} is known to support
+segmented stacks. With version 1.54 __boost_coroutine__ provides support for
+segmented stacks.
+
+The destructor releases the associated stack. The implementer is free to
+deallocate the stack or to cache it for later usage.
+
+
+[heading context switch]
+A coroutine saves and restores registers according to the underlying ABI on
+each context switch.
+
+Some applications do not use floating-point registers and can disable preserving
+fpu registers for performance reasons.
+
+[note According to the calling convention the FPU registers are preserved by
+default.]
+
+On POSIX systems, the coroutine context switch does not preserve signal masks
+for performance reasons.
+
+A context switch is done via __push_coro__op and __pull_coro__op.
+
+[warning Calling __push_coro_op__/__pull_coro_op__ from inside the [_same]
+coroutine results in undefined behaviour.]
+
+
+[heading coroutine-function]
+The __coro_fn__ returns ['void] and takes its counterpart-coroutine as
+argument, so that using the coroutine passed as argument to __coro_fn__ is the
+only way to transfer data and execution control back to the caller.
+Both coroutine types take the same template argument.
+For __pull_coro__ the __coro_fn__ is entered at __pull_coro__ construction.
+For __push_coro__ the __coro_fn__ is not entered at __push_coro__ construction
+but entered by the first invocation of __push_coro__op.
+After execution control is returned from __coro_fn__ the state of the
+coroutine can be checked via
+__pull_coro__bool returning true if the coroutine is still valid (__coro_fn__
+has not terminated). Unless T is void, true also implies that a data value is
+available.
+
+
+[heading passing data from a pull-coroutine to main-context]
+In order to transfer data from a __pull_coro__ to the main-context the framework
+synthesizes a __push_coro__ associated with the __pull_coro__ instance in the
+main-context. The synthesized __push_coro__ is passed as argument to __coro_fn__.\\
+The __coro_fn__ must call this __push_coro__op in order to transfer each
+data value back to the main-context.
+In the main-context, the __pull_coro__bool determines whether the coroutine is
+still valid and a data value is available or __coro_fn__ has terminated
+(__pull_coro__ is invalid; no data value available). Access to the transferred
+data value is given by __pull_coro__get.
+
+ std::coroutine<int>::pull_type source( // constructor enters coroutine-function
+ [&](std::coroutine<int>::push_type& sink){
+ sink(1); // push {1} back to main-context
+ sink(1); // push {1} back to main-context
+ sink(2); // push {2} back to main-context
+ sink(3); // push {3} back to main-context
+ sink(5); // push {5} back to main-context
+ sink(8); // push {8} back to main-context
+ });
+
+ while(source){ // test if pull-coroutine is valid
+ int ret=source.get(); // access data value
+ source(); // context-switch to coroutine-function
+ }
+
+
+[heading passing data from main-context to a push-coroutine]
+In order to transfer data to a __push_coro__ from the main-context the framework
+synthesizes a __pull_coro__ associated with the __push_coro__ instance in the
+main-context. The synthesized __pull_coro__ is passed as argument to __coro_fn__.
+The main-context must call this __push_coro__op in order to transfer each data
+value into the __coro_fn__.
+Access to the transferred data value is given by __pull_coro__get.
+
+ std::coroutine<int>::push_type sink( // constructor does NOT enter coroutine-function
+ [&](std::coroutine<int>::pull_type& source){
+ for (int i:source) {
+ std::cout << i << " ";
+ }
+ });
+
+ std::vector<int> v{1,1,2,3,5,8,13,21,34,55};
+ for( int i:v){
+ sink(i); // push {i} to coroutine-function
+ }
+
+
+[heading accessing parameters]
+Parameters returned from or transferred to the __coro_fn__ can be accessed with
+__pull_coro__get.
+
+Splitting-up the access of parameters from context switch function enables to
+check if __pull_coro__ is valid after return from __pull_coro__op, e.g.
+__pull_coro__ has values and __coro_fn__ has not terminated.
+
+ std::coroutine<std::tuple<int,int>>::push_type sink(
+ [&](std::coroutine<std::tuple<int,int>>::pull_type& source){
+ // access tuple {7,11}; x==7 y==1
+ int x,y;
+ std::tie(x,y)=source.get();
+ });
+
+ sink(std::make_tuple(7,11));
+
+
+[heading exceptions]
+An exception thrown inside a __pull_coro__'s __coro_fn__ before its first call
+to __push_coro__op will be re-thrown by the __pull_coro__ constructor. After a
+__pull_coro__'s __coro_fn__'s first call to __push_coro__op, any subsequent
+exception inside that __coro_fn__ will be re-thrown by __pull_coro__op.
+__pull_coro__get does not throw.
+
+An exception thrown inside a __push_coro__'s __coro_fn__ will be re-thrown by
+__push_coro__op.
+
+[important Code executed by coroutine must not prevent the propagation of the
+__forced_unwind__ exception. Absorbing that exception will cause stack
+unwinding to fail. Thus, any code that catches all exceptions must re-throw the
+pending exception.]
+
+ try {
+ // code that might throw
+ } catch(const forced_unwind&) {
+ throw;
+ } catch(...) {
+ // possibly not re-throw pending exception
+ }
+
+
+[heading Stack unwinding]
+Sometimes it is necessary to unwind the stack of an unfinished coroutine to
+destroy local stack variables so they can release allocated resources (RAII
+pattern). The third argument of the coroutine constructor, `do_unwind`,
+indicates whether the destructor should unwind the stack (stack is unwound by
+default).
+
+Stack unwinding assumes the following preconditions:
+
+* The coroutine is not __not_a_coro__
+* The coroutine is not complete
+* The coroutine is not running
+* The coroutine owns a stack
+
+After unwinding, a __coro__ is complete.
+
+ struct X {
+ X(){
+ std::cout<<"X()"<<std::endl;
+ }
+
+ ~X(){
+ std::cout<<"~X()"<<std::endl;
+ }
+ };
+
+ {
+ boost::coroutines::coroutine<void>::push_type sink(
+ [&](boost::coroutines::coroutine<void>::pull_type& source){
+ X x;
+ for(int=0;;++i){
+ std::cout<<"fn(): "<<i<<std::endl;
+ // transfer execution control back to main()
+ source();
+ }
+ });
+
+ sink();
+ sink();
+ sink();
+ sink();
+ sink();
+
+ std::cout<<"c is complete: "<<std::boolalpha<<c.is_complete()<<"\n";
+ }
+
+ std::cout<<"Done"<<std::endl;
+
+ output:
+ X()
+ fn(): 0
+ fn(): 1
+ fn(): 2
+ fn(): 3
+ fn(): 4
+ fn(): 5
+ c is complete: false
+ ~X()
+ Done
+
+
+[heading Range iterators]
+__boost_coroutine__ provides output- and input-iterators using __boost_range__.
+__pull_coro__ can be used via input-iterators using __begin__ and __end__.
+
+ int number=2,exponent=8;
+ boost::coroutines::coroutine< int >::pull_type source(
+ [&]( boost::coroutines::coroutine< int >::push_type & sink){
+ int counter=0,result=1;
+ while(counter++<exponent){
+ result=result*number;
+ sink(result);
+ }
+ });
+
+ for (auto i:source)
+ std::cout << i << " ";
+
+ std::cout << "\nDone" << std::endl;
+
+ output:
+ 2 4 8 16 32 64 128 256
+ Done
+
+Output-iterators can be created from __push_coro__.
+
+ std::coroutine<int>::push_type sink(
+ [&](std::coroutine<int>::pull_type& source){
+ while(source){
+ std::cout << source.get() << " ";
+ source();
+ }
+ });
+
+ std::vector<int> v{1,1,2,3,5,8,13,21,34,55};
+ std::copy(std::begin(v),std::end(v),std::begin(sink));
+
+
+[heading Exit a __coro_fn__]
+__coro_fn__ is exited with a simple return statement jumping back to the calling
+routine. The __pull_coro__/__push_coro__ becomes complete, e.g. __coro_bool__
+will return 'false'.
+
+[important After returning from __coro_fn__ the __coro__ is complete (can not
+resumed with __coro_op__).]
+
+
+
+[section:pull_coro Class `coroutine<>::pull_type`]
+
+ #include <boost/coroutine/coroutine.hpp>
+
+ template< typename R >
+ class coroutine<>::pull_type
+ {
+ public:
+ pull_type();
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ pull_type( Fn fn, attributes const& attr = attributes(),
+ StackAllocator const& stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ pull_type( Fn && fn, attributes const& attr = attributes(),
+ StackAllocator stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ pull_type( pull_type && other);
+
+ pull_type & operator=( pull_type && other);
+
+ operator unspecified-bool-type() const;
+
+ bool operator!() const;
+
+ void swap( pull_type & other);
+
+ bool empty() const;
+
+ pull_type & operator()();
+
+ bool has_result() const;
+
+ R get() const;
+ };
+
+ template< typename R >
+ void swap( pull_type< R > & l, pull_type< R > & r);
+
+ template< typename R >
+ range_iterator< pull_type< R > >::type begin( pull_type< R > &);
+
+ template< typename R >
+ range_iterator< pull_type< R > >::type end( pull_type< R > &);
+
+[heading `pull_type()`]
+[variablelist
+[[Effects:] [Creates a coroutine representing __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ pull_type( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ pull_type( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `pull_type( pull_type && other)`]
+[variablelist
+[[Effects:] [Moves the internal data of `other` to `*this`.
+`other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `pull_type & operator=( pull_type && other)`]
+[variablelist
+[[Effects:] [Destroys the internal data of `*this` and moves the
+internal data of `other` to `*this`. `other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `operator unspecified-bool-type() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns false. Otherwise true.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool operator!() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns true. Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool empty()`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__, the function returns true.
+Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `pull_type<> & operator()()`]
+[variablelist
+[[Preconditions:] [`*this` is not a __not_a_coro__.]]
+[[Effects:] [Execution control is transferred to __coro_fn__ (no parameter are
+passed to the coroutine-function).]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `bool has_result()`]
+[variablelist
+[[Preconditions:] [`*this` is not a __not_a_coro__.]]
+[[Returns:] [If `*this` has a, the function returns true. Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `R get()()`]
+
+ R coroutine<R>::pull_type::get();
+ R& coroutine<R&>::pull_type::get();
+ void coroutine<void>pull_type::get()=delete;
+
+[variablelist
+[[Preconditions:] [`*this` is not a __not_a_coro__.]]
+[[Returns:] [Returns data transferred from coroutine-function via
+__push_coro_op__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `void swap( pull_type & other)`]
+[variablelist
+[[Effects:] [Swaps the internal data from `*this` with the values
+of `other`.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading Non-member function `swap()`]
+
+ template< typename R >
+ void swap( pull_type< R > & l, pull_type< R > & r);
+
+[variablelist
+[[Effects:] [As if 'l.swap( r)'.]]
+]
+
+[heading Non-member function `begin( pull_type< R > &)`]
+ template< typename R >
+ range_iterator< pull_type< R > >::type begin( pull_type< R > &);
+
+[variablelist
+[[Returns:] [Returns a range-iterator (input-iterator).]]
+]
+
+[heading Non-member function `end( pull_type< R > &)`]
+ template< typename R >
+ range_iterator< pull_type< R > >::type end( pull_type< R > &);
+
+[variablelist
+[[Returns:] [Returns a end range-iterator (input-iterator).]]
+]
+
+[endsect]
+
+
+[section:push_coro Class `coroutine<>::push_type`]
+
+ #include <boost/coroutine/coroutine.hpp>
+
+ template< typename Arg >
+ class coroutine<>::push_type
+ {
+ public:
+ push_type();
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ push_type( Fn fn, attributes const& attr = attributes(),
+ StackAllocator const& stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ template<
+ typename Fn,
+ typename StackAllocator = stack_allocator,
+ typename Allocator = std::allocator< coroutine >
+ >
+ push_type( Fn && fn, attributes const& attr = attributes(),
+ StackAllocator stack_alloc = StackAllocator(),
+ Allocator const& alloc = Allocator() );
+
+ push_type( push_type && other);
+
+ push_type & operator=( push_type && other);
+
+ operator unspecified-bool-type() const;
+
+ bool operator!() const;
+
+ void swap( push_type & other);
+
+ bool empty() const;
+
+ push_type & operator()( Arg&& arg);
+ };
+
+ template< typename Arg >
+ void swap( push_type< Arg > & l, push_type< Arg > & r);
+
+ template< typename Arg >
+ range_iterator< push_type< Arg > >::type begin( push_type< Arg > &);
+
+ template< typename Arg >
+ range_iterator< push_type< Arg > >::type end( push_type< Arg > &);
+
+[heading `push_type()`]
+[variablelist
+[[Effects:] [Creates a coroutine representing __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ push_type( Fn fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+]
+
+[heading `template< typename Fn, typename StackAllocator, typename Allocator >
+ push_type( Fn && fn, attributes const& attr, StackAllocator const& stack_alloc, Allocator const& alloc)`]
+[variablelist
+[[Preconditions:] [`size` > minimum_stacksize(), `size` < maximum_stacksize()
+when ! is_stack_unbound().]]
+[[Effects:] [Creates a coroutine which will execute `fn`. Argument `attr`
+determines stack clean-up and preserving floating-point registers.
+For allocating/deallocating the stack `stack_alloc` is used and internal
+data are allocated by Allocator.]]
+]
+
+[heading `push_type( push_type && other)`]
+[variablelist
+[[Effects:] [Moves the internal data of `other` to `*this`.
+`other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `push_type & operator=( push_type && other)`]
+[variablelist
+[[Effects:] [Destroys the internal data of `*this` and moves the
+internal data of `other` to `*this`. `other` becomes __not_a_coro__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `operator unspecified-bool-type() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns false. Otherwise true.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool operator!() const`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__ or the coroutine-function
+has returned (completed), the function returns true. Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `bool empty()`]
+[variablelist
+[[Returns:] [If `*this` refers to __not_a_coro__, the function returns true.
+Otherwise false.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `push_type<> & operator()(Arg&& arg)`]
+
+ push_type& coroutine<Arg>::push_type::operator()(const Arg&);
+ push_type& coroutine<Arg>::push_type::operator()(Arg&&);
+ push_type& coroutine<Arg&>::push_type::operator()(Arg&);
+ push_type& coroutine<void>::push_type::operator()();
+
+[variablelist
+[[Preconditions:] [operator unspecified-bool-type() returns true for `*this`.]]
+[[Effects:] [Execution control is transferred to __coro_fn__ and the argument
+`arg` is passed to the coroutine-function.]]
+[[Throws:] [Exceptions thrown inside __coro_fn__.]]
+]
+
+[heading `void swap( push_type & other)`]
+[variablelist
+[[Effects:] [Swaps the internal data from `*this` with the values
+of `other`.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading `T caller_type::operator()( R)`]
+[variablelist
+[[Effects:] [Gives execution control back to calling context by returning
+a value of type R. The return type of this function is a __tuple__ containing
+the arguments passed to __coro_op__.]]
+[[Throws:] [Nothing.]]
+]
+
+[heading Non-member function `swap()`]
+
+ template< typename Arg >
+ void swap( push_type< Arg > & l, push_type< Arg > & r);
+
+[variablelist
+[[Effects:] [As if 'l.swap( r)'.]]
+]
+
+[heading Non-member function `begin( push_type< Arg > &)`]
+ template< typename Arg >
+ range_iterator< push_type< Arg > >::type begin( push_type< Arg > &);
+
+[variablelist
+[[Returns:] [Returns a range-iterator (output-iterator).]]
+]
+
+[heading Non-member function `end( push_type< Arg > &)`]
+ template< typename Arg >
+ range_iterator< push_type< Arg > >::type end( push_type< Arg > &);
+
+[variablelist
+[[Returns:] [Returns a end range-iterator (output-iterator).]]
+]
+
+[endsect]
+
+
+
+[endsect]
Deleted: branches/release/libs/coroutine/example/Jamfile.v2
==============================================================================
--- branches/release/libs/coroutine/example/Jamfile.v2 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,86 +0,0 @@
-# Boost.Coroutine Library Examples Jamfile
-
-# 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)
-
-# For more information, see http://www.boost.org/
-
-import common ;
-import feature ;
-import indirect ;
-import modules ;
-import os ;
-import toolset ;
-
-if [ os.name ] = SOLARIS
-{
- lib socket ;
- lib nsl ;
-}
-else if [ os.name ] = NT
-{
- lib ws2_32 ;
- lib mswsock ;
-}
-else if [ os.name ] = HPUX
-{
- lib ipv6 ;
-}
-
-project boost/coroutine/example
- : requirements
- <library>../build//boost_coroutine
- <library>/boost/program_options//boost_program_options
- <library>/boost/system//boost_system
- <library>/boost/thread//boost_thread
- <toolset>gcc-4.7,<segmented-stacks>on:<cxxflags>-fsplit-stack
- <toolset>gcc-4.8,<segmented-stacks>on:<cxxflags>-fsplit-stack
- <threading>multi
- <link>static
- ;
-
-exe segmented_stack
- : segmented_stack.cpp
- ;
-
-exe fibonacci
- : fibonacci.cpp
- ;
-
-exe echo
- : echo.cpp
- ;
-
-exe power
- : power.cpp
- ;
-
-exe parallel
- : parallel.cpp
- ;
-
-exe unwind
- : unwind.cpp
- ;
-
-exe same_fringe
- : same_fringe.cpp
- ;
-
-exe asio/stream_client
- : asio/stream_client.cpp
- ;
-
-exe asio/stream_server
- : asio/stream_server.cpp
- ;
-
-#exe same_fringe
-# : c++11/same_fringe.cpp
-# ;
-#
-#exe fibonacci
-# : c++11/fibonacci.cpp
-# ;
Copied: branches/release/libs/coroutine/example/cpp03/Jamfile.v2 (from r85162, trunk/libs/coroutine/example/cpp03/Jamfile.v2)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/Jamfile.v2 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/Jamfile.v2)
@@ -0,0 +1,78 @@
+# Boost.Coroutine Library Examples Jamfile
+
+# 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)
+
+# For more information, see http://www.boost.org/
+
+import common ;
+import feature ;
+import indirect ;
+import modules ;
+import os ;
+import toolset ;
+
+if [ os.name ] = SOLARIS
+{
+ lib socket ;
+ lib nsl ;
+}
+else if [ os.name ] = NT
+{
+ lib ws2_32 ;
+ lib mswsock ;
+}
+else if [ os.name ] = HPUX
+{
+ lib ipv6 ;
+}
+
+project boost/coroutine/example
+ : requirements
+ <library>../../build//boost_coroutine
+ <library>/boost/program_options//boost_program_options
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <toolset>gcc-4.7,<segmented-stacks>on:<cxxflags>-fsplit-stack
+ <toolset>gcc-4.8,<segmented-stacks>on:<cxxflags>-fsplit-stack
+ <link>static
+ <threading>multi
+ ;
+
+exe segmented_stack
+ : segmented_stack.cpp
+ ;
+
+exe fibonacci
+ : fibonacci.cpp
+ ;
+
+exe echo
+ : echo.cpp
+ ;
+
+exe power
+ : power.cpp
+ ;
+
+exe parallel
+ : parallel.cpp
+ ;
+
+exe unwind
+ : unwind.cpp
+ ;
+
+exe same_fringe
+ : same_fringe.cpp
+ ;
+
+exe layout
+ : layout.cpp
+ ;
+
+exe chaining
+ : chaining.cpp
+ ;
Copied: branches/release/libs/coroutine/example/cpp03/chaining.cpp (from r85162, trunk/libs/coroutine/example/cpp03/chaining.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/chaining.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/chaining.cpp)
@@ -0,0 +1,203 @@
+
+// Copyright Nat Goodspeed 2013.
+// 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 <iostream>
+#include <iomanip>
+#include <string>
+#include <cctype>
+#include <sstream>
+
+#include <boost/bind.hpp>
+#include <boost/coroutine/all.hpp>
+#include <boost/foreach.hpp>
+
+typedef boost::coroutines::coroutine<std::string> coro_t;
+
+// deliver each line of input stream to sink as a separate string
+void readlines(coro_t::push_type& sink, std::istream& in)
+{
+ std::string line;
+ while (std::getline(in, line))
+ sink(line);
+}
+
+void tokenize(coro_t::push_type& sink, coro_t::pull_type& source)
+{
+ // This tokenizer doesn't happen to be stateful: you could reasonably
+ // implement it with a single call to push each new token downstream. But
+ // I've worked with stateful tokenizers, in which the meaning of input
+ // characters depends in part on their position within the input line. At
+ // the time, I wished for a way to resume at the suspend point!
+ BOOST_FOREACH(std::string line, source)
+ {
+ std::string::size_type pos = 0;
+ while (pos < line.length())
+ {
+ if (line[pos] == '"')
+ {
+ std::string token;
+ ++pos; // skip open quote
+ while (pos < line.length() && line[pos] != '"')
+ token += line[pos++];
+ ++pos; // skip close quote
+ sink(token); // pass token downstream
+ }
+ else if (std::isspace(line[pos]))
+ {
+ ++pos; // outside quotes, ignore whitespace
+ }
+ else if (std::isalpha(line[pos]))
+ {
+ std::string token;
+ while (pos < line.length() && std::isalpha(line[pos]))
+ token += line[pos++];
+ sink(token); // pass token downstream
+ }
+ else // punctuation
+ {
+ sink(std::string(1, line[pos++]));
+ }
+ }
+ }
+}
+
+void only_words(coro_t::push_type& sink, coro_t::pull_type& source)
+{
+ BOOST_FOREACH(std::string token, source)
+ {
+ if (! token.empty() && std::isalpha(token[0]))
+ sink(token);
+ }
+}
+
+void trace(coro_t::push_type& sink, coro_t::pull_type& source)
+{
+ BOOST_FOREACH(std::string token, source)
+ {
+ std::cout << "trace: '" << token << "'\n";
+ sink(token);
+ }
+}
+
+struct FinalEOL
+{
+ ~FinalEOL() { std::cout << std::endl; }
+};
+
+void layout(coro_t::pull_type& source, int num, int width)
+{
+ // Finish the last line when we leave by whatever means
+ FinalEOL eol;
+
+ // Pull values from upstream, lay them out 'num' to a line
+ for (;;)
+ {
+ for (int i = 0; i < num; ++i)
+ {
+ // when we exhaust the input, stop
+ if (! source)
+ return;
+
+ std::cout << std::setw(width) << source.get();
+ // now that we've handled this item, advance to next
+ source();
+ }
+ // after 'num' items, line break
+ std::cout << std::endl;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ // For example purposes, instead of having a separate text file in the
+ // local filesystem, construct an istringstream to read.
+ std::string data(
+ "This is the first line.\n"
+ "This, the second.\n"
+ "The third has \"a phrase\"!\n"
+ );
+
+ {
+ std::cout << "\nreadlines:\n";
+ std::istringstream infile(data);
+ // Each coroutine-function has a small, specific job to do. Instead of
+ // adding conditional logic to a large, complex input function, the
+ // caller composes smaller functions into the desired processing
+ // chain.
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tracer(boost::bind(trace, _1, boost::ref(reader)));
+ BOOST_FOREACH(std::string line, tracer)
+ {
+ std::cout << "got: " << line << "\n";
+ }
+ }
+
+ {
+ std::cout << "\ncompose a chain:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::pull_type tracer(boost::bind(trace, _1, boost::ref(tokenizer)));
+ BOOST_FOREACH(std::string token, tracer)
+ {
+ // just iterate, we're already pulling through tracer
+ }
+ }
+
+ {
+ std::cout << "\nfilter:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::pull_type filter(boost::bind(only_words, _1, boost::ref(tokenizer)));
+ coro_t::pull_type tracer(boost::bind(trace, _1, boost::ref(filter)));
+ BOOST_FOREACH(std::string token, tracer)
+ {
+ // just iterate, we're already pulling through tracer
+ }
+ }
+
+ {
+ std::cout << "\nlayout() as coroutine::push_type:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::pull_type filter(boost::bind(only_words, _1, boost::ref(tokenizer)));
+ coro_t::push_type writer(boost::bind(layout, _1, 5, 15));
+ BOOST_FOREACH(std::string token, filter)
+ {
+ writer(token);
+ }
+ }
+
+ {
+ std::cout << "\ncalling layout() directly:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::pull_type filter(boost::bind(only_words, _1, boost::ref(tokenizer)));
+ // Because of the symmetry of the API, we can directly call layout()
+ // instead of using it as a coroutine-function.
+ layout(filter, 5, 15);
+ }
+
+ {
+ std::cout << "\nfiltering output:\n";
+ std::istringstream infile(data);
+ coro_t::pull_type reader(boost::bind(readlines, _1, boost::ref(infile)));
+ coro_t::pull_type tokenizer(boost::bind(tokenize, _1, boost::ref(reader)));
+ coro_t::push_type writer(boost::bind(layout, _1, 5, 15));
+ // Because of the symmetry of the API, we can use any of these
+ // chaining functions in a push_type coroutine chain as well.
+ coro_t::push_type filter(boost::bind(only_words, boost::ref(writer), _1));
+ BOOST_FOREACH(std::string token, tokenizer)
+ {
+ filter(token);
+ }
+ }
+
+ return 0;
+}
Copied: branches/release/libs/coroutine/example/cpp03/echo.cpp (from r85162, trunk/libs/coroutine/example/cpp03/echo.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/echo.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/echo.cpp)
@@ -0,0 +1,84 @@
+
+// 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 <boost/bind.hpp>
+#include <boost/coroutine/all.hpp>
+
+#ifdef BOOST_COROUTINES_UNIDIRECT
+typedef boost::coroutines::coroutine< void >::pull_type pull_coro_t;
+typedef boost::coroutines::coroutine< void >::push_type push_coro_t;
+
+void echo( pull_coro_t & source, int i)
+{
+ std::cout << i;
+ source();
+}
+
+void runit( push_coro_t & sink1)
+{
+ std::cout << "started! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ push_coro_t sink2( boost::bind( echo, _1, i) );
+ while ( sink2)
+ sink2();
+ sink1();
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ pull_coro_t source( runit);
+ while ( source) {
+ std::cout << "-";
+ source();
+ }
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
+typedef boost::coroutines::coroutine< void() > coro_t;
+
+void echo( coro_t & ca, int i)
+{
+ std::cout << i;
+ ca();
+}
+
+void runit( coro_t & ca)
+{
+ std::cout << "started! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ coro_t c( boost::bind( echo, _1, i) );
+ while ( c)
+ c();
+ ca();
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ coro_t c( runit);
+ while ( c) {
+ std::cout << "-";
+ c();
+ }
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#endif
Copied: branches/release/libs/coroutine/example/cpp03/echosse.cpp (from r85162, trunk/libs/coroutine/example/cpp03/echosse.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/echosse.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/echosse.cpp)
@@ -0,0 +1,60 @@
+
+// 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 <emmintrin.h>
+
+#include <boost/bind.hpp>
+#include <boost/coroutine/all.hpp>
+
+void echoSSE( int i)
+{
+ __m128i xmm;
+ xmm = _mm_set_epi32(i, i+1, i+2, i+3);
+ uint32_t v32[4];
+
+ memcpy(&v32, &xmm, 16);
+
+ std::cout << v32[0];
+ std::cout << v32[1];
+ std::cout << v32[2];
+ std::cout << v32[3];
+}
+
+void echo( boost::coroutines::coroutine< void >::push_type & c, int i)
+{
+ std::cout << i << ":";
+ echoSSE(i);
+ c();
+}
+
+void runit( boost::coroutines::coroutine< void >::push_type & ca)
+{
+ std::cout << "started! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ boost::coroutines::coroutine< void >::pull_type c( boost::bind( echo, _1, i) );
+ while ( c)
+ c();
+ ca();
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ boost::coroutines::coroutine< void >::pull_type c( runit);
+ while ( c) {
+ std::cout << "-";
+ c();
+ }
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
Copied: branches/release/libs/coroutine/example/cpp03/fibonacci.cpp (from r85162, trunk/libs/coroutine/example/cpp03/fibonacci.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/fibonacci.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/fibonacci.cpp)
@@ -0,0 +1,75 @@
+
+// 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 <boost/range.hpp>
+#include <boost/coroutine/all.hpp>
+
+#ifdef BOOST_COROUTINES_UNIDIRECT
+void fibonacci( boost::coroutines::coroutine< int >::push_type & sink)
+{
+ int first = 1, second = 1;
+ sink( first);
+ sink( second);
+ while ( true)
+ {
+ int third = first + second;
+ first = second;
+ second = third;
+ sink( third);
+ }
+}
+
+int main()
+{
+ boost::coroutines::coroutine< int >::pull_type source( fibonacci);
+ boost::range_iterator<
+ boost::coroutines::coroutine< int >::pull_type
+ >::type it( boost::begin( source) );
+ for ( int i = 0; i < 10; ++i)
+ {
+ std::cout << * it << " ";
+ ++it;
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
+void fibonacci( boost::coroutines::coroutine< void( int) > & c)
+{
+ int first = 1, second = 1;
+ c( first);
+ c( second);
+ while ( true)
+ {
+ int third = first + second;
+ first = second;
+ second = third;
+ c( third);
+ }
+}
+
+int main()
+{
+ boost::coroutines::coroutine< int() > c( fibonacci);
+ boost::range_iterator<
+ boost::coroutines::coroutine< int() >
+ >::type it( boost::begin( c) );
+ for ( int i = 0; i < 10; ++i)
+ {
+ std::cout << * it << " ";
+ ++it;
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#endif
Copied: branches/release/libs/coroutine/example/cpp03/layout.cpp (from r85162, trunk/libs/coroutine/example/cpp03/layout.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/layout.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/layout.cpp)
@@ -0,0 +1,71 @@
+
+// Copyright Nat Goodspeed 2013.
+// 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 <iostream>
+#include <iomanip>
+#include <vector>
+#include <string>
+#include <utility>
+
+#include <boost/assign/list_of.hpp>
+#include <boost/bind.hpp>
+#include <boost/coroutine/all.hpp>
+#include <boost/range.hpp>
+
+struct FinalEOL
+{
+ ~FinalEOL() { std::cout << std::endl; }
+};
+
+void layout(boost::coroutines::coroutine<std::string>::pull_type& in, int num, int width)
+{
+ // Finish the last line when we leave by whatever means
+ FinalEOL eol;
+
+ // Pull values from upstream, lay them out 'num' to a line
+ for (;;)
+ {
+ for (int i = 0; i < num; ++i)
+ {
+ // when we exhaust the input, stop
+ if (! in)
+ return;
+
+ std::cout << std::setw(width) << in.get();
+ // now that we've handled this item, advance to next
+ in();
+ }
+ // after 'num' items, line break
+ std::cout << std::endl;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ std::vector<std::string> words = boost::assign::list_of
+ ("peas")
+ ("porridge")
+ ("hot")
+ ("peas")
+ ("porridge")
+ ("cold")
+ ("peas")
+ ("porridge")
+ ("in")
+ ("the")
+ ("pot")
+ ("nine")
+ ("days")
+ ("old")
+ ;
+
+ boost::coroutines::coroutine<std::string>::push_type writer(
+ boost::bind(layout, _1, 5, 15));
+
+ std::copy(boost::begin(words), boost::end(words), boost::begin(writer));
+
+ return 0;
+}
Copied: branches/release/libs/coroutine/example/cpp03/parallel.cpp (from r85162, trunk/libs/coroutine/example/cpp03/parallel.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/parallel.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/parallel.cpp)
@@ -0,0 +1,91 @@
+
+// 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 <boost/bind.hpp>
+#include <boost/coroutine/all.hpp>
+
+#ifdef BOOST_COROUTINES_UNIDIRECT
+void first( boost::coroutines::coroutine< void >::push_type & sink)
+{
+ std::cout << "started first! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ sink();
+ std::cout << "a" << i;
+ }
+}
+
+void second( boost::coroutines::coroutine< void >::push_type & sink)
+{
+ std::cout << "started second! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ sink();
+ std::cout << "b" << i;
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ boost::coroutines::coroutine< void >::pull_type source1( boost::bind( first, _1) );
+ boost::coroutines::coroutine< void >::pull_type source2( boost::bind( second, _1) );
+ while ( source1 && source2) {
+ source1();
+ std::cout << " ";
+ source2();
+ std::cout << " ";
+ }
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
+typedef boost::coroutines::coroutine< void() > coroutine_t;
+
+void first( coroutine_t::caller_type & self)
+{
+ std::cout << "started first! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ self();
+ std::cout << "a" << i;
+ }
+}
+
+void second( coroutine_t::caller_type & self)
+{
+ std::cout << "started second! ";
+ for ( int i = 0; i < 10; ++i)
+ {
+ self();
+ std::cout << "b" << i;
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ coroutine_t c1( boost::bind( first, _1) );
+ coroutine_t c2( boost::bind( second, _1) );
+ while ( c1 && c2) {
+ c1();
+ std::cout << " ";
+ c2();
+ std::cout << " ";
+ }
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#endif
Copied: branches/release/libs/coroutine/example/cpp03/power.cpp (from r85162, trunk/libs/coroutine/example/cpp03/power.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/power.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/power.cpp)
@@ -0,0 +1,86 @@
+
+// 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 <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/range.hpp>
+#include <boost/coroutine/all.hpp>
+
+#ifdef BOOST_COROUTINES_UNIDIRECT
+void power( boost::coroutines::coroutine< int >::push_type & sink, int number, int exponent)
+{
+ int counter = 0;
+ int result = 1;
+ while ( counter++ < exponent)
+ {
+ result = result * number;
+ sink( result);
+ }
+}
+
+int main()
+{
+ {
+ std::cout << "using range functions" << std::endl;
+ boost::coroutines::coroutine< int >::pull_type source( boost::bind( power, _1, 2, 8) );
+ boost::coroutines::coroutine< int >::pull_type::iterator e( boost::end( source) );
+ for ( boost::coroutines::coroutine< int >::pull_type::iterator i( boost::begin( source) );
+ i != e; ++i)
+ std::cout << * i << " ";
+ }
+
+ {
+ std::cout << "\nusing BOOST_FOREACH" << std::endl;
+ boost::coroutines::coroutine< int >::pull_type source( boost::bind( power, _1, 2, 8) );
+ BOOST_FOREACH( int i, source)
+ { std::cout << i << " "; }
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
+typedef boost::coroutines::coroutine< int() > coro1_t;
+typedef boost::coroutines::coroutine< void( int) > coro2_t;
+typedef boost::range_iterator< coro1_t >::type iterator_t;
+
+void power( coro2_t & c, int number, int exponent)
+{
+ int counter = 0;
+ int result = 1;
+ while ( counter++ < exponent)
+ {
+ result = result * number;
+ c( result);
+ }
+}
+
+int main()
+{
+ {
+ std::cout << "using range functions" << std::endl;
+ coro1_t c( boost::bind( power, _1, 2, 8) );
+ iterator_t e( boost::end( c) );
+ for ( iterator_t i( boost::begin( c) ); i != e; ++i)
+ std::cout << * i << " ";
+ }
+
+ {
+ std::cout << "\nusing BOOST_FOREACH" << std::endl;
+ coro1_t c( boost::bind( power, _1, 2, 8) );
+ BOOST_FOREACH( int i, c)
+ { std::cout << i << " "; }
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#endif
Copied: branches/release/libs/coroutine/example/cpp03/same_fringe.cpp (from r85162, trunk/libs/coroutine/example/cpp03/same_fringe.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/same_fringe.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/same_fringe.cpp)
@@ -0,0 +1,161 @@
+
+// Copyright Nat Goodspeed 2013.
+// 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 <cstddef>
+#include <cstdlib>
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <utility>
+
+#include <boost/bind.hpp>
+#include <boost/range.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/coroutine/all.hpp>
+
+struct node
+{
+ typedef boost::shared_ptr< node > ptr_t;
+
+ // Each tree node has an optional left subtree, an optional right subtree
+ // and a value of its own. The value is considered to be between the left
+ // subtree and the right.
+ ptr_t left, right;
+ std::string value;
+
+ // construct leaf
+ node(const std::string& v):
+ left(), right(), value(v)
+ {}
+ // construct nonleaf
+ node(ptr_t l, const std::string& v, ptr_t r):
+ left(l), right(r), value(v)
+ {}
+
+ static ptr_t create(const std::string& v)
+ {
+ return ptr_t(new node(v));
+ }
+
+ static ptr_t create(ptr_t l, const std::string& v, ptr_t r)
+ {
+ return ptr_t(new node(l, v, r));
+ }
+};
+
+node::ptr_t create_left_tree_from(const std::string& root)
+{
+ /* --------
+ root
+ / \
+ b e
+ / \
+ a c
+ -------- */
+ return node::create(
+ node::create(
+ node::create("a"),
+ "b",
+ node::create("c")),
+ root,
+ node::create("e"));
+}
+
+node::ptr_t create_right_tree_from(const std::string& root)
+{
+ /* --------
+ root
+ / \
+ a d
+ / \
+ c e
+ -------- */
+ return node::create(
+ node::create("a"),
+ root,
+ node::create(
+ node::create("c"),
+ "d",
+ node::create("e")));
+}
+
+// recursively walk the tree, delivering values in order
+void traverse(node::ptr_t n,boost::coroutines::coroutine<std::string>::push_type& out)
+{
+ if (n->left) traverse(n->left,out);
+ out(n->value);
+ if (n->right) traverse(n->right,out);
+}
+
+int main()
+{
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ boost::bind(traverse, left_d, _1));
+ std::cout << "left tree from d:\n";
+ std::copy(boost::begin(left_d_reader),
+ boost::end(left_d_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+
+ node::ptr_t right_b(create_right_tree_from("b"));
+ boost::coroutines::coroutine<std::string>::pull_type right_b_reader(
+ boost::bind(traverse, right_b, _1));
+ std::cout << "right tree from b:\n";
+ std::copy(boost::begin(right_b_reader),
+ boost::end(right_b_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+
+ node::ptr_t right_x(create_right_tree_from("x"));
+ boost::coroutines::coroutine<std::string>::pull_type right_x_reader(
+ boost::bind(traverse, right_x, _1));
+ std::cout << "right tree from x:\n";
+ std::copy(boost::begin(right_x_reader),
+ boost::end(right_x_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+ }
+
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ boost::bind(traverse, left_d, _1));
+
+ node::ptr_t right_b(create_right_tree_from("b"));
+ boost::coroutines::coroutine<std::string>::pull_type right_b_reader(
+ boost::bind(traverse, right_b, _1));
+
+ std::cout << "left tree from d == right tree from b? "
+ << std::boolalpha
+ << std::equal(boost::begin(left_d_reader),
+ boost::end(left_d_reader),
+ boost::begin(right_b_reader))
+ << std::endl;
+ }
+
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ boost::bind(traverse, left_d, _1));
+
+ node::ptr_t right_x(create_right_tree_from("x"));
+ boost::coroutines::coroutine<std::string>::pull_type right_x_reader(
+ boost::bind(traverse, right_x, _1));
+
+ std::cout << "left tree from d == right tree from x? "
+ << std::boolalpha
+ << std::equal(boost::begin(left_d_reader),
+ boost::end(left_d_reader),
+ boost::begin(right_x_reader))
+ << std::endl;
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+}
Copied: branches/release/libs/coroutine/example/cpp03/segmented_stack.cpp (from r85162, trunk/libs/coroutine/example/cpp03/segmented_stack.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/segmented_stack.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/segmented_stack.cpp)
@@ -0,0 +1,81 @@
+
+// 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 <iostream>
+
+#include <boost/assert.hpp>
+#include <boost/coroutine/all.hpp>
+#include <boost/thread.hpp>
+
+int count = 20;
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+void access( char *buf) __attribute__ ((noinline));
+#endif
+void access( char *buf)
+{
+ buf[0] = '\0';
+}
+
+void bar( int i)
+{
+ char buf[4 * 1024];
+
+ if ( i > 0)
+ {
+ access( buf);
+ std::cout << i << ". iteration" << std::endl;
+ bar( i - 1);
+ }
+}
+
+#ifdef BOOST_COROUTINES_UNIDIRECT
+void foo( boost::coroutines::coroutine< void >::pull_type & source)
+{
+ bar( count);
+ source();
+}
+
+void thread_fn()
+{
+ {
+ boost::coroutines::coroutine< void >::push_type sink( foo);
+ sink();
+ }
+}
+#else
+typedef boost::coroutines::coroutine< void() > coro_t;
+
+void foo( coro_t & c)
+{
+ bar( count);
+ c();
+}
+
+void thread_fn()
+{
+ {
+ coro_t c( foo);
+ c();
+ }
+}
+#endif
+
+int main( int argc, char * argv[])
+{
+#if defined(BOOST_USE_SEGMENTED_STACKS)
+ std::cout << "using segmented stacks: allocates " << count << " * 4kB on stack, ";
+ std::cout << "initial stack size = " << boost::coroutines::stack_allocator::default_stacksize() / 1024 << "kB" << std::endl;
+ std::cout << "application should not fail" << std::endl;
+#else
+ std::cout << "using standard stacks: allocates " << count << " * 4kB on stack, ";
+ std::cout << "initial stack size = " << boost::coroutines::stack_allocator::default_stacksize() / 1024 << "kB" << std::endl;
+ std::cout << "application might fail" << std::endl;
+#endif
+
+ boost::thread( thread_fn).join();
+
+ return 0;
+}
Copied: branches/release/libs/coroutine/example/cpp03/tree.h (from r85162, trunk/libs/coroutine/example/cpp03/tree.h)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/tree.h 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/tree.h)
@@ -0,0 +1,155 @@
+
+// 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 TREE_H
+#define TREE_H
+
+#include <cstddef>
+#include <string>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/coroutine/all.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+# if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4355)
+# endif
+
+struct branch;
+struct leaf;
+
+struct visitor
+{
+ virtual ~visitor() {};
+
+ virtual void visit( branch & b) = 0;
+ virtual void visit( leaf & l) = 0;
+};
+
+struct node
+{
+ typedef boost::intrusive_ptr< node > ptr_t;
+
+ std::size_t use_count;
+
+ node() :
+ use_count( 0)
+ {}
+
+ virtual ~node() {}
+
+ virtual void accept( visitor & v) = 0;
+
+ friend inline void intrusive_ptr_add_ref( node * p)
+ { ++p->use_count; }
+
+ friend inline void intrusive_ptr_release( node * p)
+ { if ( 0 == --p->use_count) delete p; }
+};
+
+struct branch : public node
+{
+ node::ptr_t left;
+ node::ptr_t right;
+
+ static ptr_t create( node::ptr_t left_, node::ptr_t right_)
+ { return ptr_t( new branch( left_, right_) ); }
+
+ branch( node::ptr_t left_, node::ptr_t right_) :
+ left( left_), right( right_)
+ {}
+
+ void accept( visitor & v)
+ { v.visit( * this); }
+};
+
+struct leaf : public node
+{
+ std::string value;
+
+ static ptr_t create( std::string const& value_)
+ { return ptr_t( new leaf( value_) ); }
+
+ leaf( std::string const& value_) :
+ value( value_)
+ {}
+
+ void accept( visitor & v)
+ { v.visit( * this); }
+};
+
+inline
+bool operator==( leaf const& l, leaf const& r)
+{ return l.value == r.value; }
+
+inline
+bool operator!=( leaf const& l, leaf const& r)
+{ return l.value != r.value; }
+
+#ifdef BOOST_COROUTINES_UNIDIRECT
+class tree_visitor : public visitor
+{
+private:
+ boost::coroutines::coroutine< leaf & >::push_type & c_;
+
+public:
+ tree_visitor( boost::coroutines::coroutine< leaf & >::push_type & c) :
+ c_( c)
+ {}
+
+ void visit( branch & b)
+ {
+ if ( b.left) b.left->accept( * this);
+ if ( b.right) b.right->accept( * this);
+ }
+
+ void visit( leaf & l)
+ { c_( l); }
+};
+
+void enumerate_leafs( boost::coroutines::coroutine< leaf & >::push_type & c, node::ptr_t root)
+{
+ tree_visitor v( c);
+ root->accept( v);
+}
+#else
+typedef boost::coroutines::coroutine< leaf&() > coro_t;
+
+class tree_visitor : public visitor
+{
+private:
+ coro_t::caller_type & c_;
+
+public:
+ tree_visitor( coro_t::caller_type & c) :
+ c_( c)
+ {}
+
+ void visit( branch & b)
+ {
+ if ( b.left) b.left->accept( * this);
+ if ( b.right) b.right->accept( * this);
+ }
+
+ void visit( leaf & l)
+ { c_( l); }
+};
+
+void enumerate_leafs( coro_t::caller_type & c, node::ptr_t root)
+{
+ tree_visitor v( c);
+ root->accept( v);
+}
+#endif
+
+# if defined(BOOST_MSVC)
+# pragma warning(pop)
+# endif
+
+
+#endif // TREE_H
Copied: branches/release/libs/coroutine/example/cpp03/unwind.cpp (from r85162, trunk/libs/coroutine/example/cpp03/unwind.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp03/unwind.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp03/unwind.cpp)
@@ -0,0 +1,81 @@
+
+// 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 <boost/bind.hpp>
+#include <boost/coroutine/all.hpp>
+
+#ifdef BOOST_COROUTINES_UNIDIRECT
+struct X : private boost::noncopyable
+{
+ X() { std::cout << "X()" << std::endl; }
+ ~X() { std::cout << "~X()" << std::endl; }
+};
+
+void fn( boost::coroutines::coroutine< void >::push_type & sink)
+{
+ X x;
+ int i = 0;
+ while ( true)
+ {
+ std::cout << "fn() : " << ++i << std::endl;
+ sink();
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ boost::coroutines::coroutine< void >::pull_type source( fn);
+ for ( int k = 0; k < 3; ++k)
+ {
+ source();
+ }
+ std::cout << "destroying coroutine and unwinding stack" << std::endl;
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
+typedef boost::coroutines::coroutine< void() > coro_t;
+
+struct X : private boost::noncopyable
+{
+ X() { std::cout << "X()" << std::endl; }
+ ~X() { std::cout << "~X()" << std::endl; }
+};
+
+void fn( coro_t & ca)
+{
+ X x;
+ int i = 0;
+ while ( true)
+ {
+ std::cout << "fn() : " << ++i << std::endl;
+ ca();
+ }
+}
+
+int main( int argc, char * argv[])
+{
+ {
+ coro_t c( fn);
+ for ( int k = 0; k < 3; ++k)
+ {
+ c();
+ }
+ std::cout << "destroying coroutine and unwinding stack" << std::endl;
+ }
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#endif
Copied: branches/release/libs/coroutine/example/cpp11/Jamfile.v2 (from r85162, trunk/libs/coroutine/example/cpp11/Jamfile.v2)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp11/Jamfile.v2 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp11/Jamfile.v2)
@@ -0,0 +1,58 @@
+# Boost.Coroutine Library Examples Jamfile
+
+# 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)
+
+# For more information, see http://www.boost.org/
+
+import common ;
+import feature ;
+import indirect ;
+import modules ;
+import os ;
+import toolset ;
+
+if [ os.name ] = SOLARIS
+{
+ lib socket ;
+ lib nsl ;
+}
+else if [ os.name ] = NT
+{
+ lib ws2_32 ;
+ lib mswsock ;
+}
+else if [ os.name ] = HPUX
+{
+ lib ipv6 ;
+}
+
+project boost/coroutine/example
+ : requirements
+ <library>../../build//boost_coroutine
+ <library>/boost/program_options//boost_program_options
+ <library>/boost/system//boost_system
+ <library>/boost/thread//boost_thread
+ <toolset>gcc-4.7,<segmented-stacks>on:<cxxflags>-fsplit-stack
+ <toolset>gcc-4.8,<segmented-stacks>on:<cxxflags>-fsplit-stack
+ <link>static
+ <threading>multi
+ ;
+
+exe same_fringe
+ : same_fringe.cpp
+ ;
+
+exe fibonacci
+ : fibonacci.cpp
+ ;
+
+exe await_emu
+ : await_emu.cpp
+ ;
+
+exe layout
+ : layout.cpp
+ ;
Copied: branches/release/libs/coroutine/example/cpp11/await_emu.cpp (from r85162, trunk/libs/coroutine/example/cpp11/await_emu.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp11/await_emu.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp11/await_emu.cpp)
@@ -0,0 +1,197 @@
+// Copyright Evgeny Panasyuk 2013.
+// 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)
+
+// e-mail: E?????[dot]P???????[at]gmail.???
+
+// Full emulation of await feature from C# language in C++ based on Stackful Coroutines from
+// Boost.Coroutine library.
+// This proof-of-concept shows that exact syntax of await feature can be emulated with help of
+// Stackful Coroutines, demonstrating that it is superior mechanism.
+// Main aim of this proof-of-concept is to draw attention to Stackful Coroutines.
+
+#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
+#define BOOST_THREAD_PROVIDES_FUTURE
+#define BOOST_RESULT_OF_USE_DECLTYPE
+
+#include <boost/coroutine/all.hpp>
+#include <boost/foreach.hpp>
+#include <boost/thread.hpp>
+#include <boost/chrono.hpp>
+
+#include <functional>
+#include <iostream>
+#include <cstddef>
+#include <utility>
+#include <cstdlib>
+#include <memory>
+#include <vector>
+#include <stack>
+#include <queue>
+#include <ctime>
+
+using namespace std;
+using namespace boost;
+
+// ___________________________________________________________ //
+
+template<typename T>
+class concurrent_queue
+{
+ queue<T> q;
+ mutex m;
+ condition_variable c;
+public:
+ template<typename U>
+ void push(U &&u)
+ {
+ lock_guard<mutex> l(m);
+ q.push( forward<U>(u) );
+ c.notify_one();
+ }
+ void pop(T &result)
+ {
+ unique_lock<mutex> u(m);
+ c.wait(u, [&]{return !q.empty();} );
+ result = move_if_noexcept(q.front());
+ q.pop();
+ }
+};
+
+typedef std::function<void()> Task;
+concurrent_queue<Task> main_tasks;
+auto finished = false;
+
+void reschedule()
+{
+ this_thread::sleep_for(chrono::milliseconds( rand() % 2000 ));
+}
+
+// ___________________________________________________________ //
+
+#ifdef BOOST_COROUTINES_UNIDIRECT
+typedef coroutines::coroutine<void>::pull_type coro_pull;
+typedef coroutines::coroutine<void>::push_type coro_push;
+#else
+typedef coroutines::coroutine<void()> coro_pull;
+typedef coroutines::coroutine<void()>::caller_type coro_push;
+#endif
+struct CurrentCoro
+{
+ std::shared_ptr<coro_pull> coro;
+ coro_push *caller;
+};
+/*should be thread_local*/ stack<CurrentCoro> coro_stack;
+
+template<typename F>
+auto asynchronous(F f) -> future<decltype(f())>
+{
+ typedef promise<decltype(f())> CoroPromise;
+
+ CoroPromise coro_promise;
+ auto coro_future = coro_promise.get_future();
+
+ // It is possible to avoid shared_ptr and use move-semantic,
+ // but it would require to refuse use of std::function (it requires CopyConstructable),
+ // and would lead to further complication and is unjustified
+ // for purposes of this proof-of-concept
+ CurrentCoro current_coro =
+ {
+ make_shared<coro_pull>(std::bind( [f](CoroPromise &coro_promise, coro_push &caller)
+ {
+ caller();
+ coro_stack.top().caller = &caller;
+ coro_promise.set_value( f() );
+ }, std::move(coro_promise), placeholders::_1 ))
+ };
+
+ coro_stack.push( std::move(current_coro) );
+ (*coro_stack.top().coro)();
+ coro_stack.pop();
+
+#ifdef _MSC_VER
+ return std::move( coro_future );
+#else
+ return coro_future;
+#endif
+}
+
+struct Awaiter
+{
+ template<typename Future>
+ auto operator*(Future &&ft) -> decltype(ft.get())
+ {
+ typedef decltype(ft.get()) Result;
+
+ auto &¤t_coro = coro_stack.top();
+ auto result = ft.then([current_coro](Future &ft) -> Result
+ {
+ main_tasks.push([current_coro]
+ {
+ coro_stack.push(std::move(current_coro));
+ (*coro_stack.top().coro)();
+ coro_stack.pop();
+ });
+ return ft.get();
+ });
+ (*coro_stack.top().caller)();
+ return result.get();
+ }
+};
+#define await Awaiter()*
+
+// ___________________________________________________________ //
+
+void async_user_handler();
+
+int main()
+{
+ srand(time(0));
+
+ // Custom scheduling is not required - can be integrated
+ // to other systems transparently
+ main_tasks.push([]
+ {
+ asynchronous([]
+ {
+ return async_user_handler(),
+ finished = true;
+ });
+ });
+
+ Task task;
+ while(!finished)
+ {
+ main_tasks.pop(task);
+ task();
+ }
+}
+
+// __________________________________________________________________ //
+
+int bar(int i)
+{
+ // await is not limited by "one level" as in C#
+ auto result = await async([i]{ return reschedule(), i*100; });
+ return result + i*10;
+}
+
+int foo(int i)
+{
+ cout << i << ":\tbegin" << endl;
+ cout << await async([i]{ return reschedule(), i*10; }) << ":\tbody" << endl;
+ cout << bar(i) << ":\tend" << endl;
+ return i*1000;
+}
+
+void async_user_handler()
+{
+ vector<future<int>> fs;
+
+ for(auto i=0; i!=5; ++i)
+ fs.push_back( asynchronous([i]{ return foo(i+1); }) );
+
+ for(auto &&f : fs)
+ cout << await f << ":\tafter end" << endl;
+}
Copied: branches/release/libs/coroutine/example/cpp11/fibonacci.cpp (from r85162, trunk/libs/coroutine/example/cpp11/fibonacci.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp11/fibonacci.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp11/fibonacci.cpp)
@@ -0,0 +1,60 @@
+
+// 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 <boost/coroutine/all.hpp>
+
+#ifdef BOOST_COROUTINES_UNIDIRECT
+int main()
+{
+ boost::coroutines::coroutine< int >::pull_type source(
+ [&]( boost::coroutines::coroutine< int >::push_type & sink) {
+ int first = 1, second = 1;
+ sink( first);
+ sink( second);
+ for ( int i = 0; i < 8; ++i)
+ {
+ int third = first + second;
+ first = second;
+ second = third;
+ sink( third);
+ }
+ });
+
+ for ( auto i : source)
+ std::cout << i << " ";
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#else
+int main()
+{
+ boost::coroutines::coroutine< int() > c(
+ [&]( boost::coroutines::coroutine< void( int) > & c) {
+ int first = 1, second = 1;
+ c( first);
+ c( second);
+ for ( int i = 0; i < 8; ++i)
+ {
+ int third = first + second;
+ first = second;
+ second = third;
+ c( third);
+ }
+ });
+
+ for ( auto i : c)
+ std::cout << i << " ";
+
+ std::cout << "\nDone" << std::endl;
+
+ return EXIT_SUCCESS;
+}
+#endif
Copied: branches/release/libs/coroutine/example/cpp11/layout.cpp (from r85162, trunk/libs/coroutine/example/cpp11/layout.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp11/layout.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp11/layout.cpp)
@@ -0,0 +1,50 @@
+
+// Copyright Nat Goodspeed 2013.
+// 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 <iostream>
+#include <iomanip>
+#include <vector>
+#include <string>
+#include <utility>
+
+#include <boost/coroutine/all.hpp>
+
+struct FinalEOL{
+ ~FinalEOL(){
+ std::cout << std::endl;
+ }
+};
+
+int main(int argc,char* argv[]){
+ std::vector<std::string> words{
+ "peas", "porridge", "hot", "peas",
+ "porridge", "cold", "peas", "porridge",
+ "in", "the", "pot", "nine",
+ "days", "old" };
+
+ int num=5,width=15;
+ boost::coroutines::coroutine<std::string>::push_type writer(
+ [&](boost::coroutines::coroutine<std::string>::pull_type& in){
+ // finish the last line when we leave by whatever means
+ FinalEOL eol;
+ // pull values from upstream, lay them out 'num' to a line
+ for (;;){
+ for(int i=0;i<num;++i){
+ // when we exhaust the input, stop
+ if(!in) return;
+ std::cout << std::setw(width) << in.get();
+ // now that we've handled this item, advance to next
+ in();
+ }
+ // after 'num' items, line break
+ std::cout << std::endl;
+ }
+ });
+
+ std::copy(std::begin(words),std::end(words),std::begin(writer));
+
+ return 0;
+}
Copied: branches/release/libs/coroutine/example/cpp11/same_fringe.cpp (from r85162, trunk/libs/coroutine/example/cpp11/same_fringe.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp11/same_fringe.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp11/same_fringe.cpp)
@@ -0,0 +1,176 @@
+
+// Copyright Nat Goodspeed 2013.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSEstd::placeholders::_1_0.txt or copy at
+// http://www.boost.org/LICENSEstd::placeholders::_1_0.txt)
+
+#include <cstddef>
+#include <cstdlib>
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <utility>
+
+#include <boost/coroutine/all.hpp>
+
+struct node
+{
+ typedef std::shared_ptr< node > ptr_t;
+
+ // Each tree node has an optional left subtree, an optional right subtree
+ // and a value of its own. The value is considered to be between the left
+ // subtree and the right.
+ ptr_t left, right;
+ std::string value;
+
+ // construct leaf
+ node(const std::string& v):
+ left(),right(),value(v)
+ {}
+ // construct nonleaf
+ node(ptr_t l, const std::string& v, ptr_t r):
+ left(l),right(r),value(v)
+ {}
+
+ static ptr_t create(const std::string& v)
+ {
+ return ptr_t(new node(v));
+ }
+
+ static ptr_t create(ptr_t l, const std::string& v, ptr_t r)
+ {
+ return ptr_t(new node(l, v, r));
+ }
+};
+
+node::ptr_t create_left_tree_from(const std::string& root)
+{
+ /* --------
+ root
+ / \
+ b e
+ / \
+ a c
+ -------- */
+
+ return node::create(
+ node::create(
+ node::create("a"),
+ "b",
+ node::create("c")),
+ root,
+ node::create("e"));
+}
+
+node::ptr_t create_right_tree_from(const std::string& root)
+{
+ /* --------
+ root
+ / \
+ a d
+ / \
+ c e
+ -------- */
+
+ return node::create(
+ node::create("a"),
+ root,
+ node::create(
+ node::create("c"),
+ "d",
+ node::create("e")));
+}
+
+// recursively walk the tree, delivering values in order
+void traverse(node::ptr_t n, boost::coroutines::coroutine<std::string>::push_type& out)
+{
+ if (n->left)
+ traverse(n->left,out);
+ out(n->value);
+ if (n->right)
+ traverse(n->right,out);
+}
+
+int main()
+{
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(left_d,out);
+ });
+ std::cout << "left tree from d:\n";
+ std::copy(std::begin(left_d_reader),
+ std::end(left_d_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+
+ node::ptr_t right_b(create_right_tree_from("b"));
+ boost::coroutines::coroutine<std::string>::pull_type right_b_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(right_b,out);
+ });
+ std::cout << "right tree from b:\n";
+ std::copy(std::begin(right_b_reader),
+ std::end(right_b_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+
+ node::ptr_t right_x(create_right_tree_from("x"));
+ boost::coroutines::coroutine<std::string>::pull_type right_x_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(right_x,out);
+ });
+ std::cout << "right tree from x:\n";
+ std::copy(std::begin(right_x_reader),
+ std::end(right_x_reader),
+ std::ostream_iterator<std::string>(std::cout, " "));
+ std::cout << std::endl;
+ }
+
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(left_d,out);
+ });
+
+ node::ptr_t right_b(create_right_tree_from("b"));
+ boost::coroutines::coroutine<std::string>::pull_type right_b_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(right_b,out);
+ });
+
+ std::cout << "left tree from d == right tree from b? "
+ << std::boolalpha
+ << std::equal(std::begin(left_d_reader),
+ std::end(left_d_reader),
+ std::begin(right_b_reader))
+ << std::endl;
+ }
+
+ {
+ node::ptr_t left_d(create_left_tree_from("d"));
+ boost::coroutines::coroutine<std::string>::pull_type left_d_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(left_d,out);
+ });
+
+ node::ptr_t right_x(create_right_tree_from("x"));
+ boost::coroutines::coroutine<std::string>::pull_type right_x_reader(
+ [&]( boost::coroutines::coroutine<std::string>::push_type & out) {
+ traverse(right_x,out);
+ });
+
+ std::cout << "left tree from d == right tree from x? "
+ << std::boolalpha
+ << std::equal(std::begin(left_d_reader),
+ std::end(left_d_reader),
+ std::begin(right_x_reader))
+ << std::endl;
+ }
+
+ std::cout << "Done" << std::endl;
+
+ return EXIT_SUCCESS;
+}
Copied: branches/release/libs/coroutine/example/cpp11/tree.h (from r85162, trunk/libs/coroutine/example/cpp11/tree.h)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/example/cpp11/tree.h 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/example/cpp11/tree.h)
@@ -0,0 +1,97 @@
+
+// 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 TREE_H
+#define TREE_H
+
+#include <cstddef>
+#include <string>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+# if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4355)
+# endif
+
+struct branch;
+struct leaf;
+
+struct visitor
+{
+ virtual ~visitor() {};
+
+ virtual void visit( branch & b) = 0;
+ virtual void visit( leaf & l) = 0;
+};
+
+struct node
+{
+ typedef boost::intrusive_ptr< node > ptr_t;
+
+ std::size_t use_count;
+
+ node() :
+ use_count( 0)
+ {}
+
+ virtual ~node() {}
+
+ virtual void accept( visitor & v) = 0;
+
+ friend inline void intrusive_ptr_add_ref( node * p)
+ { ++p->use_count; }
+
+ friend inline void intrusive_ptr_release( node * p)
+ { if ( 0 == --p->use_count) delete p; }
+};
+
+struct branch : public node
+{
+ node::ptr_t left;
+ node::ptr_t right;
+
+ static ptr_t create( node::ptr_t left_, node::ptr_t right_)
+ { return ptr_t( new branch( left_, right_) ); }
+
+ branch( node::ptr_t left_, node::ptr_t right_) :
+ left( left_), right( right_)
+ {}
+
+ void accept( visitor & v)
+ { v.visit( * this); }
+};
+
+struct leaf : public node
+{
+ std::string value;
+
+ static ptr_t create( std::string const& value_)
+ { return ptr_t( new leaf( value_) ); }
+
+ leaf( std::string const& value_) :
+ value( value_)
+ {}
+
+ void accept( visitor & v)
+ { v.visit( * this); }
+};
+
+inline
+bool operator==( leaf const& l, leaf const& r)
+{ return l.value == r.value; }
+
+inline
+bool operator!=( leaf const& l, leaf const& r)
+{ return l.value != r.value; }
+
+# if defined(BOOST_MSVC)
+# pragma warning(pop)
+# endif
+
+#endif // TREE_H
Deleted: branches/release/libs/coroutine/example/echo.cpp
==============================================================================
--- branches/release/libs/coroutine/example/echo.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,46 +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 <boost/bind.hpp>
-#include <boost/coroutine/all.hpp>
-
-typedef boost::coroutines::coroutine< void() > coro_t;
-
-void echo( coro_t & ca, int i)
-{
- std::cout << i;
- ca();
-}
-
-void runit( coro_t & ca)
-{
- std::cout << "started! ";
- for ( int i = 0; i < 10; ++i)
- {
- coro_t c( boost::bind( echo, _1, i) );
- while ( c)
- c();
- ca();
- }
-}
-
-int main( int argc, char * argv[])
-{
- {
- coro_t c( runit);
- while ( c) {
- std::cout << "-";
- c();
- }
- }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
-}
Deleted: branches/release/libs/coroutine/example/fibonacci.cpp
==============================================================================
--- branches/release/libs/coroutine/example/fibonacci.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,72 +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 <boost/range.hpp>
-#include <boost/coroutine/all.hpp>
-
-void fibonacci( boost::coroutines::coroutine< void( int) > & c)
-{
- int first = 1, second = 1;
- while ( true)
- {
- int third = first + second;
- first = second;
- second = third;
- c( third);
- }
-}
-
-int main()
-{
- boost::coroutines::coroutine< int() > c( fibonacci);
- boost::range_iterator<
- boost::coroutines::coroutine< int() >
- >::type it( boost::begin( c) );
- for ( int i = 0; i < 10; ++i)
- {
- std::cout << * it << " ";
- ++it;
- }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
-}
-
-// C++11
-#if 0
-int main()
-{
- boost::coroutines::coroutine< int() > c(
- [&]( boost::coroutines::coroutine< void( int) > & c) {
- int first = 1, second = 1;
- while ( true)
- {
- int third = first + second;
- first = second;
- second = third;
- c( third);
- }
- });
-
- boost::range_iterator<
- boost::coroutines::coroutine< int() >
- >::type it( boost::begin( c) );
-
- for ( int i = 0; i < 10; ++i)
- {
- std::cout << * it << " ";
- ++it;
- }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
-}
-#endif
Deleted: branches/release/libs/coroutine/example/parallel.cpp
==============================================================================
--- branches/release/libs/coroutine/example/parallel.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,51 +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 <boost/bind.hpp>
-#include <boost/coroutine/all.hpp>
-
-typedef boost::coroutines::coroutine< void() > coroutine_t;
-
-void first( coroutine_t::caller_type & self)
-{
- std::cout << "started first! ";
- for ( int i = 0; i < 10; ++i)
- {
- self();
- std::cout << "a" << i;
- }
-}
-
-void second( coroutine_t::caller_type & self)
-{
- std::cout << "started second! ";
- for ( int i = 0; i < 10; ++i)
- {
- self();
- std::cout << "b" << i;
- }
-}
-
-int main( int argc, char * argv[])
-{
- {
- coroutine_t c1( boost::bind( first, _1) );
- coroutine_t c2( boost::bind( second, _1) );
- while ( c1 && c2) {
- c1();
- std::cout << " ";
- c2();
- std::cout << " ";
- }
- }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
-}
Deleted: branches/release/libs/coroutine/example/power.cpp
==============================================================================
--- branches/release/libs/coroutine/example/power.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,92 +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 <boost/bind.hpp>
-#include <boost/foreach.hpp>
-#include <boost/range.hpp>
-#include <boost/coroutine/all.hpp>
-
-typedef boost::coroutines::coroutine< int() > coro1_t;
-typedef boost::coroutines::coroutine< void( int) > coro2_t;
-typedef boost::range_iterator< coro1_t >::type iterator_t;
-
-void power( coro2_t & c, int number, int exponent)
-{
- int counter = 0;
- int result = 1;
- while ( counter++ < exponent)
- {
- result = result * number;
- c( result);
- }
-}
-
-int main()
-{
- {
- std::cout << "using range functions" << std::endl;
- coro1_t c( boost::bind( power, _1, 2, 8) );
- iterator_t e( boost::end( c) );
- for ( iterator_t i( boost::begin( c) ); i != e; ++i)
- std::cout << * i << " ";
- }
-
- {
- std::cout << "\nusing BOOST_FOREACH" << std::endl;
- coro1_t c( boost::bind( power, _1, 2, 8) );
- BOOST_FOREACH( int i, c)
- { std::cout << i << " "; }
- }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
-}
-#if 0
-int main()
-{
- {
- std::cout << "using range functions" << std::endl;
- boost::coroutines::coroutine< int() > c(
- [&]( boost::coroutines::coroutine< void( int) > &c) {
- int counter = 0;
- int result = 1;
- while ( counter++ < 8)
- {
- result = result * 2;
- c( result);
- }
- });
- iterator_t e( boost::end( c) );
- for ( iterator_t i( boost::begin( c) ); i != e; ++i)
- std::cout << * i << " ";
- }
-
- {
- std::cout << "\nusing BOOST_FOREACH" << std::endl;
- boost::coroutines::coroutine< int() > c(
- [&]( boost::coroutines::coroutine< void( int) > &c) {
- int counter = 0;
- int result = 1;
- while ( counter++ < 8)
- {
- result = result * 2;
- c( result);
- }
- });
- for ( int i : c) {
- std::cout << i << " ";
- }
- }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
-}
-#endif
Deleted: branches/release/libs/coroutine/example/same_fringe.cpp
==============================================================================
--- branches/release/libs/coroutine/example/same_fringe.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,81 +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 <cstddef>
-#include <cstdlib>
-#include <iostream>
-#include <string>
-#include <utility>
-
-#include <boost/bind.hpp>
-#include <boost/range.hpp>
-
-#include "tree.h"
-
-bool match_trees( coro_t & c1, coro_t & c2)
-{
- typedef boost::range_iterator< coro_t >::type iterator_t;
- iterator_t i1( boost::begin( c1) );
- iterator_t e1( boost::end( c1) );
- iterator_t i2( boost::begin( c2) );
- return std::equal( i1, e1, i2);
-}
-
-std::pair< node::ptr_t, node::ptr_t > create_eq_trees()
-{
- branch::ptr_t tree1 = branch::create(
- leaf::create( "A"),
- branch::create(
- leaf::create( "B"),
- leaf::create( "C") ) );
-
- branch::ptr_t tree2 = branch::create(
- branch::create(
- leaf::create( "A"),
- leaf::create( "B") ),
- leaf::create( "C") );
-
- return std::make_pair( tree1, tree2);
-}
-
-std::pair< node::ptr_t, node::ptr_t > create_diff_trees()
-{
- branch::ptr_t tree1 = branch::create(
- leaf::create( "A"),
- branch::create(
- leaf::create( "B"),
- leaf::create( "C") ) );
-
- branch::ptr_t tree2 = branch::create(
- branch::create(
- leaf::create( "A"),
- leaf::create( "X") ),
- leaf::create( "C") );
-
- return std::make_pair( tree1, tree2);
-}
-
-int main()
-{
- {
- std::pair< node::ptr_t, node::ptr_t > pt = create_eq_trees();
- coro_t te1( boost::bind( enumerate_leafs, _1, pt.first) );
- coro_t te2( boost::bind( enumerate_leafs, _1, pt.second) );
- bool result = match_trees( te1, te2);
- std::cout << std::boolalpha << "eq. trees matched == " << result << std::endl;
- }
- {
- std::pair< node::ptr_t, node::ptr_t > pt = create_diff_trees();
- coro_t te1( boost::bind( enumerate_leafs, _1, pt.first) );
- coro_t te2( boost::bind( enumerate_leafs, _1, pt.second) );
- bool result = match_trees( te1, te2);
- std::cout << std::boolalpha << "diff. trees matched == " << result << std::endl;
- }
-
- std::cout << "Done" << std::endl;
-
- return EXIT_SUCCESS;
-}
Deleted: branches/release/libs/coroutine/example/segmented_stack.cpp
==============================================================================
--- branches/release/libs/coroutine/example/segmented_stack.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,64 +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 <iostream>
-
-#include <boost/assert.hpp>
-#include <boost/coroutine/all.hpp>
-#include <boost/thread.hpp>
-
-typedef boost::coroutines::coroutine< void() > coro_t;
-
-int count = 20;
-
-void access( char *buf) __attribute__ ((noinline));
-void access( char *buf)
-{
- buf[0] = '\0';
-}
-void bar( int i)
-{
- char buf[4 * 1024];
-
- if ( i > 0)
- {
- access( buf);
- std::cout << i << ". iteration" << std::endl;
- bar( i - 1);
- }
-}
-
-void foo( coro_t & c)
-{
- bar( count);
- c();
-}
-
-void thread_fn()
-{
- {
- coro_t c( foo);
- c();
- int i = 7;
- }
-}
-
-int main( int argc, char * argv[])
-{
-#if defined(BOOST_USE_SEGMENTED_STACKS)
- std::cout << "using segmented stacks: allocates " << count << " * 4kB on stack, ";
- std::cout << "initial stack size = " << boost::coroutines::stack_allocator::default_stacksize() / 1024 << "kB" << std::endl;
- std::cout << "application should not fail" << std::endl;
-#else
- std::cout << "using standard stacks: allocates " << count << " * 4kB on stack, ";
- std::cout << "initial stack size = " << boost::coroutines::stack_allocator::default_stacksize() / 1024 << "kB" << std::endl;
- std::cout << "application might fail" << std::endl;
-#endif
-
- boost::thread( thread_fn).join();
-
- return 0;
-}
Deleted: branches/release/libs/coroutine/example/tree.h
==============================================================================
--- branches/release/libs/coroutine/example/tree.h 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,127 +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 TREE_H
-#define TREE_H
-
-#include <cstddef>
-#include <string>
-
-#include <boost/assert.hpp>
-#include <boost/config.hpp>
-#include <boost/coroutine/all.hpp>
-#include <boost/intrusive_ptr.hpp>
-
-# if defined(BOOST_MSVC)
-# pragma warning(push)
-# pragma warning(disable:4355)
-# endif
-
-struct branch;
-struct leaf;
-
-struct visitor
-{
- virtual ~visitor() {};
-
- virtual void visit( branch & b) = 0;
- virtual void visit( leaf & l) = 0;
-};
-
-struct node
-{
- typedef boost::intrusive_ptr< node > ptr_t;
-
- std::size_t use_count;
-
- node() :
- use_count( 0)
- {}
-
- virtual ~node() {}
-
- virtual void accept( visitor & v) = 0;
-
- friend inline void intrusive_ptr_add_ref( node * p)
- { ++p->use_count; }
-
- friend inline void intrusive_ptr_release( node * p)
- { if ( 0 == --p->use_count) delete p; }
-};
-
-struct branch : public node
-{
- node::ptr_t left;
- node::ptr_t right;
-
- static ptr_t create( node::ptr_t left_, node::ptr_t right_)
- { return ptr_t( new branch( left_, right_) ); }
-
- branch( node::ptr_t left_, node::ptr_t right_) :
- left( left_), right( right_)
- {}
-
- void accept( visitor & v)
- { v.visit( * this); }
-};
-
-struct leaf : public node
-{
- std::string value;
-
- static ptr_t create( std::string const& value_)
- { return ptr_t( new leaf( value_) ); }
-
- leaf( std::string const& value_) :
- value( value_)
- {}
-
- void accept( visitor & v)
- { v.visit( * this); }
-};
-
-inline
-bool operator==( leaf const& l, leaf const& r)
-{ return l.value == r.value; }
-
-inline
-bool operator!=( leaf const& l, leaf const& r)
-{ return l.value != r.value; }
-
-typedef boost::coroutines::coroutine< leaf&() > coro_t;
-
-class tree_visitor : public visitor
-{
-private:
- coro_t::caller_type & c_;
-
-public:
- tree_visitor( coro_t::caller_type & c) :
- c_( c)
- {}
-
- void visit( branch & b)
- {
- if ( b.left) b.left->accept( * this);
- if ( b.right) b.right->accept( * this);
- }
-
- void visit( leaf & l)
- { c_( l); }
-};
-
-void enumerate_leafs( coro_t::caller_type & c, node::ptr_t root)
-{
- tree_visitor v( c);
- root->accept( v);
-}
-
-# if defined(BOOST_MSVC)
-# pragma warning(pop)
-# endif
-
-
-#endif // TREE_H
Deleted: branches/release/libs/coroutine/example/unwind.cpp
==============================================================================
--- branches/release/libs/coroutine/example/unwind.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85162)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,46 +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 <boost/bind.hpp>
-#include <boost/coroutine/all.hpp>
-
-typedef boost::coroutines::coroutine< void() > coro_t;
-
-struct X : private boost::noncopyable
-{
- X() { std::cout << "X()" << std::endl; }
- ~X() { std::cout << "~X()" << std::endl; }
-};
-
-void fn( coro_t & ca)
-{
- X x;
- int i = 0;
- while ( true)
- {
- std::cout << "fn() : " << ++i << std::endl;
- ca();
- }
-}
-
-int main( int argc, char * argv[])
-{
- {
- coro_t c( fn);
- for ( int k = 0; k < 3; ++k)
- {
- c();
- }
- std::cout << "destroying coroutine and unwinding stack" << std::endl;
- }
-
- std::cout << "\nDone" << std::endl;
-
- return EXIT_SUCCESS;
-}
Modified: branches/release/libs/coroutine/performance/Jamfile.v2
==============================================================================
--- branches/release/libs/coroutine/performance/Jamfile.v2 Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/performance/Jamfile.v2 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -19,8 +19,8 @@
<library>/boost/coroutine//boost_coroutine
<toolset>gcc-4.7,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>gcc-4.8,<segmented-stacks>on:<cxxflags>-fsplit-stack
- <link>static
<linkflags>"-lrt"
+ <link>static
<threading>multi
;
Modified: branches/release/libs/coroutine/performance/performance.cpp
==============================================================================
--- branches/release/libs/coroutine/performance/performance.cpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/performance/performance.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -27,25 +27,81 @@
namespace coro = boost::coroutines;
-typedef coro::coroutine< void() > coro_t;
-
-#define COUNTER BOOST_PP_LIMIT_MAG
+# define COUNTER BOOST_PP_LIMIT_MAG
-#define CALL_COROUTINE(z,n,unused) \
+# define CALL_COROUTINE(z,n,unused) \
c();
+#ifdef BOOST_COROUTINES_UNIDIRECT
+void fn( boost::coroutines::coroutine< void >::push_type & c)
+{ while ( true) c(); }
+
+# ifdef BOOST_CONTEXT_CYCLE
+cycle_t test_cycles( cycle_t ov, coro::flag_fpu_t preserve_fpu)
+{
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ boost::coroutines::coroutine< void >::pull_type c( fn, coro::attributes( preserve_fpu) );
+# else
+ coro::simple_stack_allocator< 8 * 1024 * 1024, 64 * 1024, 8 * 1024 > alloc;
+ boost::coroutines::coroutine< void >::pull_type c( fn, coro::attributes( preserve_fpu), alloc);
+# endif
+
+ // cache warum-up
+BOOST_PP_REPEAT_FROM_TO( 0, COUNTER, CALL_COROUTINE, ~)
+
+ cycle_t start( cycles() );
+BOOST_PP_REPEAT_FROM_TO( 0, COUNTER, CALL_COROUTINE, ~)
+ cycle_t total( cycles() - start);
+
+ // we have two jumps and two measuremt-overheads
+ total -= ov; // overhead of measurement
+ total /= COUNTER; // per call
+ total /= 2; // 2x jump_to c1->c2 && c2->c1
+
+ return total;
+}
+# endif
+
+# if _POSIX_C_SOURCE >= 199309L
+zeit_t test_zeit( zeit_t ov, coro::flag_fpu_t preserve_fpu)
+{
+# if defined(BOOST_USE_SEGMENTED_STACKS)
+ boost::coroutines::coroutine< void >::pull_type c( fn, coro::attributes( preserve_fpu) );
+# else
+ coro::simple_stack_allocator< 8 * 1024 * 1024, 64 * 1024, 8 * 1024 > alloc;
+ boost::coroutines::coroutine< void >::pull_type c( fn, coro::attributes( preserve_fpu), alloc);
+# endif
+
+ // cache warum-up
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_COROUTINE, ~)
+
+ zeit_t start( zeit() );
+BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_COROUTINE, ~)
+ zeit_t total( zeit() - start);
+
+ // we have two jumps and two measuremt-overheads
+ total -= ov; // overhead of measurement
+ total /= BOOST_PP_LIMIT_MAG; // per call
+ total /= 2; // 2x jump_to c1->c2 && c2->c1
+
+ return total;
+}
+# endif
+#else
+typedef coro::coroutine< void() > coro_t;
+
void fn( coro_t::caller_type & c)
{ while ( true) c(); }
-#ifdef BOOST_CONTEXT_CYCLE
+# ifdef BOOST_CONTEXT_CYCLE
cycle_t test_cycles( cycle_t ov, coro::flag_fpu_t preserve_fpu)
{
-#if defined(BOOST_USE_SEGMENTED_STACKS)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
coro_t c( fn, coro::attributes( preserve_fpu) );
-#else
+# else
coro::simple_stack_allocator< 8 * 1024 * 1024, 64 * 1024, 8 * 1024 > alloc;
coro_t c( fn, coro::attributes( preserve_fpu), alloc);
-#endif
+# endif
// cache warum-up
BOOST_PP_REPEAT_FROM_TO( 0, COUNTER, CALL_COROUTINE, ~)
@@ -61,17 +117,17 @@
return total;
}
-#endif
+# endif
-#if _POSIX_C_SOURCE >= 199309L
+# if _POSIX_C_SOURCE >= 199309L
zeit_t test_zeit( zeit_t ov, coro::flag_fpu_t preserve_fpu)
{
-#if defined(BOOST_USE_SEGMENTED_STACKS)
+# if defined(BOOST_USE_SEGMENTED_STACKS)
coro_t c( fn, coro::attributes( preserve_fpu) );
-#else
+# else
coro::simple_stack_allocator< 8 * 1024 * 1024, 64 * 1024, 8 * 1024 > alloc;
coro_t c( fn, coro::attributes( preserve_fpu), alloc);
-#endif
+# endif
// cache warum-up
BOOST_PP_REPEAT_FROM_TO( 0, BOOST_PP_LIMIT_MAG, CALL_COROUTINE, ~)
@@ -87,6 +143,7 @@
return total;
}
+# endif
#endif
int main( int argc, char * argv[])
Modified: branches/release/libs/coroutine/src/detail/coroutine_context.cpp
==============================================================================
--- branches/release/libs/coroutine/src/detail/coroutine_context.cpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/src/detail/coroutine_context.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,6 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#define BOOST_COROUTINES_SOURCE
-
#include "boost/coroutine/detail/coroutine_context.hpp"
#ifdef BOOST_MSVC
Modified: branches/release/libs/coroutine/src/detail/segmented_stack_allocator.cpp
==============================================================================
--- branches/release/libs/coroutine/src/detail/segmented_stack_allocator.cpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/src/detail/segmented_stack_allocator.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,6 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#define BOOST_COROUTINES_SOURCE
-
#include <boost/coroutine/detail/segmented_stack_allocator.hpp>
#include <boost/assert.hpp>
Modified: branches/release/libs/coroutine/src/detail/standard_stack_allocator_posix.cpp
==============================================================================
--- branches/release/libs/coroutine/src/detail/standard_stack_allocator_posix.cpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/src/detail/standard_stack_allocator_posix.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,6 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#define BOOST_COROUTINES_SOURCE
-
#include "boost/coroutine/detail/standard_stack_allocator.hpp"
extern "C" {
Modified: branches/release/libs/coroutine/src/detail/standard_stack_allocator_windows.cpp
==============================================================================
--- branches/release/libs/coroutine/src/detail/standard_stack_allocator_windows.cpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/src/detail/standard_stack_allocator_windows.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -4,8 +4,6 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
-#define BOOST_COROUTINES_SOURCE
-
#include "boost/coroutine/detail/standard_stack_allocator.hpp"
extern "C" {
Copied: branches/release/libs/coroutine/src/exceptions.cpp (from r85162, trunk/libs/coroutine/src/exceptions.cpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/libs/coroutine/src/exceptions.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163, copy of r85162, trunk/libs/coroutine/src/exceptions.cpp)
@@ -0,0 +1,36 @@
+
+// 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 <boost/coroutine/exceptions.hpp>
+
+namespace boost {
+namespace coroutines {
+
+class coroutine_error_category : public system::error_category
+{
+public:
+ virtual const char* name() const BOOST_NOEXCEPT
+ { return "coroutine"; }
+
+ virtual std::string message( int ev) const
+ {
+ switch (BOOST_SCOPED_ENUM_NATIVE(coroutine_errc)(ev))
+ {
+ case coroutine_errc::no_data:
+ return std::string("Operation not permitted because coroutine "
+ "has no valid result.");
+ }
+ return std::string("unspecified coroutine_errc value\n");
+ }
+};
+
+system::error_category const& coroutine_category() BOOST_NOEXCEPT
+{
+ static coroutines::coroutine_error_category cat;
+ return cat;
+}
+
+}}
Modified: branches/release/libs/coroutine/test/Jamfile.v2
==============================================================================
--- branches/release/libs/coroutine/test/Jamfile.v2 Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/test/Jamfile.v2 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -18,6 +18,7 @@
<library>../../test/build//boost_unit_test_framework
<library>/boost/context//boost_context
<library>/boost/coroutine//boost_coroutine
+ <library>/boost/system//boost_system
<toolset>gcc-4.7,<segmented-stacks>on:<cxxflags>-fsplit-stack
<toolset>gcc-4.8,<segmented-stacks>on:<cxxflags>-fsplit-stack
<link>static
Modified: branches/release/libs/coroutine/test/test_coroutine.cpp
==============================================================================
--- branches/release/libs/coroutine/test/test_coroutine.cpp Fri Jul 26 11:24:15 2013 (r85162)
+++ branches/release/libs/coroutine/test/test_coroutine.cpp 2013-07-26 11:44:40 EDT (Fri, 26 Jul 2013) (r85163)
@@ -30,7 +30,506 @@
int value1 = 0;
std::string value2 = "";
bool value3 = false;
+double value4 = .0;
+int * value5 = 0;
+int& value6 = value1;
+int& value7 = value1;
+int value8 = 0;
+int value9 = 0;
+#ifdef BOOST_COROUTINES_UNIDIRECT
+struct X : private boost::noncopyable
+{
+ X() { value1 = 7; }
+ ~X() { value1 = 0; }
+};
+
+class copyable
+{
+public:
+ bool state;
+
+ copyable() :
+ state( false)
+ {}
+
+ copyable( int) :
+ state( true)
+ {}
+
+ void operator()( coro::coroutine< int >::push_type &)
+ { value3 = state; }
+};
+
+class moveable
+{
+private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( moveable);
+
+public:
+ bool state;
+
+ moveable() :
+ state( false)
+ {}
+
+ moveable( int) :
+ state( true)
+ {}
+
+ moveable( BOOST_RV_REF( moveable) other) :
+ state( false)
+ { std::swap( state, other.state); }
+
+ moveable & operator=( BOOST_RV_REF( moveable) other)
+ {
+ if ( this == & other) return * this;
+ moveable tmp( boost::move( other) );
+ std::swap( state, tmp.state);
+ return * this;
+ }
+
+ void operator()( coro::coroutine< int >::push_type &)
+ { value3 = state; }
+};
+
+struct my_exception {};
+
+void f1( coro::coroutine< void >::push_type & c)
+{ c(); }
+
+void f2( coro::coroutine< void >::push_type &)
+{ ++value1; }
+
+void f3( coro::coroutine< void >::push_type & c)
+{
+ ++value1;
+ c();
+ ++value1;
+}
+
+void f4( coro::coroutine< int >::push_type & c)
+{
+ c( 3);
+ c( 7);
+}
+
+void f5( coro::coroutine< std::string >::push_type & c)
+{
+ std::string res("abc");
+ c( res);
+ res = "xyz";
+ c( res);
+}
+
+void f6( coro::coroutine< int >::pull_type & c)
+{ value1 = c.get(); }
+
+void f7( coro::coroutine< std::string >::pull_type & c)
+{ value2 = c.get(); }
+
+void f8( coro::coroutine< boost::tuple< double, double > >::pull_type & c)
+{
+ double x = 0, y = 0;
+ boost::tie( x, y) = c.get();
+ value4 = x + y;
+ c();
+ boost::tie( x, y) = c.get();
+ value4 = x + y;
+}
+
+void f9( coro::coroutine< int * >::pull_type & c)
+{ value5 = c.get(); }
+
+void f91( coro::coroutine< int const* >::pull_type & c)
+{ value5 = const_cast< int * >( c.get() ); }
+
+void f10( coro::coroutine< int & >::pull_type & c)
+{
+ int const& i = c.get();
+ value5 = const_cast< int * >( & i);
+}
+
+void f101( coro::coroutine< int const& >::pull_type & c)
+{
+ int const& i = c.get();
+ value5 = const_cast< int * >( & i);
+}
+
+void f11( coro::coroutine< boost::tuple< int, int > >::pull_type & c)
+{
+ boost::tie( value8, value9) = c.get();
+}
+
+void f12( coro::coroutine< void >::pull_type & c)
+{
+ X x_;
+ c();
+ c();
+}
+
+template< typename E >
+void f14( coro::coroutine< void >::pull_type &, E const& e)
+{ throw e; }
+
+void f16( coro::coroutine< int >::push_type & c)
+{
+ c( 1);
+ c( 2);
+ c( 3);
+ c( 4);
+ c( 5);
+}
+
+void f17( coro::coroutine< int >::pull_type & c, std::vector< int > & vec)
+{
+ int x = c.get();
+ while ( 5 > x)
+ {
+ vec.push_back( x);
+ x = c().get();
+ }
+}
+
+void f19( coro::coroutine< const int* >::push_type & c, std::vector< const int * > & vec)
+{
+ BOOST_FOREACH( const int * ptr, vec)
+ { c( ptr); }
+}
+
+void f20( coro::coroutine< int >::push_type &)
+{}
+
+void test_move()
+{
+ {
+ coro::coroutine< void >::pull_type coro1;
+ coro::coroutine< void >::pull_type coro2( f1);
+ BOOST_CHECK( ! coro1);
+ BOOST_CHECK( coro1.empty() );
+ BOOST_CHECK( coro2);
+ BOOST_CHECK( ! coro2.empty() );
+ coro1 = boost::move( coro2);
+ BOOST_CHECK( coro1);
+ BOOST_CHECK( ! coro1.empty() );
+ BOOST_CHECK( ! coro2);
+ BOOST_CHECK( coro2.empty() );
+ }
+
+ {
+ value3 = false;
+ copyable cp( 3);
+ BOOST_CHECK( cp.state);
+ BOOST_CHECK( ! value3);
+ coro::coroutine< int >::pull_type coro( cp);
+ BOOST_CHECK( cp.state);
+ BOOST_CHECK( value3);
+ }
+
+ {
+ value3 = false;
+ moveable mv( 7);
+ BOOST_CHECK( mv.state);
+ BOOST_CHECK( ! value3);
+ coro::coroutine< int >::pull_type coro( boost::move( mv) );
+ BOOST_CHECK( ! mv.state);
+ BOOST_CHECK( value3);
+ }
+}
+
+void test_complete()
+{
+ value1 = 0;
+
+ coro::coroutine< void >::pull_type coro( f2);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( ( int)1, value1);
+}
+
+void test_jump()
+{
+ value1 = 0;
+
+ coro::coroutine< void >::pull_type coro( f3);
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int)1, value1);
+ coro();
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( ( int)2, value1);
+}
+
+void test_result_int()
+{
+ coro::coroutine< int >::pull_type coro( f4);
+ BOOST_CHECK( coro);
+ int result = coro.get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( 3, result);
+ result = coro().get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( 7, result);
+ coro();
+ BOOST_CHECK( ! coro);
+}
+
+void test_result_string()
+{
+ coro::coroutine< std::string >::pull_type coro( f5);
+ BOOST_CHECK( coro);
+ std::string result = coro.get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( std::string("abc"), result);
+ result = coro().get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( std::string("xyz"), result);
+ coro();
+ BOOST_CHECK( ! coro);
+}
+
+void test_arg_int()
+{
+ value1 = 0;
+
+ coro::coroutine< int >::push_type coro( f6);
+ BOOST_CHECK( coro);
+ coro( 3);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( 3, value1);
+}
+
+void test_arg_string()
+{
+ value2 = "";
+
+ coro::coroutine< std::string >::push_type coro( f7);
+ BOOST_CHECK( coro);
+ coro( std::string("abc") );
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( std::string("abc"), value2);
+}
+
+void test_fp()
+{
+ value4 = 0;
+
+ coro::coroutine< boost::tuple< double, double > >::push_type coro( f8);
+ BOOST_CHECK( coro);
+ coro( boost::make_tuple( 7.35, 3.14) );
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( double) 10.49, value4);
+
+ value4 = 0;
+ coro( boost::make_tuple( 1.15, 3.14) );
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( ( double) 4.29, value4);
+}
+
+void test_ptr()
+{
+ value5 = 0;
+
+ int a = 3;
+ coro::coroutine< int * >::push_type coro( f9);
+ BOOST_CHECK( coro);
+ coro( & a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_const_ptr()
+{
+ value5 = 0;
+
+ int a = 3;
+ coro::coroutine< int const* >::push_type coro( f91);
+ BOOST_CHECK( coro);
+ coro( & a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_ref()
+{
+ value5 = 0;
+
+ int a = 3;
+ coro::coroutine< int & >::push_type coro( f10);
+ BOOST_CHECK( coro);
+ coro( a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_const_ref()
+{
+ value5 = 0;
+
+ int a = 3;
+ coro::coroutine< int const& >::push_type coro( f101);
+ BOOST_CHECK( coro);
+ coro( a);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( & a, value5);
+}
+
+void test_tuple()
+{
+ value8 = 0;
+ value9 = 0;
+
+ int a = 3, b = 7;
+ boost::tuple< int, int > tpl( a, b);
+ BOOST_CHECK_EQUAL( a, tpl.get< 0 >() );
+ BOOST_CHECK_EQUAL( b, tpl.get< 1 >() );
+ coro::coroutine< boost::tuple< int, int > >::push_type coro( f11);
+ BOOST_CHECK( coro);
+ coro( tpl);
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK_EQUAL( a, value8);
+ BOOST_CHECK_EQUAL( b, value9);
+}
+
+void test_unwind()
+{
+ value1 = 0;
+ {
+ coro::coroutine< void >::push_type coro( f12);
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+ coro();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ coro();
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ }
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+}
+
+void test_no_unwind()
+{
+ value1 = 0;
+ {
+ coro::coroutine< void >::push_type coro(
+ f12,
+ coro::attributes(
+ coro::stack_allocator::default_stacksize(),
+ coro::no_stack_unwind) );
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int) 0, value1);
+ coro();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ coro();
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+ }
+ BOOST_CHECK_EQUAL( ( int) 7, value1);
+}
+
+void test_exceptions()
+{
+ bool thrown = false;
+ std::runtime_error ex("abc");
+ try
+ {
+ coro::coroutine< void >::push_type coro( boost::bind( f14< std::runtime_error >, _1, ex) );
+ BOOST_CHECK( coro);
+ coro();
+ BOOST_CHECK( ! coro);
+ BOOST_CHECK( false);
+ }
+ catch ( std::runtime_error const&)
+ { thrown = true; }
+ catch ( std::exception const&)
+ {}
+ catch (...)
+ {}
+ BOOST_CHECK( thrown);
+}
+
+void test_output_iterator()
+{
+ {
+ std::vector< int > vec;
+ coro::coroutine< int >::pull_type coro( f16);
+ BOOST_FOREACH( int i, coro)
+ { vec.push_back( i); }
+ BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
+ BOOST_CHECK_EQUAL( ( int)1, vec[0] );
+ BOOST_CHECK_EQUAL( ( int)2, vec[1] );
+ BOOST_CHECK_EQUAL( ( int)3, vec[2] );
+ BOOST_CHECK_EQUAL( ( int)4, vec[3] );
+ BOOST_CHECK_EQUAL( ( int)5, vec[4] );
+ }
+ {
+ std::vector< int > vec;
+ coro::coroutine< int >::pull_type coro( f16);
+ coro::coroutine< int >::pull_type::iterator e = boost::end( coro);
+ for (
+ coro::coroutine< int >::pull_type::iterator i = boost::begin( coro);
+ i != e; ++i)
+ { vec.push_back( * i); }
+ BOOST_CHECK_EQUAL( ( std::size_t)5, vec.size() );
+ BOOST_CHECK_EQUAL( ( int)1, vec[0] );
+ BOOST_CHECK_EQUAL( ( int)2, vec[1] );
+ BOOST_CHECK_EQUAL( ( int)3, vec[2] );
+ BOOST_CHECK_EQUAL( ( int)4, vec[3] );
+ BOOST_CHECK_EQUAL( ( int)5, vec[4] );
+ }
+ {
+ int i1 = 1, i2 = 2, i3 = 3;
+ std::vector< const int* > vec_in;
+ vec_in.push_back( & i1);
+ vec_in.push_back( & i2);
+ vec_in.push_back( & i3);
+ std::vector< const int* > vec_out;
+ coro::coroutine< const int* >::pull_type coro( boost::bind( f19, _1, boost::ref( vec_in) ) );
+ coro::coroutine< const int* >::pull_type::const_iterator e = boost::const_end( coro);
+ for (
+ coro::coroutine< const int* >::pull_type::const_iterator i = boost::const_begin( coro);
+ i != e; ++i)
+ { vec_out.push_back( * i); }
+ BOOST_CHECK_EQUAL( ( std::size_t)3, vec_out.size() );
+ BOOST_CHECK_EQUAL( & i1, vec_out[0] );
+ BOOST_CHECK_EQUAL( & i2, vec_out[1] );
+ BOOST_CHECK_EQUAL( & i3, vec_out[2] );
+ }
+}
+
+void test_input_iterator()
+{
+ int counter = 0;
+ std::vector< int > vec;
+ coro::coroutine< int >::push_type coro(
+ boost::bind( f17, _1, boost::ref( vec) ) );
+ coro::coroutine< int >::push_type::iterator e( boost::end( coro) );
+ for ( coro::coroutine< int >::push_type::iterator i( boost::begin( coro) );
+ i != e; ++i)
+ {
+ i = ++counter;
+ }
+ BOOST_CHECK_EQUAL( ( std::size_t)4, vec.size() );
+ BOOST_CHECK_EQUAL( ( int)1, vec[0] );
+ BOOST_CHECK_EQUAL( ( int)2, vec[1] );
+ BOOST_CHECK_EQUAL( ( int)3, vec[2] );
+ BOOST_CHECK_EQUAL( ( int)4, vec[3] );
+}
+
+void test_invalid_result()
+{
+ bool catched = false;
+ coro::coroutine< int >::pull_type coro( f20);
+ BOOST_CHECK( ! coro);
+ try
+ {
+ int i = coro.get();
+ }
+ catch ( coro::invalid_result const& e)
+ {
+ catched = true;
+ }
+ BOOST_CHECK( catched);
+}
+#else
typedef coro::coroutine< void() > coro_void_void;
typedef coro::coroutine< int() > coro_int_void;
typedef coro::coroutine< std::string() > coro_string_void;
@@ -40,7 +539,9 @@
typedef coro::coroutine< int(int,int) > coro_int;
typedef coro::coroutine< int(int) > coro_int_int;
typedef coro::coroutine< int*(int*) > coro_ptr;
-typedef coro::coroutine< int const&(int const&) > coro_ref;
+typedef coro::coroutine< int const*(int const*) > coro_const_ptr;
+typedef coro::coroutine< int&(int&) > coro_ref;
+typedef coro::coroutine< int const&(int const&) > coro_const_ref;
typedef coro::coroutine< boost::tuple<int&,int&>(int&,int&) > coro_tuple;
typedef coro::coroutine< const int *() > coro_const_int_ptr_void;
@@ -146,9 +647,15 @@
void f9( coro_ptr::caller_type & self)
{ self( self.get() ); }
+void f91( coro_const_ptr::caller_type & self)
+{ self( self.get() ); }
+
void f10( coro_ref::caller_type & self)
{ self( self.get() ); }
+void f101( coro_const_ref::caller_type & self)
+{ self( self.get() ); }
+
void f11( coro_tuple::caller_type & self)
{
boost::tuple<int&,int&> tpl( self.get().get< 0 >(), self.get().get< 1 >() );
@@ -338,6 +845,18 @@
BOOST_CHECK( ! coro);
}
+void test_const_ptr()
+{
+ int a = 3;
+ coro_const_ptr coro( f91, & a);
+ BOOST_CHECK( coro);
+ int const* res = coro.get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( & a, res);
+ coro( & a);
+ BOOST_CHECK( ! coro);
+}
+
void test_ref()
{
int a = 3;
@@ -350,6 +869,18 @@
BOOST_CHECK( ! coro);
}
+void test_const_ref()
+{
+ int a = 3;
+ coro_const_ref coro( f101, a);
+ BOOST_CHECK( coro);
+ int const& res = coro.get();
+ BOOST_CHECK( coro);
+ BOOST_CHECK_EQUAL( & a, & res);
+ coro( a);
+ BOOST_CHECK( ! coro);
+}
+
void test_tuple()
{
int a = 3, b = 7;
@@ -507,6 +1038,7 @@
coro( -1);
BOOST_CHECK( ! coro);
}
+#endif
boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
{
@@ -516,15 +1048,21 @@
test->add( BOOST_TEST_CASE( & test_move) );
test->add( BOOST_TEST_CASE( & test_complete) );
test->add( BOOST_TEST_CASE( & test_jump) );
- test->add( BOOST_TEST_CASE( & test_pre) );
- test->add( BOOST_TEST_CASE( & test_post) );
test->add( BOOST_TEST_CASE( & test_result_int) );
test->add( BOOST_TEST_CASE( & test_result_string) );
test->add( BOOST_TEST_CASE( & test_arg_int) );
test->add( BOOST_TEST_CASE( & test_arg_string) );
test->add( BOOST_TEST_CASE( & test_fp) );
test->add( BOOST_TEST_CASE( & test_ptr) );
+ test->add( BOOST_TEST_CASE( & test_const_ptr) );
+#ifndef BOOST_COROUTINES_UNIDIRECT
+ test->add( BOOST_TEST_CASE( & test_pre) );
+ test->add( BOOST_TEST_CASE( & test_post) );
+#else
+ test->add( BOOST_TEST_CASE( & test_invalid_result) );
+#endif
test->add( BOOST_TEST_CASE( & test_ref) );
+ test->add( BOOST_TEST_CASE( & test_const_ref) );
test->add( BOOST_TEST_CASE( & test_tuple) );
test->add( BOOST_TEST_CASE( & test_unwind) );
test->add( BOOST_TEST_CASE( & test_no_unwind) );
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