// Copyright Oliver Kowalke 2014. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP #define BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP #include #include #include #include #include #include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif namespace boost { namespace coroutines2 { namespace detail { template< typename T > class pull_coroutine { private: template< typename X > friend class push_coroutine; struct control_block; control_block * cb_; explicit pull_coroutine( control_block *) noexcept; bool has_result_() const noexcept; public: template< typename Fn, typename = detail::disable_overload< pull_coroutine, Fn > > explicit pull_coroutine( Fn &&); template< typename StackAllocator, typename Fn > pull_coroutine( StackAllocator &&, Fn &&); ~pull_coroutine(); pull_coroutine( pull_coroutine const&) = delete; pull_coroutine & operator=( pull_coroutine const&) = delete; pull_coroutine( pull_coroutine &&) noexcept; pull_coroutine & operator=( pull_coroutine && other) noexcept { std::swap( cb_, other.cb_); return * this; } pull_coroutine & operator()(); explicit operator bool() const noexcept; bool operator!() const noexcept; T get() noexcept; class iterator { private: pull_coroutine< T > * c_{ nullptr }; void fetch_() noexcept { BOOST_ASSERT( nullptr != c_); if ( ! ( * c_) ) { c_ = nullptr; return; } } void increment_() { BOOST_ASSERT( nullptr != c_); BOOST_ASSERT( * c_); ( * c_)(); fetch_(); } public: typedef std::input_iterator_tag iterator_category; typedef typename std::remove_reference< T >::type value_type; typedef std::ptrdiff_t difference_type; typedef value_type * pointer; typedef value_type & reference; typedef pointer pointer_t; typedef reference reference_t; iterator() noexcept = default; explicit iterator( pull_coroutine< T > * c) noexcept : c_{ c } { fetch_(); } bool operator==( iterator const& other) const noexcept { return other.c_ == c_; } bool operator!=( iterator const& other) const noexcept { return other.c_ != c_; } iterator & operator++() { increment_(); return * this; } void operator++( int) { increment_(); } reference_t operator*() const noexcept { return c_->cb_->get(); } pointer_t operator->() const noexcept { return std::addressof( c_->cb_->get() ); } }; friend class iterator; }; template< typename T > class pull_coroutine< T & > { private: template< typename X > friend class push_coroutine; struct control_block; control_block * cb_; explicit pull_coroutine( control_block *) noexcept; bool has_result_() const noexcept; public: template< typename Fn, typename = detail::disable_overload< pull_coroutine, Fn > > explicit pull_coroutine( Fn &&); template< typename StackAllocator, typename Fn > pull_coroutine( StackAllocator &&, Fn &&); ~pull_coroutine(); pull_coroutine( pull_coroutine const&) = delete; pull_coroutine & operator=( pull_coroutine const&) = delete; pull_coroutine( pull_coroutine &&) noexcept; pull_coroutine & operator=( pull_coroutine && other) noexcept { std::swap( cb_, other.cb_); return * this; } pull_coroutine & operator()(); explicit operator bool() const noexcept; bool operator!() const noexcept; T & get() noexcept; class iterator { private: pull_coroutine< T & > * c_{ nullptr }; void fetch_() noexcept { BOOST_ASSERT( nullptr != c_); if ( ! ( * c_) ) { c_ = nullptr; return; } } void increment_() { BOOST_ASSERT( nullptr != c_); BOOST_ASSERT( * c_); ( * c_)(); fetch_(); } public: typedef std::input_iterator_tag iterator_category; typedef typename std::remove_reference< T >::type value_type; typedef std::ptrdiff_t difference_type; typedef value_type * pointer; typedef value_type & reference; typedef pointer pointer_t; typedef reference reference_t; iterator() noexcept = default; explicit iterator( pull_coroutine< T & > * c) noexcept : c_{ c } { fetch_(); } bool operator==( iterator const& other) const noexcept { return other.c_ == c_; } bool operator!=( iterator const& other) const noexcept { return other.c_ != c_; } iterator & operator++() { increment_(); return * this; } void operator++( int) { increment_(); } reference_t operator*() const noexcept { return c_->cb_->get(); } pointer_t operator->() const noexcept { return std::addressof( c_->cb_->get() ); } }; friend class iterator; }; template<> class pull_coroutine< void > { private: template< typename X > friend class push_coroutine; struct control_block; control_block * cb_; explicit pull_coroutine( control_block *) noexcept; public: template< typename Fn, typename = detail::disable_overload< pull_coroutine, Fn > > explicit pull_coroutine( Fn &&); template< typename StackAllocator, typename Fn > pull_coroutine( StackAllocator &&, Fn &&); ~pull_coroutine(); pull_coroutine( pull_coroutine const&) = delete; pull_coroutine & operator=( pull_coroutine const&) = delete; pull_coroutine( pull_coroutine &&) noexcept; pull_coroutine & operator=( pull_coroutine && other) noexcept { std::swap( cb_, other.cb_); return * this; } pull_coroutine & operator()(); explicit operator bool() const noexcept; bool operator!() const noexcept; }; template< typename T > typename pull_coroutine< T >::iterator begin( pull_coroutine< T > & c) { return typename pull_coroutine< T >::iterator( & c); } template< typename T > typename pull_coroutine< T >::iterator end( pull_coroutine< T > &) { return typename pull_coroutine< T >::iterator(); } }}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif #endif // BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP