boost/coroutine/v1/detail/coroutine_op.hpp
// 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_OP_H #define BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H #include <iterator> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/context/fcontext.hpp> #include <boost/optional.hpp> #include <boost/preprocessor/arithmetic/add.hpp> #include <boost/preprocessor/arithmetic/sub.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/punctuation/comma_if.hpp> #include <boost/preprocessor/repetition/repeat_from_to.hpp> #include <boost/type_traits/function_traits.hpp> #include <boost/type_traits/remove_reference.hpp> #include <boost/coroutine/detail/config.hpp> #include <boost/coroutine/v1/detail/arg.hpp> #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines { namespace detail { template< typename Signature, typename D, typename Result, int arity > struct coroutine_op; template< typename Signature, typename D > struct coroutine_op< Signature, D, void, 0 > { D & operator()() { BOOST_ASSERT( static_cast< D * >( this)->impl_); BOOST_ASSERT( ! static_cast< D * >( this)->impl_->is_complete() ); static_cast< D * >( this)->impl_->resume(); return * static_cast< D * >( this); } }; template< typename Signature, typename D, typename Result > struct coroutine_op< Signature, D, Result, 0 > { class iterator : public std::iterator< std::input_iterator_tag, typename remove_reference< Result >::type > { private: D * dp_; optional< Result > val_; void fetch_() { BOOST_ASSERT( dp_); if ( ! dp_->has_result() ) { dp_ = 0; val_ = none; return; } val_ = dp_->get(); } void increment_() { BOOST_ASSERT( dp_); BOOST_ASSERT( * dp_); ( * dp_)(); fetch_(); } public: typedef typename iterator::pointer pointer_t; typedef typename iterator::reference reference_t; iterator() : dp_( 0), val_() {} explicit iterator( D * dp) : dp_( dp), val_() { fetch_(); } iterator( iterator const& other) : dp_( other.dp_), val_( other.val_) {} iterator & operator=( iterator const& other) { if ( this == & other) return * this; dp_ = other.dp_; val_ = other.val_; return * this; } bool operator==( iterator const& other) { return other.dp_ == dp_ && other.val_ == val_; } bool operator!=( iterator const& other) { return other.dp_ != dp_ || other.val_ != val_; } iterator & operator++() { increment_(); return * this; } iterator operator++( int) { iterator tmp( * this); ++*this; return tmp; } reference_t operator*() const { return const_cast< optional< Result > & >( val_).get(); } pointer_t operator->() const { return const_cast< optional< Result > & >( val_).get_ptr(); } }; class const_iterator : public std::iterator< std::input_iterator_tag, const typename remove_reference< Result >::type > { private: D * dp_; optional< Result > val_; void fetch_() { BOOST_ASSERT( dp_); if ( ! dp_->has_result() ) { dp_ = 0; val_ = none; return; } val_ = dp_->get(); } void increment_() { BOOST_ASSERT( dp_); BOOST_ASSERT( * dp_); ( * dp_)(); fetch_(); } public: typedef typename const_iterator::pointer pointer_t; typedef typename const_iterator::reference reference_t; const_iterator() : dp_( 0), val_() {} explicit const_iterator( D const* dp) : dp_( const_cast< D * >( dp) ), val_() { fetch_(); } const_iterator( const_iterator const& other) : dp_( other.dp_), val_( other.val_) {} const_iterator & operator=( const_iterator const& other) { if ( this == & other) return * this; dp_ = other.dp_; val_ = other.val_; return * this; } bool operator==( const_iterator const& other) { return other.dp_ == dp_ && other.val_ == val_; } bool operator!=( const_iterator const& other) { return other.dp_ != dp_ || other.val_ != val_; } const_iterator & operator++() { increment_(); return * this; } const_iterator operator++( int) { const_iterator tmp( * this); ++*this; return tmp; } reference_t operator*() const { return val_.get(); } pointer_t operator->() const { return val_.get_ptr(); } }; D & operator()() { BOOST_ASSERT( static_cast< D * >( this)->impl_); BOOST_ASSERT( ! static_cast< D * >( this)->impl_->is_complete() ); static_cast< D * >( this)->impl_->resume(); return * static_cast< D * >( this); } }; template< typename Signature, typename D > struct coroutine_op< Signature, D, void, 1 > { typedef typename arg< Signature >::type arg_type; class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > { private: D * dp_; public: iterator() : dp_( 0) {} explicit iterator( D * dp) : dp_( dp) {} iterator & operator=( arg_type a1) { BOOST_ASSERT( dp_); if ( ! ( * dp_)( a1) ) dp_ = 0; return * this; } bool operator==( iterator const& other) { return other.dp_ == dp_; } bool operator!=( iterator const& other) { return other.dp_ != dp_; } iterator & operator*() { return * this; } iterator & operator++() { return * this; } }; struct const_iterator; D & operator()( arg_type a1) { BOOST_ASSERT( static_cast< D * >( this)->impl_); BOOST_ASSERT( ! static_cast< D * >( this)->impl_->is_complete() ); static_cast< D * >( this)->impl_->resume( a1); return * static_cast< D * >( this); } }; template< typename Signature, typename D, typename Result > struct coroutine_op< Signature, D, Result, 1 > { typedef typename arg< Signature >::type arg_type; D & operator()( arg_type a1) { BOOST_ASSERT( static_cast< D * >( this)->impl_); BOOST_ASSERT( ! static_cast< D * >( this)->impl_->is_complete() ); static_cast< D * >( this)->impl_->resume( a1); return * static_cast< D * >( this); } }; #define BOOST_COROUTINE_OP_COMMA(n) BOOST_PP_COMMA_IF(BOOST_PP_SUB(n,1)) #define BOOST_COROUTINE_OP_VAL(z,n,unused) BOOST_COROUTINE_OP_COMMA(n) BOOST_PP_CAT(a,n) #define BOOST_COROUTINE_OP_VALS(n) BOOST_PP_REPEAT_FROM_TO(1,BOOST_PP_ADD(n,1),BOOST_COROUTINE_OP_VAL,~) #define BOOST_COROUTINE_OP_ARG_TYPE(n) \ typename function_traits< Signature >::BOOST_PP_CAT(BOOST_PP_CAT(arg,n),_type) #define BOOST_COROUTINE_OP_ARG(z,n,unused) BOOST_COROUTINE_OP_COMMA(n) BOOST_COROUTINE_OP_ARG_TYPE(n) BOOST_PP_CAT(a,n) #define BOOST_COROUTINE_OP_ARGS(n) BOOST_PP_REPEAT_FROM_TO(1,BOOST_PP_ADD(n,1),BOOST_COROUTINE_OP_ARG,~) #define BOOST_COROUTINE_OP(z,n,unused) \ template< typename Signature, typename D, typename Result > \ struct coroutine_op< Signature, D, Result, n > \ { \ D & operator()( BOOST_COROUTINE_OP_ARGS(n)) \ { \ BOOST_ASSERT( static_cast< D * >( this)->impl_); \ BOOST_ASSERT( ! static_cast< D * >( this)->impl_->is_complete() ); \ \ static_cast< D * >( this)->impl_->resume(BOOST_COROUTINE_OP_VALS(n)); \ \ return * static_cast< D * >( this); \ } \ }; BOOST_PP_REPEAT_FROM_TO(2,11,BOOST_COROUTINE_OP,~) #undef BOOST_COROUTINE_OP #undef BOOST_COROUTINE_OP_ARGS #undef BOOST_COROUTINE_OP_ARG #undef BOOST_COROUTINE_OP_ARG_TYPE #undef BOOST_COROUTINE_OP_VALS #undef BOOST_COROUTINE_OP_VAL #undef BOOST_COROUTINE_OP_COMMA }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES_V1_DETAIL_COROUTINE_OP_H