/home/users/khuck/src/hpx-lsu/hpx/lcos/future.hpp

Line% of fetchesSource
1  
//  Copyright (c) 2007-2015 Hartmut Kaiser
2  
//  Copyright (c) 2013 Agustin Berge
3  
//
4  
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
7  
#if !defined(HPX_LCOS_FUTURE_MAR_06_2012_1059AM)
8  
#define HPX_LCOS_FUTURE_MAR_06_2012_1059AM
9  
10  
#include <hpx/config.hpp>
11  
#include <hpx/error_code.hpp>
12  
#include <hpx/lcos/detail/future_data.hpp>
13  
#include <hpx/lcos_fwd.hpp>
14  
#include <hpx/runtime/actions/continuation_fwd.hpp>
15  
#include <hpx/runtime/launch_policy.hpp>
16  
#include <hpx/throw_exception.hpp>
17  
#include <hpx/traits/acquire_shared_state.hpp>
18  
#include <hpx/traits/concepts.hpp>
19  
#include <hpx/traits/future_access.hpp>
20  
#include <hpx/traits/future_traits.hpp>
21  
#include <hpx/traits/is_callable.hpp>
22  
#include <hpx/traits/is_executor.hpp>
23  
#include <hpx/traits/is_launch_policy.hpp>
24  
#include <hpx/util/always_void.hpp>
25  
#include <hpx/util/bind.hpp>
26  
#include <hpx/util/decay.hpp>
27  
#include <hpx/util/function.hpp>
28  
#include <hpx/util/identity.hpp>
29  
#include <hpx/util/invoke.hpp>
30  
#include <hpx/util/lazy_conditional.hpp>
31  
#include <hpx/util/lazy_enable_if.hpp>
32  
#include <hpx/util/result_of.hpp>
33  
#include <hpx/util/steady_clock.hpp>
34  
#include <hpx/util/void_guard.hpp>
35  
36  
#if defined(HPX_HAVE_AWAIT)
37  
    #include <hpx/lcos/detail/future_await_traits.hpp>
