• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 //          Copyright Oliver Kowalke 2013.
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_FIBERS_FUTURE_HPP
8 #define BOOST_FIBERS_FUTURE_HPP
9 
10 #include <algorithm>
11 #include <chrono>
12 #include <exception>
13 #include <utility>
14 
15 #include <boost/config.hpp>
16 
17 #include <boost/fiber/detail/config.hpp>
18 #include <boost/fiber/exceptions.hpp>
19 #include <boost/fiber/future/detail/shared_state.hpp>
20 #include <boost/fiber/future/future_status.hpp>
21 
22 namespace boost {
23 namespace fibers {
24 namespace detail {
25 
26 template< typename R >
27 struct future_base {
28     typedef typename shared_state< R >::ptr_type   ptr_type;
29 
30     ptr_type           state_{};
31 
32     future_base() = default;
33 
future_baseboost::fibers::detail::future_base34     explicit future_base( ptr_type  p) noexcept :
35         state_{std::move( p )} {
36     }
37 
38     ~future_base() = default;
39 
future_baseboost::fibers::detail::future_base40     future_base( future_base const& other) :
41         state_{ other.state_ } {
42     }
43 
future_baseboost::fibers::detail::future_base44     future_base( future_base && other) noexcept :
45         state_{ other.state_ } {
46         other.state_.reset();
47     }
48 
operator =boost::fibers::detail::future_base49     future_base & operator=( future_base const& other) noexcept {
50         if ( BOOST_LIKELY( this != & other) ) {
51             state_ = other.state_;
52         }
53         return * this;
54     }
55 
operator =boost::fibers::detail::future_base56     future_base & operator=( future_base && other) noexcept {
57         if ( BOOST_LIKELY( this != & other) ) {
58             state_ = other.state_;
59             other.state_.reset();
60         }
61         return * this;
62     }
63 
validboost::fibers::detail::future_base64     bool valid() const noexcept {
65         return nullptr != state_.get();
66     }
67 
get_exception_ptrboost::fibers::detail::future_base68     std::exception_ptr get_exception_ptr() {
69         if ( BOOST_UNLIKELY( ! valid() ) ) {
70             throw future_uninitialized{};
71         }
72         return state_->get_exception_ptr();
73     }
74 
waitboost::fibers::detail::future_base75     void wait() const {
76         if ( BOOST_UNLIKELY( ! valid() ) ) {
77             throw future_uninitialized{};
78         }
79         state_->wait();
80     }
81 
82     template< typename Rep, typename Period >
wait_forboost::fibers::detail::future_base83     future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const {
84         if ( BOOST_UNLIKELY( ! valid() ) ) {
85             throw future_uninitialized{};
86         }
87         return state_->wait_for( timeout_duration);
88     }
89 
90     template< typename Clock, typename Duration >
wait_untilboost::fibers::detail::future_base91     future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const {
92         if ( BOOST_UNLIKELY( ! valid() ) ) {
93             throw future_uninitialized{};
94         }
95         return state_->wait_until( timeout_time);
96     }
97 };
98 
99 template< typename R >
100 struct promise_base;
101 
102 }
103 
104 template< typename R >
105 class shared_future;
106 
107 template< typename Signature >
108 class packaged_task;
109 
110 template< typename R >
111 class future : private detail::future_base< R > {
112 private:
113     typedef detail::future_base< R >  base_type;
114 
115     friend struct detail::promise_base< R >;
116     friend class shared_future< R >;
117     template< typename Signature >
118     friend class packaged_task;
119 
future(typename base_type::ptr_type const & p)120     explicit future( typename base_type::ptr_type const& p) noexcept :
121         base_type{ p } {
122     }
123 
124 public:
125     future() = default;
126 
127     future( future const&) = delete;
128     future & operator=( future const&) = delete;
129 
future(future && other)130     future( future && other) noexcept :
131         base_type{ std::move( other) } {
132     }
133 
operator =(future && other)134     future & operator=( future && other) noexcept {
135         if ( BOOST_LIKELY( this != & other) ) {
136             base_type::operator=( std::move( other) );
137         }
138         return * this;
139     }
140 
141     shared_future< R > share();
142 
get()143     R get() {
144         if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
145             throw future_uninitialized{};
146         }
147         typename base_type::ptr_type tmp{};
148         tmp.swap( base_type::state_);
149         return std::move( tmp->get() );
150     }
151 
152     using base_type::valid;
153     using base_type::get_exception_ptr;
154     using base_type::wait;
155     using base_type::wait_for;
156     using base_type::wait_until;
157 };
158 
159 template< typename R >
160 class future< R & > : private detail::future_base< R & > {
161 private:
162     typedef detail::future_base< R & >  base_type;
163 
164     friend struct detail::promise_base< R & >;
165     friend class shared_future< R & >;
166     template< typename Signature >
167     friend class packaged_task;
168 
future(typename base_type::ptr_type const & p)169     explicit future( typename base_type::ptr_type const& p) noexcept :
170         base_type{ p  } {
171     }
172 
173 public:
174     future() = default;
175 
176     future( future const&) = delete;
177     future & operator=( future const&) = delete;
178 
future(future && other)179     future( future && other) noexcept :
180         base_type{ std::move( other) } {
181     }
182 
operator =(future && other)183     future & operator=( future && other) noexcept {
184         if ( BOOST_LIKELY( this != & other) ) {
185             base_type::operator=( std::move( other) );
186         }
187         return * this;
188     }
189 
190     shared_future< R & > share();
191 
get()192     R & get() {
193         if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
194             throw future_uninitialized{};
195         }
196         typename base_type::ptr_type tmp{};
197         tmp.swap( base_type::state_);
198         return tmp->get();
199     }
200 
201     using base_type::valid;
202     using base_type::get_exception_ptr;
203     using base_type::wait;
204     using base_type::wait_for;
205     using base_type::wait_until;
206 };
207 
208 template<>
209 class future< void > : private detail::future_base< void > {
210 private:
211     typedef detail::future_base< void >  base_type;
212 
213     friend struct detail::promise_base< void >;
214     friend class shared_future< void >;
215     template< typename Signature >
216     friend class packaged_task;
217 
future(base_type::ptr_type const & p)218     explicit future( base_type::ptr_type const& p) noexcept :
219         base_type{ p } {
220     }
221 
222 public:
223     future() = default;
224 
225     future( future const&) = delete;
226     future & operator=( future const&) = delete;
227 
228     inline
future(future && other)229     future( future && other) noexcept :
230         base_type{ std::move( other) } {
231     }
232 
233     inline
operator =(future && other)234     future & operator=( future && other) noexcept {
235         if ( BOOST_LIKELY( this != & other) ) {
236             base_type::operator=( std::move( other) );
237         }
238         return * this;
239     }
240 
241     shared_future< void > share();
242 
243     inline
get()244     void get() {
245         if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
246             throw future_uninitialized{};
247         }
248         base_type::ptr_type tmp{};
249         tmp.swap( base_type::state_);
250         tmp->get();
251     }
252 
253     using base_type::valid;
254     using base_type::get_exception_ptr;
255     using base_type::wait;
256     using base_type::wait_for;
257     using base_type::wait_until;
258 };
259 
260 
261 template< typename R >
262 class shared_future : private detail::future_base< R > {
263 private:
264     typedef detail::future_base< R >   base_type;
265 
shared_future(typename base_type::ptr_type const & p)266     explicit shared_future( typename base_type::ptr_type const& p) noexcept :
267         base_type{ p } {
268     }
269 
270 public:
271     shared_future() = default;
272 
273     ~shared_future() = default;
274 
shared_future(shared_future const & other)275     shared_future( shared_future const& other) :
276         base_type{ other } {
277     }
278 
shared_future(shared_future && other)279     shared_future( shared_future && other) noexcept :
280         base_type{ std::move( other) } {
281     }
282 
shared_future(future<R> && other)283     shared_future( future< R > && other) noexcept :
284         base_type{ std::move( other) } {
285     }
286 
operator =(shared_future const & other)287     shared_future & operator=( shared_future const& other) noexcept {
288         if ( BOOST_LIKELY( this != & other) ) {
289             base_type::operator=( other);
290         }
291         return * this;
292     }
293 
operator =(shared_future && other)294     shared_future & operator=( shared_future && other) noexcept {
295         if ( BOOST_LIKELY( this != & other) ) {
296             base_type::operator=( std::move( other) );
297         }
298         return * this;
299     }
300 
operator =(future<R> && other)301     shared_future & operator=( future< R > && other) noexcept {
302         base_type::operator=( std::move( other) );
303         return * this;
304     }
305 
get() const306     R const& get() const {
307         if ( BOOST_UNLIKELY( ! valid() ) ) {
308             throw future_uninitialized{};
309         }
310         return base_type::state_->get();
311     }
312 
313     using base_type::valid;
314     using base_type::get_exception_ptr;
315     using base_type::wait;
316     using base_type::wait_for;
317     using base_type::wait_until;
318 };
319 
320 template< typename R >
321 class shared_future< R & > : private detail::future_base< R & > {
322 private:
323     typedef detail::future_base< R & >  base_type;
324 
shared_future(typename base_type::ptr_type const & p)325     explicit shared_future( typename base_type::ptr_type const& p) noexcept :
326         base_type{ p } {
327     }
328 
329 public:
330     shared_future() = default;
331 
332     ~shared_future() = default;
333 
shared_future(shared_future const & other)334     shared_future( shared_future const& other) :
335         base_type{ other } {
336     }
337 
shared_future(shared_future && other)338     shared_future( shared_future && other) noexcept :
339         base_type{ std::move( other) } {
340     }
341 
shared_future(future<R &> && other)342     shared_future( future< R & > && other) noexcept :
343         base_type{ std::move( other) } {
344     }
345 
operator =(shared_future const & other)346     shared_future & operator=( shared_future const& other) noexcept {
347         if ( BOOST_LIKELY( this != & other) ) {
348             base_type::operator=( other);
349         }
350         return * this;
351     }
352 
operator =(shared_future && other)353     shared_future & operator=( shared_future && other) noexcept {
354         if ( BOOST_LIKELY( this != & other) ) {
355             base_type::operator=( std::move( other) );
356         }
357         return * this;
358     }
359 
operator =(future<R &> && other)360     shared_future & operator=( future< R & > && other) noexcept {
361         base_type::operator=( std::move( other) );
362         return * this;
363     }
364 
get() const365     R & get() const {
366         if ( BOOST_UNLIKELY( ! valid() ) ) {
367             throw future_uninitialized{};
368         }
369         return base_type::state_->get();
370     }
371 
372     using base_type::valid;
373     using base_type::get_exception_ptr;
374     using base_type::wait;
375     using base_type::wait_for;
376     using base_type::wait_until;
377 };
378 
379 template<>
380 class shared_future< void > : private detail::future_base< void > {
381 private:
382     typedef detail::future_base< void > base_type;
383 
shared_future(base_type::ptr_type const & p)384     explicit shared_future( base_type::ptr_type const& p) noexcept :
385         base_type{ p } {
386     }
387 
388 public:
389     shared_future() = default;
390 
391     ~shared_future() = default;
392 
393     inline
shared_future(shared_future const & other)394     shared_future( shared_future const& other) :
395         base_type{ other } {
396     }
397 
398     inline
shared_future(shared_future && other)399     shared_future( shared_future && other) noexcept :
400         base_type{ std::move( other) } {
401     }
402 
403     inline
shared_future(future<void> && other)404     shared_future( future< void > && other) noexcept :
405         base_type{ std::move( other) } {
406     }
407 
408     inline
operator =(shared_future const & other)409     shared_future & operator=( shared_future const& other) noexcept {
410         if ( BOOST_LIKELY( this != & other) ) {
411             base_type::operator=( other);
412         }
413         return * this;
414     }
415 
416     inline
operator =(shared_future && other)417     shared_future & operator=( shared_future && other) noexcept {
418         if ( BOOST_LIKELY( this != & other) ) {
419             base_type::operator=( std::move( other) );
420         }
421         return * this;
422     }
423 
424     inline
operator =(future<void> && other)425     shared_future & operator=( future< void > && other) noexcept {
426         base_type::operator=( std::move( other) );
427         return * this;
428     }
429 
430     inline
get() const431     void get() const {
432         if ( BOOST_UNLIKELY( ! valid() ) ) {
433             throw future_uninitialized{};
434         }
435         base_type::state_->get();
436     }
437 
438     using base_type::valid;
439     using base_type::get_exception_ptr;
440     using base_type::wait;
441     using base_type::wait_for;
442     using base_type::wait_until;
443 };
444 
445 
446 template< typename R >
447 shared_future< R >
share()448 future< R >::share() {
449     if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
450         throw future_uninitialized{};
451     }
452     return shared_future< R >{ std::move( * this) };
453 }
454 
455 template< typename R >
456 shared_future< R & >
share()457 future< R & >::share() {
458     if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
459         throw future_uninitialized{};
460     }
461     return shared_future< R & >{ std::move( * this) };
462 }
463 
464 inline
465 shared_future< void >
share()466 future< void >::share() {
467     if ( BOOST_UNLIKELY( ! base_type::valid() ) ) {
468         throw future_uninitialized{};
469     }
470     return shared_future< void >{ std::move( * this) };
471 }
472 
473 }}
474 
475 #endif
476