summaryrefslogtreecommitdiff
path: root/boost/coroutine/detail/symmetric_coroutine_yield.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/coroutine/detail/symmetric_coroutine_yield.hpp')
-rw-r--r--boost/coroutine/detail/symmetric_coroutine_yield.hpp307
1 files changed, 307 insertions, 0 deletions
diff --git a/boost/coroutine/detail/symmetric_coroutine_yield.hpp b/boost/coroutine/detail/symmetric_coroutine_yield.hpp
new file mode 100644
index 0000000000..296676b6f9
--- /dev/null
+++ b/boost/coroutine/detail/symmetric_coroutine_yield.hpp
@@ -0,0 +1,307 @@
+
+// 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_SYMMETRIC_COROUTINE_YIELD_H
+#define BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H
+
+#include <algorithm>
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/move/move.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/utility/explicit_operator_bool.hpp>
+
+#include <boost/coroutine/detail/config.hpp>
+#include <boost/coroutine/exceptions.hpp>
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+template< typename R >
+class symmetric_coroutine_yield
+{
+private:
+ template< typename X, typename Y, typename Z >
+ friend class symmetric_coroutine_object;
+
+ typedef symmetric_coroutine_impl< R > impl_type;
+
+ struct dummy {};
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
+
+ impl_type * impl_;
+ R * result_;
+
+ symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT :
+ impl_( impl),
+ result_( result)
+ {
+ BOOST_ASSERT( 0 != impl_);
+ BOOST_ASSERT( 0 != result_);
+ }
+
+public:
+ symmetric_coroutine_yield() BOOST_NOEXCEPT :
+ impl_( 0),
+ result_( 0)
+ {}
+
+ symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
+ impl_( 0),
+ result_( 0)
+ { swap( other); }
+
+ symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
+ {
+ symmetric_coroutine_yield tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL();
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return 0 == impl_; }
+
+ void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
+ {
+ std::swap( impl_, other.impl_);
+ std::swap( result_, other.result_);
+ }
+
+ symmetric_coroutine_yield & operator()()
+ {
+ result_ = impl_->yield();
+ return * this;
+ }
+
+ template< typename Coro >
+ symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type x,
+ typename disable_if<
+ is_same< typename Coro::value_type, void >,
+ dummy*
+ >::type = 0)
+ {
+ BOOST_ASSERT( other);
+
+ result_ = impl_->yield_to( other.impl_, x);
+ return * this;
+ }
+
+ template< typename Coro >
+ symmetric_coroutine_yield & operator()( Coro & other,
+ typename enable_if<
+ is_same< typename Coro::value_type, void >,
+ dummy*
+ >::type = 0)
+ {
+ BOOST_ASSERT( other);
+
+ result_ = impl_->yield_to( other.impl_);
+ return * this;
+ }
+
+ R get() const
+ {
+ if ( 0 == result_)
+ boost::throw_exception(
+ invalid_result() );
+
+ return * result_;
+ }
+};
+
+template< typename R >
+class symmetric_coroutine_yield< R & >
+{
+private:
+ template< typename X, typename Y, typename Z >
+ friend class symmetric_coroutine_object;
+
+ typedef symmetric_coroutine_impl< R & > impl_type;
+
+ struct dummy {};
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
+
+ impl_type * impl_;
+ R * result_;
+
+ symmetric_coroutine_yield( impl_type * impl, R * result) BOOST_NOEXCEPT :
+ impl_( impl),
+ result_( result)
+ {
+ BOOST_ASSERT( 0 != impl_);
+ BOOST_ASSERT( 0 != result_);
+ }
+
+public:
+ symmetric_coroutine_yield() BOOST_NOEXCEPT :
+ impl_( 0),
+ result_( 0)
+ {}
+
+ symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
+ impl_( 0),
+ result_( 0)
+ { swap( other); }
+
+ symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
+ {
+ symmetric_coroutine_yield tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL();
+
+ bool operator!() const BOOST_NOEXCEPT
+ { return 0 == impl_; }
+
+ void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
+ {
+ std::swap( impl_, other.impl_);
+ std::swap( result_, other.result_);
+ }
+
+ symmetric_coroutine_yield & operator()()
+ {
+ result_ = impl_->yield();
+ return * this;
+ }
+
+ template< typename Coro >
+ symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x,
+ typename disable_if<
+ is_same< typename Coro::value_type, void >,
+ dummy*
+ >::type = 0)
+ {
+ BOOST_ASSERT( other);
+
+ result_ = impl_->yield_to( other.impl_, x);
+ return * this;
+ }
+
+ template< typename Coro >
+ symmetric_coroutine_yield & operator()( Coro & other,
+ typename enable_if<
+ is_same< typename Coro::value_type, void >,
+ dummy*
+ >::type = 0)
+ {
+ BOOST_ASSERT( other);
+
+ result_ = impl_->yield_to( other.impl_);
+ return * this;
+ }
+
+ R & get() const
+ {
+ if ( 0 == result_)
+ boost::throw_exception(
+ invalid_result() );
+
+ return * result_;
+ }
+};
+
+template<>
+class symmetric_coroutine_yield< void >
+{
+private:
+ template< typename X, typename Y, typename Z >
+ friend class symmetric_coroutine_object;
+
+ typedef symmetric_coroutine_impl< void > impl_type;
+
+ struct dummy {};
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE( symmetric_coroutine_yield)
+
+ impl_type * impl_;
+
+ symmetric_coroutine_yield( impl_type * impl) BOOST_NOEXCEPT :
+ impl_( impl)
+ { BOOST_ASSERT( 0 != impl_); }
+
+public:
+ symmetric_coroutine_yield() BOOST_NOEXCEPT :
+ impl_( 0)
+ {}
+
+ symmetric_coroutine_yield( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT :
+ impl_( 0)
+ { swap( other); }
+
+ symmetric_coroutine_yield & operator=( BOOST_RV_REF( symmetric_coroutine_yield) other) BOOST_NOEXCEPT
+ {
+ symmetric_coroutine_yield tmp( boost::move( other) );
+ swap( tmp);
+ return * this;
+ }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL();
+
+ inline bool operator!() const BOOST_NOEXCEPT
+ { return 0 == impl_; }
+
+ inline void swap( symmetric_coroutine_yield & other) BOOST_NOEXCEPT
+ { std::swap( impl_, other.impl_); }
+
+ inline symmetric_coroutine_yield & operator()()
+ {
+ impl_->yield();
+ return * this;
+ }
+
+ template< typename Coro >
+ symmetric_coroutine_yield & operator()( Coro & other, typename Coro::value_type & x,
+ typename disable_if<
+ is_same< typename Coro::value_type, void >,
+ dummy*
+ >::type = 0)
+ {
+ BOOST_ASSERT( other);
+
+ impl_->yield_to( other.impl_, x);
+ return * this;
+ }
+
+ template< typename Coro >
+ symmetric_coroutine_yield & operator()( Coro & other,
+ typename enable_if<
+ is_same< typename Coro::value_type, void >,
+ dummy*
+ >::type = 0)
+ {
+ BOOST_ASSERT( other);
+
+ impl_->yield_to( other.impl_);
+ return * this;
+ }
+};
+
+template< typename R >
+void swap( symmetric_coroutine_yield< R > & l, symmetric_coroutine_yield< R > & r)
+{ l.swap( r); }
+
+}}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_DETAIL_SYMMETRIC_COROUTINE_YIELD_H