38  
#endif
39  
40  
#include <boost/exception_ptr.hpp>
41  
#include <boost/intrusive_ptr.hpp>
42  
43  
#include <iterator>
44  
#include <type_traits>
45  
#include <utility>
46  
47  
namespace hpx { namespace lcos { namespace detail
48  
{
49  
    ///////////////////////////////////////////////////////////////////////////
50  
    enum future_state
51  
    {
52  
        invalid = 0,
53  
        has_value = 1,
54  
        has_exception = 2
55  
    };
56  
57  
    template <typename Archive, typename Future>
58  
    typename std::enable_if<
59  
        !std::is_void<typename hpx::traits::future_traits<Future>::type>::value
60  
    >::type serialize_future_load(Archive& ar, Future& f)
61  
    {
62  
        typedef typename hpx::traits::future_traits<Future>::type value_type;
63  
        typedef lcos::detail::future_data<value_type> shared_state;
64  
65  
        int state = future_state::invalid;
66  
        ar >> state;
67  
        if (state == future_state::has_value)
68  
        {
69  
            value_type value;
70  
            ar >> value;
71  
72  
            boost::intrusive_ptr<shared_state> p(new shared_state());
73  
            p->set_value(std::move(value));
74  
75  
            f = hpx::traits::future_access<Future>::create(std::move(p));
76  
        } else if (state == future_state::has_exception) {
77  
            boost::exception_ptr exception;
78  
            ar >> exception;
79  
80  
            boost::intrusive_ptr<shared_state> p(new shared_state());
81  
            p->set_exception(exception);
82  
83  
            f = hpx::traits::future_access<Future>::create(std::move(p));
84  
        } else if (state == future_state::invalid) {
85  
            f = Future();
86  
        } else {
87  
            HPX_ASSERT(false);
88  
        }
89  
    }
90  
91  
    template <typename Archive, typename Future>
92  
    typename std::enable_if<
93  
        std::is_void<typename hpx::traits::future_traits<Future>::type>::value
94  
    >::type serialize_future_load(Archive& ar, Future& f) //-V659
95  
    {
96  
        typedef lcos::detail::future_data<void> shared_state;
97  
98  
        int state = future_state::invalid;
99  
        ar >> state;
100  
        if (state == future_state::has_value)
101  
        {
102  
            boost::intrusive_ptr<shared_state> p(new shared_state());
103  
            p->set_value(hpx::util::unused);
104  
105  
            f = hpx::traits::future_access<Future>::create(std::move(p));
106  
        } else if (state == future_state::has_exception) {
107  
            boost::exception_ptr exception;
108  
            ar >> exception;
109  
110  
            boost::intrusive_ptr<shared_state> p(new shared_state());
111  
            p->set_exception(exception);
112  
113  
            f = hpx::traits::future_access<Future>::create(std::move(p));
114  
        } else if (state == future_state::invalid) {
115  
            f = Future();
116  
        } else {
117  
            HPX_ASSERT(false);
118  
        }
119  
    }
120  
121  
    template <typename Archive, typename Future>
122  
    typename std::enable_if<
123  
        !std::is_void<typename hpx::traits::future_traits<Future>::type>::value
124  
    >::type serialize_future_save(Archive& ar, Future const& f)
125  
    {
126  
        typedef typename hpx::traits::future_traits<Future>::result_type value_type;
127  
128  
        int state = future_state::invalid;
129  
        if(ar.is_preprocessing())
130  
        {
131  
            if(!f.is_ready())
132  
            {
133  
                typename hpx::traits::detail::shared_state_ptr_for<Future>::type state
134  
                    = hpx::traits::future_access<Future>::get_shared_state(f);
135  
136  
                state->execute_deferred();
137  
138  
                ar.await_future(f);
139  
            }
140  
            else
141  
            {
142  
                if(f.is_ready())
143  
                {
144  
                    if (f.has_value())
145  
                    {
146  
                        value_type const & value =
147  
                            *hpx::traits::future_access<Future>::
148  
                                get_shared_state(f)->get_result();
149  
                        ar << state << value; //-V128
150  
                    } else if (f.has_exception()) {
151  
                        state = future_state::has_exception;
152  
                        boost::exception_ptr exception = f.get_exception_ptr();
153  
                        ar << state << exception;
154  
                    } else {
155  
                        state = future_state::invalid;
156  
                        ar << state;
157  
                    }
158  
                }
159  
            }
160  
            return;
161  
        }
162  
163  
#if defined(HPX_DEBUG)
164  
        if (f.valid())
165  
        {
166  
            HPX_ASSERT(f.is_ready());
167  
        }
168  
#endif
169  
170  
        if (f.has_value())
171  
        {
172  
            state = future_state::has_value;
173  
            value_type const & value =
174  
                *hpx::traits::future_access<Future>::
175  
                    get_shared_state(f)->get_result();
176  
            ar << state << value; //-V128
177  
        } else if (f.has_exception()) {
178  
            state = future_state::has_exception;
179  
            boost::exception_ptr exception = f.get_exception_ptr();
180  
            ar << state << exception;
181  
        } else {
182  
            state = future_state::invalid;
183  
            ar << state;
184  
        }
185  
    }
186  
187  
    template <typename Archive, typename Future>
188  
    typename std::enable_if<
189  
        std::is_void<typename hpx::traits::future_traits<Future>::type>::value
190  
    >::type serialize_future_save(Archive& ar, Future const& f) //-V659
191  
    {
192  
        int state = future_state::invalid;
193  
        if(ar.is_preprocessing())
194  
        {
195  
            if(!f.is_ready())
196  
            {
197  
                typename
198  
                    hpx::traits::detail::shared_state_ptr_for<Future>::type state
199  
                    = hpx::traits::future_access<Future>::get_shared_state(f);
200  
201  
                state->execute_deferred();
202  
203  
                ar.await_future(f);
204  
            }
205  
            else
206  
            {
207  
                if (f.has_value())
208  
                {
209  
                    state = future_state::has_value;
210  
                    ar << state;
211  
                }
212  
                else if (f.has_exception())
213  
                {
214  
                    state = future_state::has_exception;
215  
                    boost::exception_ptr exception = f.get_exception_ptr();
216  
                    ar << state << exception;
217  
                }
218  
                else
219  
                {
220  
                    state = future_state::invalid;
221  
                    ar << state;
222  
                }
223  
            }
224  
            return;
225  
        }
226  
227  
#if defined(HPX_DEBUG)
228  
        if (f.valid())
229  
        {
230  
            HPX_ASSERT(f.is_ready());
231  
        }
232  
#endif
233  
234  
        if (f.has_value())
235  
        {
236  
            state = future_state::has_value;
237  
            ar << state;
238  
        }
239  
        else if (f.has_exception())
240  
        {
241  
            state = future_state::has_exception;
242  
            boost::exception_ptr exception = f.get_exception_ptr();
243  
            ar << state << exception;
244  
        }
245  
        else
246  
        {
247  
            state = future_state::invalid;
248  
            ar << state;
249  
        }
250  
    }
251  
252  
    template <typename Future>
253  
    void serialize_future(serialization::input_archive& ar, Future& f, unsigned)
254  
    {
255  
        serialize_future_load(ar, f);
256  
    }
257  
258  
    template <typename Future>
259  
    void serialize_future(serialization::output_archive& ar, Future& f, unsigned)
260  
    {
261  
        serialize_future_save(ar, f);
262  
    }
263  
264  
    ///////////////////////////////////////////////////////////////////////////
265  
    template <typename Future, typename F, typename Enable = void>
266  
    struct future_then_result
267  
    {
268  
        typedef struct continuation_not_callable
269  
        {
270  
            void error(Future future, F& f)
271  
            {
272  
                f(future);
273  
            }
274  
275  
            ~continuation_not_callable()
276  
            {
277  
                error(std::declval<Future>(), std::declval<F&>());
278  
            }
279  
        } type;
280  
    };
281  
282  
    template <typename Future, typename F>
283  
    struct future_then_result<
284  
        Future, F
285  
      , typename hpx::util::always_void<
286  
            typename hpx::util::result_of<F(Future)>::type
287  
        >::type
288  
    >
289  
    {
290  
        typedef typename hpx::util::result_of<F(Future)>::type cont_result;
291  
292  
        typedef typename util::lazy_conditional<
293  
            hpx::traits::detail::is_unique_future<cont_result>::value
294  
          , hpx::traits::future_traits<cont_result>
295  
          , hpx::util::identity<cont_result>
296  
        >::type result_type;
297  
298  
        typedef lcos::future<result_type> type;
299  
    };
300  
301  
    ///////////////////////////////////////////////////////////////////////////
302  
    template <typename Future, typename Enable = void>
303  
    struct future_unwrap_result
304  
    {};
305  
306  
    template <template <typename> class Future, typename R>
307  
    struct future_unwrap_result<Future<Future<R> > >
308  
    {
309  
        typedef R result_type;
310  
311  
        typedef Future<result_type> type;
312  
    };
313  
314  
    template <typename R>
315  
    struct future_unwrap_result<future<shared_future<R> > >
316  
    {
317  
        typedef R result_type;
318  
319  
        typedef future<result_type> type;
320  
    };
321  
322  
    ///////////////////////////////////////////////////////////////////////////
323  
    template <typename Iter, typename Enable = void>
324  
    struct future_iterator_traits
325  
    {};
326  
327  
    template <typename Iterator>
328  
    struct future_iterator_traits<Iterator,
329  
        typename hpx::util::always_void<
330  
#if defined(HPX_MSVC) && HPX_MSVC <= 1800       // MSVC12 needs special help
331  
            typename Iterator::iterator_category
332  
#else
333  
            typename std::iterator_traits<Iterator>::value_type
334  
#endif
335  
        >::type>
336  
    {
337  
        typedef
338  
            typename std::iterator_traits<Iterator>::value_type
339  
            type;
340  
341  
        typedef hpx::traits::future_traits<type> traits_type;
342  
    };
343  
344  
    ///////////////////////////////////////////////////////////////////////////
345  
    template <typename T>
346  
    struct future_value
347  
      : future_data_result<T>
348  
    {
349  
        template <typename U>
350  
        HPX_FORCEINLINE static
351  
        U get(U && u)
352  
        {
353  
            return std::forward<U>(u);
354  
        }
355  
356  
        static T get_default()
357  
        {
358  
            return T();
359  
        }
360  
    };
361  
362  
    template <typename T>
363  
    struct future_value<T&>
364  
      : future_data_result<T&>
365  
    {
366  
        HPX_FORCEINLINE static
367  
        T& get(T* u)
368  
        {
369  
            return *u;
370  
        }
371  
372  
        static T& get_default()
373  
        {
374  
            static T default_;
375  
            return default_;
376  
        }
377  
    };
378  
379  
    template <>
380  
    struct future_value<void>
381  
      : future_data_result<void>
382  
    {
383  
        HPX_FORCEINLINE static
384  
        void get(hpx::util::unused_type)
385  
        {}
386  
387  
        static void get_default()
388  
        {}
389  
    };
390  
391  
    ///////////////////////////////////////////////////////////////////////////
392  
    template <typename Future, typename F, typename ContResult>
393  
    class continuation;
394  
395  
    template <typename ContResult>
396  
    struct continuation_result;
397  
398  
    template <typename ContResult, typename Future, typename F>
399  
    inline typename hpx::traits::detail::shared_state_ptr<
400  
        typename continuation_result<ContResult>::type
401  
    >::type
402  
    make_continuation(Future const& future, launch policy,
403  
        F && f);
404  
405  
    template <typename ContResult, typename Future, typename F>
406  
    inline typename hpx::traits::detail::shared_state_ptr<
407  
        typename continuation_result<ContResult>::type
408  
    >::type
409  
    make_continuation(Future const& future, threads::executor& sched,
410  
        F && f);
411  
    template <typename ContResult, typename Future, typename Executor,
412  
        typename F>
413  
    inline typename hpx::traits::detail::shared_state_ptr<
414  
        typename continuation_result<ContResult>::type
415  
    >::type
416  
    make_continuation_exec(Future const& future, Executor& exec, F && f);
417  
418  
    ///////////////////////////////////////////////////////////////////////////
419  
    template <typename Future>
420  
    typename hpx::traits::detail::shared_state_ptr<
421  
        typename future_unwrap_result<Future>::result_type>::type
422  
    unwrap(Future&& future, error_code& ec = throws);
423  
424  
    ///////////////////////////////////////////////////////////////////////////
425  
    class void_continuation;
426  
427  
    template <typename Future>
428  
    inline typename hpx::traits::detail::shared_state_ptr<void>::type
429  
    make_void_continuation(Future& future);
430  
431  
    ///////////////////////////////////////////////////////////////////////////
432  
    template <typename Derived, typename R>
433  
    class future_base
434  
    {
435  
    public:
436  
        typedef R result_type;
437  
        typedef future_data<R> shared_state_type;
438  
439  
    public:
440  
        future_base() HPX_NOEXCEPT
441  
          : shared_state_()
442  
        {}
443  
444  
        explicit future_base(
445  
            boost::intrusive_ptr<shared_state_type> const& p
446  
        ) : shared_state_(p)
447  
        {}
448  
449  
        explicit future_base(
450  
            boost::intrusive_ptr<shared_state_type> && p
451  
        ) : shared_state_(std::move(p))
452  
        {}
453  
454  
        future_base(future_base const& other)
455  
          : shared_state_(other.shared_state_)
456  
        {}
457  
458  
        future_base(future_base && other) HPX_NOEXCEPT
459  
          : shared_state_(std::move(other.shared_state_))
460  
        {
461  
            other.shared_state_ = nullptr;
462  
        }
463  
464  
        void swap(future_base& other)
465  
        {
466  
            shared_state_.swap(other.shared_state_);
467  
        }
468  
469  
        future_base& operator=(future_base const & other)
470  
        {
471  
            if (this != &other)
472  
            {
473  
                shared_state_ = other.shared_state_;
474  
            }
475  
            return *this;
476  
        }
477  
478  
        future_base& operator=(future_base && other) HPX_NOEXCEPT
479  
        {
480  
            if (this != &other)
481  
            {
482  
                shared_state_ = std::move(other.shared_state_);
483  
                other.shared_state_ = nullptr;
484  
            }
485  
            return *this;
486  
        }
487  
488  
        // Returns: true only if *this refers to a shared state.
489  
        bool valid() const HPX_NOEXCEPT
490  
        {
491  
            return shared_state_ != nullptr;
492  
        }
493  
494  
        // Returns: true if the shared state is ready, false if it isn't.
495  
        bool is_ready() const HPX_NOEXCEPT
496  
        {
497  
            return shared_state_ != nullptr && shared_state_->is_ready();
498  
        }
499  
500  
        // Returns: true if the shared state is ready and stores a value,
501  
        //          false if it isn't.
502  
        bool has_value() const HPX_NOEXCEPT
503  
        {
504  
            return shared_state_ != nullptr && shared_state_->has_value();
505  
        }
506  
507  
        // Returns: true if the shared state is ready and stores an exception,
508  
        //          false if it isn't.
509  
        bool has_exception() const HPX_NOEXCEPT
510  
        {
511  
            return shared_state_ != nullptr && shared_state_->has_exception();
512  
        }
513  
514  
        // Effects:
515  
        //   - Blocks until the future is ready.
516  
        // Returns: The stored exception_ptr if has_exception(), a null
517  
        //          pointer otherwise.
518  
        boost::exception_ptr get_exception_ptr() const
519  
        {
520  
            if (!shared_state_)
521  
            {
522  
                HPX_THROW_EXCEPTION(no_state,
523  
                    "future_base<R>::get_exception_ptr",
524  
                    "this future has no valid shared state");
525  
            }
526  
527  
            error_code ec(lightweight);
528  
            this->shared_state_->get_result(ec);
529  
            if (!ec) return boost::exception_ptr();
530  
            return hpx::detail::access_exception(ec);
531  
        }
532  
533  
        // Notes: The three functions differ only by input parameters.
534  
        //   - The first only takes a callable object which accepts a future
535  
        //     object as a parameter.
536  
        //   - The second function takes an executor as the first parameter
537  
        //     and a callable object as the second parameter.
538  
        //   - The third function takes a launch policy as the first parameter
539  
        //     and a callable object as the second parameter.
540  
        //   In cases where 'decltype(func(*this))' is future<R>, the
541  
        //   resulting type is future<R> instead of future<future<R>>.
542  
        // Effects:
543  
        //   - The continuation is called when the object's shared state is
544  
        //     ready (has a value or exception stored).
545  
        //   - The continuation launches according to the specified launch
546  
        //     policy or executor.
547  
        //   - When the executor or launch policy is not provided the
548  
        //     continuation inherits the parent's launch policy or executor.
549  
        //   - If the parent was created with std::promise or with a
550  
        //     packaged_task (has no associated launch policy), the
551  
        //     continuation behaves the same as the third overload with a
552  
        //     policy argument of launch::async | launch::deferred and the
553  
        //     same argument for func.
554  
        //   - If the parent has a policy of launch::deferred and the
555  
        //     continuation does not have a specified launch policy or
556  
        //     scheduler, then the parent is filled by immediately calling
557  
        //     .wait(), and the policy of the antecedent is launch::deferred
558  
        // Returns: An object of type future<decltype(func(*this))> that
559  
        //          refers to the shared state created by the continuation.
560  
        // Postcondition:
561  
        //   - The future object is moved to the parameter of the continuation
562  
        //     function.
563  
        //   - valid() == false on original future object immediately after it
564  
        //     returns.
565  
        template <typename F>
566  
        typename util::lazy_enable_if<
567  
            !hpx::traits::is_launch_policy<F>::value &&
568  
            !hpx::traits::is_threads_executor<F>::value &&
569  
            !hpx::traits::is_executor<F>::value
570  
          , future_then_result<Derived, F>
571  
        >::type
572  
        then(F && f, error_code& ec = throws) const
573  
        {
574  
            return then(launch::all, std::forward<F>(f), ec);
575  
        }
576  
577  
        template <typename F>
578  
        typename future_then_result<Derived, F>::type
579  
        then(launch policy, F && f, error_code& ec = throws) const
580  
        {
581  
            typedef
582  
                typename future_then_result<Derived, F>::result_type
583  
                result_type;
584  
585  
            if (!shared_state_)
586  
            {
587  
                HPX_THROWS_IF(ec, no_state,
588  
                    "future_base<R>::then",
589  
                    "this future has no valid shared state");
590  
                return future<result_type>();
591  
            }
592  
593  
            typedef
594  
                typename hpx::util::result_of<F(Derived)>::type
595  
                continuation_result_type;
596  
            typedef
597  
                typename hpx::traits::detail::shared_state_ptr<result_type>::type
598  
                shared_state_ptr;
599  
600  
            shared_state_ptr p =
601  
                detail::make_continuation<continuation_result_type>(
602  
                    *static_cast<Derived const*>(this), policy, std::forward<F>(f));
603  
            return hpx::traits::future_access<future<result_type> >::create(
604  
                std::move(p));
605  
        }
606  
607  
        template <typename F>
608  
        typename future_then_result<Derived, F>::type
609  
        then(threads::executor& sched, F && f, error_code& ec = throws) const
610  
        {
611  
            typedef
612  
                typename future_then_result<Derived, F>::result_type
613  
                result_type;
614  
615  
            if (!shared_state_)
616  
            {
617  
                HPX_THROWS_IF(ec, no_state,
618  
                    "future_base<R>::then",
619  
                    "this future has no valid shared state");
620  
                return future<result_type>();
621  
            }
622  
623  
            typedef
624  
                typename hpx::util::result_of<F(Derived)>::type
625  
                continuation_result_type;
626  
            typedef
627  
                typename hpx::traits::detail::shared_state_ptr<result_type>::type
628  
                shared_state_ptr;
629  
630  
            shared_state_ptr p =
631  
                detail::make_continuation<continuation_result_type>(
632  
                    *static_cast<Derived const*>(this), sched, std::forward<F>(f));
633  
            return hpx::traits::future_access<future<result_type> >::create(
634  
                std::move(p));
635  
        }
636  
637  
        template <typename Executor, typename F>
638  
        typename util::lazy_enable_if<
639  
            hpx::traits::is_executor<Executor>::value
640  
          , future_then_result<Derived, F>
641  
        >::type
642  
        then(Executor& exec, F && f, error_code& ec = throws) const
643  
        {
644  
            typedef
645  
                typename future_then_result<Derived, F>::result_type
646  
                result_type;
647  
648  
            if (!shared_state_)
649  
            {
650  
                HPX_THROWS_IF(ec, no_state,
651  
                    "future_base<R>::then",
652  
                    "this future has no valid shared state");
653  
                return future<result_type>();
654  
            }
655  
656  
            typedef
657  
                typename hpx::util::result_of<F(Derived)>::type
658  
                continuation_result_type;
659  
            typedef
660  
                typename hpx::traits::detail::shared_state_ptr<result_type>::type
661  
                shared_state_ptr;
662  
663  
            shared_state_ptr p =
664  
                detail::make_continuation_exec<continuation_result_type>(
665  
                    *static_cast<Derived const*>(this), exec,
666  
                    std::forward<F>(f));
667  
            return hpx::traits::future_access<future<result_type> >::
668  
                create(std::move(p));
669  
        }
670  
671  
        // Effects: blocks until the shared state is ready.
672  
        void wait(error_code& ec = throws) const
673  
        {
674  
            if (!shared_state_)
675  
            {
676  
                HPX_THROWS_IF(ec, no_state,
677  
                    "future_base<R>::wait",
678  
                    "this future has no valid shared state");
679  
                return;
680  
            }
681  
            shared_state_->wait(ec);
682  
        }
683  
684  
        // Effects: none if the shared state contains a deferred function
685  
        //          (30.6.8), otherwise blocks until the shared state is ready
686  
        //          or until the absolute timeout (30.2.4) specified by
687  
        //          abs_time has expired.
688  
        // Returns:
689  
        //   - future_status::deferred if the shared state contains a deferred
690  
        //     function.
691  
        //   - future_status::ready if the shared state is ready.
692  
        //   - future_status::timeout if the function is returning because the
693  
        //     absolute timeout (30.2.4) specified by abs_time has expired.
694  
        // Throws: timeout-related exceptions (30.2.4).
695  
        future_status
696  
        wait_until(hpx::util::steady_time_point const& abs_time,
697  
            error_code& ec = throws) const
698  
        {
699  
            if (!shared_state_)
700  
            {
701  
                HPX_THROWS_IF(ec, no_state,
702  
                    "future_base<R>::wait_until",
703  
                    "this future has no valid shared state");
704  
                return future_status::uninitialized;
705  
            }
706  
            return shared_state_->wait_until(abs_time.value(), ec);
707  
        }
708  
709  
        // Effects: none if the shared state contains a deferred function
710  
        //          (30.6.8), otherwise blocks until the shared state is ready
711  
        //          or until the relative timeout (30.2.4) specified by
712  
        //          rel_time has expired.
713  
        // Returns:
714  
        //   - future_status::deferred if the shared state contains a deferred
715  
        //     function.
716  
        //   - future_status::ready if the shared state is ready.
717  
        //   - future_status::timeout if the function is returning because the
718  
        //     relative timeout (30.2.4) specified by rel_time has expired.
719  
        // Throws: timeout-related exceptions (30.2.4).
720  
        future_status
721  
        wait_for(hpx::util::steady_duration const& rel_time,
722  
            error_code& ec = throws) const
723  
        {
724  
            return wait_until(rel_time.from_now(), ec);
725  
        }
726  
727  
#if defined(HPX_HAVE_AWAIT)
728  
        bool await_ready() const
729  
        {
730  
            return detail::await_ready(*static_cast<Derived const*>(this));
731  
        }
732  
733  
        template <typename Promise>
734  
        void await_suspend(std::experimental::coroutine_handle<Promise> rh)
735  
        {
736  
            detail::await_suspend(*static_cast<Derived*>(this), rh);
737  
        }
738  
739  
        R await_resume()
740  
        {
741  
            return detail::await_resume(*static_cast<Derived*>(this));
742  
        }
743  
#endif
744  
745  
    protected:
746  
        boost::intrusive_ptr<shared_state_type> shared_state_;
747  
    };
748  
}}}
749  
750  
namespace hpx { namespace lcos
751  
{
752  
    ///////////////////////////////////////////////////////////////////////////
753  
    template <typename R>
754  
    class future : public detail::future_base<future<R>, R>
755  
    {
756  
        HPX_MOVABLE_ONLY(future);
757  
758  
        typedef detail::future_base<future<R>, R> base_type;
759  
760  
    public:
761  
        typedef R result_type;
762  
        typedef typename base_type::shared_state_type shared_state_type;
763  
764  
    private:
765  
        struct invalidate
766  
        {
767  
            explicit invalidate(future& f)
768  
              : f_(f)
769  
            {}
770  
771  
            ~invalidate()
772  
            {
773  
                f_.shared_state_.reset();
774  
            }
775  
776  
            future& f_;
777  
        };
778  
779  
    private:
780  
        template <typename Future>
781  
        friend struct hpx::traits::future_access;
782  
783  
        template <typename Future, typename Enable>
784  
        friend struct hpx::traits::detail::future_access_customization_point;
785  
786  
        // Effects: constructs a future object from an shared state
787  
        explicit future(
788  
            boost::intrusive_ptr<shared_state_type> const& state
789  
        ) : base_type(state)
790  
        {}
791  
792  
        explicit future(
793  
            boost::intrusive_ptr<shared_state_type> && state
794  
        ) : base_type(std::move(state))
795  
        {}
796  
797  
        template <typename SharedState>
798  
        explicit future(boost::intrusive_ptr<SharedState> const& state)
799  
          : base_type(boost::static_pointer_cast<shared_state_type>(state))
800  
        {}
801  
802  
    public:
803  
        // Effects: constructs an empty future object that does not refer to
804  
        //          an shared state.
805  
        // Postcondition: valid() == false.
806  
        future() HPX_NOEXCEPT
807  
          : base_type()
808  
        {}
809  
810  
        // Effects: move constructs a future object that refers to the shared
811  
        //          state that was originally referred to by other (if any).
812  
        // Postconditions:
813  
        //   - valid() returns the same value as other.valid() prior to the
814  
        //     constructor invocation.
815  
        //   - other.valid() == false.
816  
        future(future && other) HPX_NOEXCEPT
817  
          : base_type(std::move(other))
818  
        {}
819  
820  
        // Effects: constructs a future object by moving the instance referred
821  
        //          to by rhs and unwrapping the inner future.
822  
        // Postconditions:
823  
        //   - valid() returns the same value as other.valid() prior to the
824  
        //     constructor invocation.
825  
        //   - other.valid() == false.
826  
        future(future<future> && other) HPX_NOEXCEPT
827  
          : base_type(other.valid() ? detail::unwrap(std::move(other)) : nullptr)
828  
        {}
829  
830  
        // Effects: constructs a future object by moving the instance referred
831  
        //          to by rhs and unwrapping the inner future.
832  
        // Postconditions:
833  
        //   - valid() returns the same value as other.valid() prior to the
834  
        //     constructor invocation.
835  
        //   - other.valid() == false.
836  
        future(future<shared_future<R> > && other) HPX_NOEXCEPT
837  
          : base_type(other.valid() ? detail::unwrap(std::move(other)) : nullptr)
838  
        {}
839  
840  
        // Effects: constructs a future<void> object that will be ready when
841  
        //          the given future is ready
842  
        // Postconditions:
843  
        //   - valid() returns the same value as other.valid() prior to the
844  
        //     constructor invocation.
845  
        //   - other.valid() == false.
846  
        template <typename T>
847  
        future(future<T>&& other,
848  
            typename std::enable_if<std::is_void<R>::value, T>::type* = nullptr
849  
        ) : base_type(other.valid() ? detail::make_void_continuation(other) : nullptr)
850  
        {
851  
            other = future<T>();
852  
        }
853  
854  
        // Effects:
855  
        //   - releases any shared state (30.6.4);
856  
        //   - destroys *this.
857  
        ~future()
858  
        {}
859  
860  
        // Effects:
861  
        //   - releases any shared state (30.6.4).
862  
        //   - move assigns the contents of other to *this.
863  
        // Postconditions:
864  
        //   - valid() returns the same value as other.valid() prior to the
865  
        //     assignment.
866  
        //   - other.valid() == false.
867  
        future& operator=(future && other) HPX_NOEXCEPT
868  
        {
869  
            base_type::operator=(std::move(other));
870  
            return *this;
871  
        }
872  
873  
        // Returns: shared_future<R>(std::move(*this)).
874  
        // Postcondition: valid() == false.
875  
        shared_future<R> share()
876  
        {
877  
            return shared_future<R>(std::move(*this));
878  
        }
879  
880  
        // Effects: wait()s until the shared state is ready, then retrieves
881  
        //          the value stored in the shared state.
882  
        // Returns:
883  
        //   - future::get() returns the value v stored in the object's
884  
        //     shared state as std::move(v).
885  
        //   - future<R&>::get() returns the reference stored as value in the
886  
        //     object's shared state.
887  
        //   - future<void>::get() returns nothing.
888  
        // Throws: the stored exception, if an exception was stored in the
889  
        //         shared state.
890  
        // Postcondition: valid() == false.
891  
        typename hpx::traits::future_traits<future>::result_type
892  
        get()
893  
        {
894  
            if (!this->shared_state_)
895  
            {
896  
                HPX_THROW_EXCEPTION(no_state,
897  
                    "future<R>::get",
898  
                    "this future has no valid shared state");
899  
            }
900  
901  
            invalidate on_exit(*this);
902  
903  
            typedef typename shared_state_type::result_type result_type;
904  
            result_type* result = this->shared_state_->get_result();
905  
906  
            // no error has been reported, return the result
907  
            return detail::future_value<R>::get(std::move(*result));
908  
        }
909  
910  
        typename hpx::traits::future_traits<future>::result_type
911  
        get(error_code& ec)
912  
        {
913  
            if (!this->shared_state_)
914  
            {
915  
                HPX_THROWS_IF(ec, no_state,
916  
                    "future<R>::get",
917  
                    "this future has no valid shared state");
918  
                return detail::future_value<R>::get_default();
919  
            }
920  
921  
            invalidate on_exit(*this);
922  
923  
            typedef typename shared_state_type::result_type result_type;
924  
            result_type* result = this->shared_state_->get_result(ec);
925  
            if (ec) return detail::future_value<R>::get_default();
926  
927  
            // no error has been reported, return the result
928  
            return detail::future_value<R>::get(std::move(*result));
929  
        }
930  
        using base_type::get_exception_ptr;
931  
932  
        using base_type::valid;
933  
        using base_type::is_ready;
934  
        using base_type::has_value;
935  
        using base_type::has_exception;
936  
937  
        template <typename F>
938  
        typename util::lazy_enable_if<
939  
            !hpx::traits::is_launch_policy<F>::value &&
940  
            !hpx::traits::is_threads_executor<F>::value &&
941  
            !hpx::traits::is_executor<F>::value
942  
          , detail::future_then_result<future, F>
943  
        >::type
944  
        then(F && f, error_code& ec = throws)
945  
        {
946  
            invalidate on_exit(*this);
947  
            return base_type::then(std::forward<F>(f), ec);
948  
        }
949  
950  
        template <typename F>
951  
        typename detail::future_then_result<future, F>::type
952  
        then(launch policy, F && f, error_code& ec = throws)
953  
        {
954  
            invalidate on_exit(*this);
955  
            return base_type::then(policy, std::forward<F>(f), ec);
956  
        }
957  
958  
        template <typename F>
959  
        typename detail::future_then_result<future, F>::type
960  
        then(threads::executor& sched, F && f, error_code& ec = throws)
961  
        {
962  
            invalidate on_exit(*this);
963  
            return base_type::then(sched, std::forward<F>(f), ec);
964  
        }
965  
966  
        template <typename Executor, typename F>
967  
        typename util::lazy_enable_if<
968  
            hpx::traits::is_executor<Executor>::value
969  
          , detail::future_then_result<future, F>
970  
        >::type
971  
        then(Executor& exec, F && f, error_code& ec = throws)
972  
        {
973  
            invalidate on_exit(*this);
974  
            return base_type::then(exec, std::forward<F>(f), ec);
975  
        }
976  
977  
        using base_type::wait;
978  
        using base_type::wait_for;
979  
        using base_type::wait_until;
980  
    };
981  
982  
    ///////////////////////////////////////////////////////////////////////////
983  
    namespace detail
984  
    {
985  
        template <typename T, typename Future>
986  
        typename std::enable_if<
987  
            std::is_convertible<Future, hpx::future<T> >::value,
988  
            hpx::future<T>
989  
        >::type
990  
        make_future_helper(Future && f)
991  
        {
992  
            return std::move(f);
993  
        };
994  
995  
        template <typename T, typename Future>
996  
        typename std::enable_if<
997  
           !std::is_convertible<Future, hpx::future<T> >::value,
998  
            hpx::future<T>
999  
        >::type
1000  
        make_future_helper(Future && f) //-V659
1001  
        {
1002  
            return f.then(
1003  
                [](Future && f) -> T
1004  
                {
1005  
                    return util::void_guard<T>(), f.get();
1006  
                });
1007  
        }
1008  
    }
1009  
1010  
    // Allow to convert any future<U> into any other future<R> based on an
1011  
    // existing conversion path U --> R.
1012  
    template <typename R, typename U>
1013  
    hpx::future<R>
1014  
    make_future(hpx::future<U> && f)
1015  
    {
1016  
        static_assert(
1017  
            std::is_convertible<R, U>::value || std::is_void<R>::value,
1018  
            "the argument type must be implicitly convertible to the requested "
1019  
            "result type");
1020  
1021  
        return detail::make_future_helper<R>(std::move(f));
1022  
    }
1023  
1024  
    namespace detail
1025  
    {
1026  
        template <typename T, typename Future, typename Conv>
1027  
        typename std::enable_if<
1028  
            std::is_convertible<Future, hpx::future<T> >::value,
1029  
            hpx::future<T>
1030  
        >::type
1031  
        convert_future_helper(Future && f, Conv && conv)
1032  
        {
1033  
            return std::move(f);
1034  
        };
1035  
1036  
        template <typename T, typename Future, typename Conv>
1037  
        typename std::enable_if<
1038  
           !std::is_convertible<Future, hpx::future<T> >::value,
1039  
            hpx::future<T>
1040  
        >::type
1041  
        convert_future_helper(Future && f, Conv && conv) //-V659
1042  
        {
1043  
            return f.then(
1044  
                [conv](Future && f) -> T
1045  
                {
1046  
                    return hpx::util::invoke(conv, f.get());
1047  
                });
1048  
        }
1049  
    }
1050  
1051  
    // Allow to convert any future<U> into any other future<R> based on a given
1052  
    // conversion function: R conv(U).
1053  
    template <typename R, typename U, typename Conv>
1054  
    hpx::future<R>
1055  
    make_future(hpx::future<U> && f, Conv && conv)
1056  
    {
1057  
        return detail::convert_future_helper<R>(
1058  
            std::move(f), std::forward<Conv>(conv));
1059  
    }
1060  
}}
1061  
1062  
namespace hpx { namespace lcos
1063  
{
1064  
    ///////////////////////////////////////////////////////////////////////////
1065  
    template <typename R>
1066  
    class shared_future : public detail::future_base<shared_future<R>, R>
1067  
    {
1068  
        typedef detail::future_base<shared_future<R>, R> base_type;
1069  
1070  
    public:
1071  
        typedef R result_type;
1072  
        typedef typename base_type::shared_state_type shared_state_type;
1073  
1074  
    private:
1075  
        template <typename Future>
1076  
        friend struct hpx::traits::future_access;
1077  
1078  
        template <typename Future, typename Enable>
1079  
        friend struct hpx::traits::detail::future_access_customization_point;
1080  
1081  
        // Effects: constructs a future object from an shared state
1082  
        explicit shared_future(
1083  
            boost::intrusive_ptr<shared_state_type> const& state
1084  
        ) : base_type(state)
1085  
        {}
1086  
1087  
        explicit shared_future(
1088  
            boost::intrusive_ptr<shared_state_type> && state
1089  
        ) : base_type(std::move(state))
1090  
        {}
1091  
1092  
        template <typename SharedState>
1093  
        explicit shared_future(boost::intrusive_ptr<SharedState> const& state)
1094  
          : base_type(boost::static_pointer_cast<shared_state_type>(state))
1095  
        {}
1096  
1097  
    public:
1098  
        // Effects: constructs an empty future object that does not refer to
1099  
        //          an shared state.
1100  
        // Postcondition: valid() == false.
1101  
        shared_future() HPX_NOEXCEPT
1102  
          : base_type()
1103  
        {}
1104  
1105  
        // Effects: constructs a shared_future object that refers to the same
1106  
        //          shared state as other (if any).
1107  
        // Postcondition: valid() returns the same value as other.valid().
1108  
        shared_future(shared_future const& other)
1109  
          : base_type(other)
1110  
        {}
1111  
1112  
        // Effects: move constructs a future object that refers to the shared
1113  
        //          state that was originally referred to by other (if any).
1114  
        // Postconditions:
1115  
        //   - valid() returns the same value as other.valid() prior to the
1116  
        //     constructor invocation.
1117  
        //   - other.valid() == false.
1118  
        shared_future(shared_future && other) HPX_NOEXCEPT
1119  
          : base_type(std::move(other))
1120  
        {}
1121  
1122  
        shared_future(future<R> && other) HPX_NOEXCEPT
1123  
          : base_type(hpx::traits::detail::get_shared_state(other))
1124  
        {
1125  
            other = future<R>();
1126  
        }
1127  
1128  
        // Effects: constructs a shared_future object by moving the instance
1129  
        //          referred to by rhs and unwrapping the inner future.
1130  
        // Postconditions:
1131  
        //   - valid() returns the same value as other.valid() prior to the
1132  
        //     constructor invocation.
1133  
        //   - other.valid() == false.
1134  
        shared_future(future<shared_future> && other) HPX_NOEXCEPT
1135  
          : base_type(other.valid() ? detail::unwrap(other.share()) : nullptr)
1136  
        {}
1137  
1138  
        // Effects: constructs a future<void> object that will be ready when
1139  
        //          the given future is ready
1140  
        // Postconditions:
1141  
        //   - valid() returns the same value as other.valid() prior to the
1142  
        //     constructor invocation.
1143  
        template <typename T>
1144  
        shared_future(shared_future<T> const& other,
1145  
            typename std::enable_if<std::is_void<R>::value, T>::type* = nullptr
1146  
        ) : base_type(other.valid() ? detail::make_void_continuation(other) : nullptr)
1147  
        {}
1148  
1149  
        // Effects:
1150  
        //   - releases any shared state (30.6.4);
1151  
        //   - destroys *this.
1152  
        ~shared_future()
1153  
        {}
1154  
1155  
        // Effects:
1156  
        //   - releases any shared state (30.6.4).
1157  
        //   - assigns the contents of other to *this. As a result, *this
1158  
        //     refers to the same shared state as other (if any).
1159  
        // Postconditions:
1160  
        //   - valid() == other.valid().
1161  
        shared_future& operator=(shared_future const & other)
1162  
        {
1163  
            base_type::operator=(other);
1164  
            return *this;
1165  
        }
1166  
1167  
        // Effects:
1168  
        //   - releases any shared state (30.6.4).
1169  
        //   - move assigns the contents of other to *this.
1170  
        // Postconditions:
1171  
        //   - valid() returns the same value as other.valid() prior to the
1172  
        //     assignment.
1173  
        //   - other.valid() == false.
1174  
        shared_future& operator=(shared_future && other) HPX_NOEXCEPT
1175  
        {
1176  
            base_type::operator=(std::move(other));
1177  
            return *this;
1178  
        }
1179  
1180  
        // Effects: wait()s until the shared state is ready, then retrieves
1181  
        //          the value stored in the shared state.
1182  
        // Returns:
1183  
        //   - shared_future::get() returns a const reference to the value
1184  
        //     stored in the object's shared state.
1185  
        //   - shared_future<R&>::get() returns the reference stored as value
1186  
        //     in the object's shared state.
1187  
        //   - shared_future<void>::get() returns nothing.
1188  
        // Throws: the stored exception, if an exception was stored in the
1189  
        //         shared state.
1190  
        // Postcondition: valid() == false.
1191  
        typename hpx::traits::future_traits<shared_future>::result_type
1192  
        get() const //-V659
1193  
        {
1194  
            if (!this->shared_state_)
1195  
            {
1196  
                HPX_THROW_EXCEPTION(no_state,
1197  
                    "shared_future<R>::get",
1198  
                    "this future has no valid shared state");
1199  
            }
1200  
1201  
            typedef typename shared_state_type::result_type result_type;
1202  
            result_type* result = this->shared_state_->get_result();
1203  
1204  
            // no error has been reported, return the result
1205  
            return detail::future_value<R>::get(*result);
1206  
        }
1207  
        typename hpx::traits::future_traits<shared_future>::result_type
1208  
        get(error_code& ec) const //-V659
1209  
        {
1210  
            typedef typename shared_state_type::result_type result_type;
1211  
            if (!this->shared_state_)
1212  
            {
1213  
                HPX_THROWS_IF(ec, no_state,
1214  
                    "shared_future<R>::get",
1215  
                    "this future has no valid shared state");
1216  
                static result_type res(detail::future_value<R>::get_default());
1217  
                return res;
1218  
            }
1219  
1220  
            result_type* result = this->shared_state_->get_result(ec);
1221  
            if (ec)
1222  
            {
1223  
                static result_type res(detail::future_value<R>::get_default());
1224  
                return res;
1225  
            }
1226  
1227  
            // no error has been reported, return the result
1228  
            return detail::future_value<R>::get(*result);
1229  
        }
1230  
        using base_type::get_exception_ptr;
1231  
1232  
        using base_type::valid;
1233  
        using base_type::is_ready;
1234  
        using base_type::has_value;
1235  
        using base_type::has_exception;
1236  
1237  
        using base_type::then;
1238  
1239  
        using base_type::wait;
1240  
        using base_type::wait_for;
1241  
        using base_type::wait_until;
1242  
    };
1243  
1244  
    ///////////////////////////////////////////////////////////////////////////
1245  
    // Allow to convert any shared_future<U> into any other future<R> based on
1246  
    // an existing conversion path U --> R.
1247  
    template <typename R, typename U>
1248  
    hpx::future<R>
1249  
    make_future(hpx::shared_future<U> f)
1250  
    {
1251  
        static_assert(
1252  
            std::is_convertible<R, U>::value || std::is_void<R>::value,
1253  
            "the argument type must be implicitly convertible to the requested "
1254  
            "result type");
1255  
1256  
        return detail::make_future_helper<R>(std::move(f));
1257  
    }
1258  
1259  
    // Allow to convert any future<U> into any other future<R> based on a given
1260  
    // conversion function: R conv(U).
1261  
    template <typename R, typename U, typename Conv>
1262  
    hpx::future<R>
1263  
    make_future(hpx::shared_future<U> const& f, Conv && conv)
1264  
    {
1265  
        static_assert(
1266  
            hpx::traits::is_callable<Conv(U), R>::value,
1267  
            "the argument type must be convertible to the requested "
1268  
            "result type by using the supplied conversion function");
1269  
1270  
        return f.then(
1271  
            [conv](hpx::shared_future<U> const& f)
1272  
            {
1273  
                return hpx::util::invoke(conv, f.get());
1274  
            });
1275  
    }
1276  
}}
1277  
1278  
namespace hpx { namespace lcos
1279  
{
1280  
    ///////////////////////////////////////////////////////////////////////////
1281  
    // extension: create a pre-initialized future object
1282  
    template <typename Result>
1283  
    future<typename hpx::util::decay_unwrap<Result>::type>
1284  
    make_ready_future(Result && init)
1285  
    {
1286  
        typedef typename hpx::util::decay_unwrap<Result>::type result_type;
1287  
        typedef lcos::detail::future_data<result_type> shared_state;
1288  
1289  
        boost::intrusive_ptr<shared_state> p(new shared_state());
1290  
        p->set_value(std::forward<Result>(init));
1291  
1292  
        return hpx::traits::future_access<future<result_type> >::create(std::move(p));
1293  
    }
1294  
1295  
    // extension: create a pre-initialized future object which holds the
1296  
    // given error
1297  
    template <typename T>
1298  
    future<T> make_exceptional_future(boost::exception_ptr const& e)
1299  
    {
1300  
        typedef lcos::detail::future_data<T> shared_state;
1301  
1302  
        boost::intrusive_ptr<shared_state> p(new shared_state());
1303  
        p->set_exception(e);
1304  
1305  
        return hpx::traits::future_access<future<T> >::create(std::move(p));
1306  
    }
1307  
1308  
    template <typename T, typename E>
1309  
    future<T> make_exceptional_future(E e)
1310  
    {
1311  
        try
1312  
        {
1313  
            boost::throw_exception(e);
1314  
        } catch (...) {
1315  
            return lcos::make_exceptional_future<T>(boost::current_exception());
1316  
        }
1317  
1318  
        return future<T>();
1319  
    }
1320  
1321  
    // extension: create a pre-initialized future object which gets ready at
1322  
    // a given point in time
1323  
    template <typename Result>
1324  
    future<typename hpx::util::decay_unwrap<Result>::type>
1325  
    make_ready_future_at(hpx::util::steady_time_point const& abs_time,
1326  
        Result&& init)
1327  
    {
1328  
        typedef typename hpx::util::decay_unwrap<Result>::type result_type;
1329  
        typedef lcos::detail::timed_future_data<result_type> shared_state;
1330  
1331  
        return hpx::traits::future_access<future<result_type> >::create(
1332  
            new shared_state(abs_time.value(), std::forward<Result>(init)));
1333  
    }
1334  
1335  
    template <typename Result>
1336  
    future<typename hpx::util::decay_unwrap<Result>::type>
1337  
    make_ready_future_after(hpx::util::steady_duration const& rel_time,
1338  
        Result && init)
1339  
    {
1340  
        return make_ready_future_at(rel_time.from_now(),
1341  
            std::forward<Result>(init));
1342  
    }
1343  
1344  
    // extension: create a pre-initialized future object
1345  
    inline future<void> make_ready_future()
1346  
    {
1347  
        typedef lcos::detail::future_data<void> shared_state;
1348  
1349  
        boost::intrusive_ptr<shared_state> p(new shared_state());
1350  
        p->set_value(hpx::util::unused);
1351  
1352  
        return hpx::traits::future_access<future<void> >::create(std::move(p));
1353  
    }
1354  
1355  
    // extension: create a pre-initialized future object which gets ready at
1356  
    // a given point in time
1357  
    inline future<void> make_ready_future_at(
1358  
        hpx::util::steady_time_point const& abs_time)
1359  
    {
1360  
        typedef lcos::detail::timed_future_data<void> shared_state;
1361  
1362  
        return hpx::traits::future_access<future<void> >::create(
1363  
            new shared_state(abs_time.value(), hpx::util::unused));
1364  
    }
1365  
1366  
    inline future<void> make_ready_future_after(
1367  
        hpx::util::steady_duration const& rel_time)
1368  
    {
1369  
        return make_ready_future_at(rel_time.from_now());
1370  
    }
1371  
}}
1372  
1373  
namespace hpx { namespace serialization
1374  
{
1375  
    template <typename Archive, typename T>
1376  
    HPX_FORCEINLINE
1377  
    void serialize(Archive& ar, ::hpx::lcos::future<T>& f, unsigned version)
1378  
    {
1379  
        hpx::lcos::detail::serialize_future(ar, f, version);
1380  
    }
1381  
1382  
    template <typename Archive, typename T>
1383  
    HPX_FORCEINLINE
1384  
    void serialize(Archive& ar, ::hpx::lcos::shared_future<T>& f, unsigned version)
1385  
    {
1386  
        hpx::lcos::detail::serialize_future(ar, f, version);
1387  
    }
1388  
}}
1389  
1390  
#include <hpx/lcos/local/packaged_continuation.hpp>
1391  
1392  
///////////////////////////////////////////////////////////////////////////////
1393  
// hoist names into main namespace
1394  
namespace hpx
1395  
{
1396  
    using lcos::make_ready_future;
1397  
    using lcos::make_exceptional_future;
1398  
    using lcos::make_ready_future_at;
1399  
    using lcos::make_ready_future_after;
1400  
1401  
    using lcos::make_future;
1402  
}
1403  
1404  
#define HPX_MAKE_EXCEPTIONAL_FUTURE(T, errorcode, f, msg)                     \
1405  
    hpx::make_exceptional_future<T>(HPX_GET_EXCEPTION(errorcode, f, msg))     \
1406  
    /**/
1407  
1408  
#endif
1409  

Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.