• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 //          Copyright Oliver Kowalke 2014.
3 // Distributed under the Boost Software License, Version 1.0.
4 //    (See accompanying file LICENSE_1_0.txt or copy at
5 //          http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP
8 #define BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP
9 
10 #include <iterator>
11 #include <type_traits>
12 
13 #include <boost/assert.hpp>
14 #include <boost/config.hpp>
15 
16 #include <boost/coroutine2/detail/config.hpp>
17 #include <boost/coroutine2/detail/disable_overload.hpp>
18 
19 #ifdef BOOST_HAS_ABI_HEADERS
20 #  include BOOST_ABI_PREFIX
21 #endif
22 
23 namespace boost {
24 namespace coroutines2 {
25 namespace detail {
26 
27 template< typename T >
28 class push_coroutine {
29 private:
30     template< typename X >
31     friend class pull_coroutine;
32 
33     struct control_block;
34 
35     control_block   *   cb_;
36 
37     explicit push_coroutine( control_block *) noexcept;
38 
39 public:
40     template< typename Fn,
41               typename = detail::disable_overload< push_coroutine, Fn >
42     >
43     explicit push_coroutine( Fn &&);
44 
45     template< typename StackAllocator, typename Fn >
46     push_coroutine( StackAllocator &&, Fn &&);
47 
48     ~push_coroutine();
49 
50     push_coroutine( push_coroutine const&) = delete;
51     push_coroutine & operator=( push_coroutine const&) = delete;
52 
53     push_coroutine( push_coroutine &&) noexcept;
54 
operator =(push_coroutine && other)55     push_coroutine & operator=( push_coroutine && other) noexcept {
56         if ( this == & other) return * this;
57         std::swap( cb_, other.cb_);
58         return * this;
59     }
60 
61     push_coroutine & operator()( T const&);
62 
63     push_coroutine & operator()( T &&);
64 
65     explicit operator bool() const noexcept;
66 
67     bool operator!() const noexcept;
68 
69     class iterator {
70     private:
71         push_coroutine< T > *   c_{ nullptr };
72 
73     public:
74         typedef std::output_iterator_tag iterator_category;
75         typedef void value_type;
76         typedef void difference_type;
77         typedef void pointer;
78         typedef void reference;
79 
80         iterator() noexcept = default;
81 
iterator(push_coroutine<T> * c)82         explicit iterator( push_coroutine< T > * c) noexcept :
83             c_{ c } {
84         }
85 
operator =(T t)86         iterator & operator=( T t) {
87             BOOST_ASSERT( nullptr != c_);
88             if ( ! ( * c_)( t) ) {
89                 c_ = nullptr;
90             }
91             return * this;
92         }
93 
operator ==(iterator const & other) const94         bool operator==( iterator const& other) const noexcept {
95             return other.c_ == c_;
96         }
97 
operator !=(iterator const & other) const98         bool operator!=( iterator const& other) const noexcept {
99             return other.c_ != c_;
100         }
101 
operator *()102         iterator & operator*() noexcept {
103             return * this;
104         }
105 
operator ++()106         iterator & operator++() noexcept {
107             return * this;
108         }
109     };
110 };
111 
112 template< typename T >
113 class push_coroutine< T & > {
114 private:
115     template< typename X >
116     friend class pull_coroutine;
117 
118     struct control_block;
119 
120     control_block   *   cb_;
121 
122     explicit push_coroutine( control_block *) noexcept;
123 
124 public:
125     template< typename Fn,
126               typename = detail::disable_overload< push_coroutine, Fn >
127     >
128     explicit push_coroutine( Fn &&);
129 
130     template< typename StackAllocator, typename Fn >
131     push_coroutine( StackAllocator &&, Fn &&);
132 
133     ~push_coroutine();
134 
135     push_coroutine( push_coroutine const&) = delete;
136     push_coroutine & operator=( push_coroutine const&) = delete;
137 
138     push_coroutine( push_coroutine &&) noexcept;
139 
operator =(push_coroutine && other)140     push_coroutine & operator=( push_coroutine && other) noexcept {
141         if ( this == & other) return * this;
142         std::swap( cb_, other.cb_);
143         return * this;
144     }
145 
146     push_coroutine & operator()( T &);
147 
148     explicit operator bool() const noexcept;
149 
150     bool operator!() const noexcept;
151 
152     class iterator {
153     private:
154         push_coroutine< T & >   *   c_{ nullptr };
155 
156     public:
157         typedef std::output_iterator_tag iterator_category;
158         typedef void value_type;
159         typedef void difference_type;
160         typedef void pointer;
161         typedef void reference;
162 
163         iterator() noexcept = default;
164 
iterator(push_coroutine<T &> * c)165         explicit iterator( push_coroutine< T & > * c) noexcept :
166             c_{ c } {
167         }
168 
operator =(T & t)169         iterator & operator=( T & t) {
170             BOOST_ASSERT( nullptr != c_);
171             if ( ! ( * c_)( t) ) {
172                 c_ = nullptr;
173             }
174             return * this;
175         }
176 
operator ==(iterator const & other) const177         bool operator==( iterator const& other) const noexcept {
178             return other.c_ == c_;
179         }
180 
operator !=(iterator const & other) const181         bool operator!=( iterator const& other) const noexcept {
182             return other.c_ != c_;
183         }
184 
operator *()185         iterator & operator*() noexcept {
186             return * this;
187         }
188 
operator ++()189         iterator & operator++() noexcept {
190             return * this;
191         }
192     };
193 };
194 
195 template<>
196 class push_coroutine< void > {
197 private:
198     template< typename X >
199     friend class pull_coroutine;
200 
201     struct control_block;
202 
203     control_block   *   cb_;
204 
205     explicit push_coroutine( control_block *) noexcept;
206 
207 public:
208     template< typename Fn,
209               typename = detail::disable_overload< push_coroutine, Fn >
210     >
211     explicit push_coroutine( Fn &&);
212 
213     template< typename StackAllocator, typename Fn >
214     push_coroutine( StackAllocator &&, Fn &&);
215 
216     ~push_coroutine();
217 
218     push_coroutine( push_coroutine const&) = delete;
219     push_coroutine & operator=( push_coroutine const&) = delete;
220 
221     push_coroutine( push_coroutine &&) noexcept;
222 
operator =(push_coroutine && other)223     push_coroutine & operator=( push_coroutine && other) noexcept {
224         if ( this == & other) return * this;
225         std::swap( cb_, other.cb_);
226         return * this;
227     }
228 
229     push_coroutine & operator()();
230 
231     explicit operator bool() const noexcept;
232 
233     bool operator!() const noexcept;
234 };
235 
236 template< typename T >
237 typename push_coroutine< T >::iterator
begin(push_coroutine<T> & c)238 begin( push_coroutine< T > & c) {
239     return typename push_coroutine< T >::iterator( & c);
240 }
241 
242 template< typename T >
243 typename push_coroutine< T >::iterator
end(push_coroutine<T> &)244 end( push_coroutine< T > &) {
245     return typename push_coroutine< T >::iterator();
246 }
247 
248 }}}
249 
250 #ifdef BOOST_HAS_ABI_HEADERS
251 #  include BOOST_ABI_SUFFIX
252 #endif
253 
254 #endif // BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP
255