• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // impl/use_future.hpp
3 // ~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef BOOST_ASIO_IMPL_USE_FUTURE_HPP
12 #define BOOST_ASIO_IMPL_USE_FUTURE_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include <boost/asio/detail/config.hpp>
19 #include <tuple>
20 #include <boost/asio/async_result.hpp>
21 #include <boost/asio/detail/memory.hpp>
22 #include <boost/asio/dispatch.hpp>
23 #include <boost/system/error_code.hpp>
24 #include <boost/asio/execution.hpp>
25 #include <boost/asio/packaged_task.hpp>
26 #include <boost/system/system_error.hpp>
27 #include <boost/asio/system_executor.hpp>
28 
29 #include <boost/asio/detail/push_options.hpp>
30 
31 namespace boost {
32 namespace asio {
33 namespace detail {
34 
35 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
36 
37 template <typename T, typename F, typename... Args>
promise_invoke_and_set(std::promise<T> & p,F & f,BOOST_ASIO_MOVE_ARG (Args)...args)38 inline void promise_invoke_and_set(std::promise<T>& p,
39     F& f, BOOST_ASIO_MOVE_ARG(Args)... args)
40 {
41 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
42   try
43 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
44   {
45     p.set_value(f(BOOST_ASIO_MOVE_CAST(Args)(args)...));
46   }
47 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
48   catch (...)
49   {
50     p.set_exception(std::current_exception());
51   }
52 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
53 }
54 
55 template <typename F, typename... Args>
promise_invoke_and_set(std::promise<void> & p,F & f,BOOST_ASIO_MOVE_ARG (Args)...args)56 inline void promise_invoke_and_set(std::promise<void>& p,
57     F& f, BOOST_ASIO_MOVE_ARG(Args)... args)
58 {
59 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
60   try
61 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
62   {
63     f(BOOST_ASIO_MOVE_CAST(Args)(args)...);
64     p.set_value();
65   }
66 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
67   catch (...)
68   {
69     p.set_exception(std::current_exception());
70   }
71 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
72 }
73 
74 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
75 
76 template <typename T, typename F>
77 inline void promise_invoke_and_set(std::promise<T>& p, F& f)
78 {
79 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
80   try
81 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
82   {
83     p.set_value(f());
84   }
85 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
86   catch (...)
87   {
88     p.set_exception(std::current_exception());
89   }
90 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
91 }
92 
93 template <typename F, typename Args>
94 inline void promise_invoke_and_set(std::promise<void>& p, F& f)
95 {
96 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
97   try
98 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
99   {
100     f();
101     p.set_value();
102 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
103   }
104   catch (...)
105   {
106     p.set_exception(std::current_exception());
107   }
108 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
109 }
110 
111 #if defined(BOOST_ASIO_NO_EXCEPTIONS)
112 
113 #define BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
114   template <typename T, typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
115   inline void promise_invoke_and_set(std::promise<T>& p, \
116       F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
117   { \
118     p.set_value(f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
119   } \
120   \
121   template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
122   inline void promise_invoke_and_set(std::promise<void>& p, \
123       F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
124   { \
125     f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
126     p.set_value(); \
127   } \
128   /**/
129   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF)
130 #undef BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF
131 
132 #else // defined(BOOST_ASIO_NO_EXCEPTIONS)
133 
134 #define BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
135   template <typename T, typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
136   inline void promise_invoke_and_set(std::promise<T>& p, \
137       F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
138   { \
139     try \
140     { \
141       p.set_value(f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
142     } \
143     catch (...) \
144     { \
145       p.set_exception(std::current_exception()); \
146     } \
147   } \
148   \
149   template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
150   inline void promise_invoke_and_set(std::promise<void>& p, \
151       F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
152   { \
153     try \
154     { \
155       f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
156       p.set_value(); \
157     } \
158     catch (...) \
159     { \
160       p.set_exception(std::current_exception()); \
161     } \
162   } \
163   /**/
164   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF)
165 #undef BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF
166 
167 #endif // defined(BOOST_ASIO_NO_EXCEPTIONS)
168 
169 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
170 
171 // A function object adapter to invoke a nullary function object and capture
172 // any exception thrown into a promise.
173 template <typename T, typename F>
174 class promise_invoker
175 {
176 public:
promise_invoker(const shared_ptr<std::promise<T>> & p,BOOST_ASIO_MOVE_ARG (F)f)177   promise_invoker(const shared_ptr<std::promise<T> >& p,
178       BOOST_ASIO_MOVE_ARG(F) f)
179     : p_(p), f_(BOOST_ASIO_MOVE_CAST(F)(f))
180   {
181   }
182 
operator ()()183   void operator()()
184   {
185 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
186     try
187 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
188     {
189       f_();
190     }
191 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
192     catch (...)
193     {
194       p_->set_exception(std::current_exception());
195     }
196 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
197   }
198 
199 private:
200   shared_ptr<std::promise<T> > p_;
201   typename decay<F>::type f_;
202 };
203 
204 // An executor that adapts the system_executor to capture any exeption thrown
205 // by a submitted function object and save it into a promise.
206 template <typename T, typename Blocking = execution::blocking_t::possibly_t>
207 class promise_executor
208 {
209 public:
promise_executor(const shared_ptr<std::promise<T>> & p)210   explicit promise_executor(const shared_ptr<std::promise<T> >& p)
211     : p_(p)
212   {
213   }
214 
query(execution::blocking_t)215   static BOOST_ASIO_CONSTEXPR Blocking query(execution::blocking_t)
216   {
217     return Blocking();
218   }
219 
220   promise_executor<T, execution::blocking_t::possibly_t>
require(execution::blocking_t::possibly_t) const221   require(execution::blocking_t::possibly_t) const
222   {
223     return promise_executor<T, execution::blocking_t::possibly_t>(p_);
224   }
225 
226   promise_executor<T, execution::blocking_t::never_t>
require(execution::blocking_t::never_t) const227   require(execution::blocking_t::never_t) const
228   {
229     return promise_executor<T, execution::blocking_t::never_t>(p_);
230   }
231 
232   template <typename F>
execute(BOOST_ASIO_MOVE_ARG (F)f) const233   void execute(BOOST_ASIO_MOVE_ARG(F) f) const
234   {
235     execution::execute(
236         boost::asio::require(system_executor(), Blocking()),
237         promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)));
238   }
239 
240 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
context() const241   execution_context& context() const BOOST_ASIO_NOEXCEPT
242   {
243     return system_executor().context();
244   }
245 
on_work_started() const246   void on_work_started() const BOOST_ASIO_NOEXCEPT {}
on_work_finished() const247   void on_work_finished() const BOOST_ASIO_NOEXCEPT {}
248 
249   template <typename F, typename A>
dispatch(BOOST_ASIO_MOVE_ARG (F)f,const A &) const250   void dispatch(BOOST_ASIO_MOVE_ARG(F) f, const A&) const
251   {
252     promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f))();
253   }
254 
255   template <typename F, typename A>
post(BOOST_ASIO_MOVE_ARG (F)f,const A & a) const256   void post(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
257   {
258     system_executor().post(
259         promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)), a);
260   }
261 
262   template <typename F, typename A>
defer(BOOST_ASIO_MOVE_ARG (F)f,const A & a) const263   void defer(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
264   {
265     system_executor().defer(
266         promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)), a);
267   }
268 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
269 
operator ==(const promise_executor & a,const promise_executor & b)270   friend bool operator==(const promise_executor& a,
271       const promise_executor& b) BOOST_ASIO_NOEXCEPT
272   {
273     return a.p_ == b.p_;
274   }
275 
operator !=(const promise_executor & a,const promise_executor & b)276   friend bool operator!=(const promise_executor& a,
277       const promise_executor& b) BOOST_ASIO_NOEXCEPT
278   {
279     return a.p_ != b.p_;
280   }
281 
282 private:
283   shared_ptr<std::promise<T> > p_;
284 };
285 
286 // The base class for all completion handlers that create promises.
287 template <typename T>
288 class promise_creator
289 {
290 public:
291   typedef promise_executor<T> executor_type;
292 
get_executor() const293   executor_type get_executor() const BOOST_ASIO_NOEXCEPT
294   {
295     return executor_type(p_);
296   }
297 
298   typedef std::future<T> future_type;
299 
get_future()300   future_type get_future()
301   {
302     return p_->get_future();
303   }
304 
305 protected:
306   template <typename Allocator>
create_promise(const Allocator & a)307   void create_promise(const Allocator& a)
308   {
309     BOOST_ASIO_REBIND_ALLOC(Allocator, char) b(a);
310     p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b);
311   }
312 
313   shared_ptr<std::promise<T> > p_;
314 };
315 
316 // For completion signature void().
317 class promise_handler_0
318   : public promise_creator<void>
319 {
320 public:
operator ()()321   void operator()()
322   {
323     this->p_->set_value();
324   }
325 };
326 
327 // For completion signature void(error_code).
328 class promise_handler_ec_0
329   : public promise_creator<void>
330 {
331 public:
operator ()(const boost::system::error_code & ec)332   void operator()(const boost::system::error_code& ec)
333   {
334     if (ec)
335     {
336       this->p_->set_exception(
337           std::make_exception_ptr(
338             boost::system::system_error(ec)));
339     }
340     else
341     {
342       this->p_->set_value();
343     }
344   }
345 };
346 
347 // For completion signature void(exception_ptr).
348 class promise_handler_ex_0
349   : public promise_creator<void>
350 {
351 public:
operator ()(const std::exception_ptr & ex)352   void operator()(const std::exception_ptr& ex)
353   {
354     if (ex)
355     {
356       this->p_->set_exception(ex);
357     }
358     else
359     {
360       this->p_->set_value();
361     }
362   }
363 };
364 
365 // For completion signature void(T).
366 template <typename T>
367 class promise_handler_1
368   : public promise_creator<T>
369 {
370 public:
371   template <typename Arg>
operator ()(BOOST_ASIO_MOVE_ARG (Arg)arg)372   void operator()(BOOST_ASIO_MOVE_ARG(Arg) arg)
373   {
374     this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
375   }
376 };
377 
378 // For completion signature void(error_code, T).
379 template <typename T>
380 class promise_handler_ec_1
381   : public promise_creator<T>
382 {
383 public:
384   template <typename Arg>
operator ()(const boost::system::error_code & ec,BOOST_ASIO_MOVE_ARG (Arg)arg)385   void operator()(const boost::system::error_code& ec,
386       BOOST_ASIO_MOVE_ARG(Arg) arg)
387   {
388     if (ec)
389     {
390       this->p_->set_exception(
391           std::make_exception_ptr(
392             boost::system::system_error(ec)));
393     }
394     else
395       this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
396   }
397 };
398 
399 // For completion signature void(exception_ptr, T).
400 template <typename T>
401 class promise_handler_ex_1
402   : public promise_creator<T>
403 {
404 public:
405   template <typename Arg>
operator ()(const std::exception_ptr & ex,BOOST_ASIO_MOVE_ARG (Arg)arg)406   void operator()(const std::exception_ptr& ex,
407       BOOST_ASIO_MOVE_ARG(Arg) arg)
408   {
409     if (ex)
410       this->p_->set_exception(ex);
411     else
412       this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
413   }
414 };
415 
416 // For completion signature void(T1, ..., Tn);
417 template <typename T>
418 class promise_handler_n
419   : public promise_creator<T>
420 {
421 public:
422 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
423 
424   template <typename... Args>
operator ()(BOOST_ASIO_MOVE_ARG (Args)...args)425   void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
426   {
427     this->p_->set_value(
428         std::forward_as_tuple(
429           BOOST_ASIO_MOVE_CAST(Args)(args)...));
430   }
431 
432 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
433 
434 #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
435   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
436   void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
437   {\
438     this->p_->set_value( \
439         std::forward_as_tuple( \
440           BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
441   } \
442   /**/
443   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
444 #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
445 
446 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
447 };
448 
449 // For completion signature void(error_code, T1, ..., Tn);
450 template <typename T>
451 class promise_handler_ec_n
452   : public promise_creator<T>
453 {
454 public:
455 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
456 
457   template <typename... Args>
operator ()(const boost::system::error_code & ec,BOOST_ASIO_MOVE_ARG (Args)...args)458   void operator()(const boost::system::error_code& ec,
459       BOOST_ASIO_MOVE_ARG(Args)... args)
460   {
461     if (ec)
462     {
463       this->p_->set_exception(
464           std::make_exception_ptr(
465             boost::system::system_error(ec)));
466     }
467     else
468     {
469       this->p_->set_value(
470           std::forward_as_tuple(
471             BOOST_ASIO_MOVE_CAST(Args)(args)...));
472     }
473   }
474 
475 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
476 
477 #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
478   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
479   void operator()(const boost::system::error_code& ec, \
480       BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
481   {\
482     if (ec) \
483     { \
484       this->p_->set_exception( \
485           std::make_exception_ptr( \
486             boost::system::system_error(ec))); \
487     } \
488     else \
489     { \
490       this->p_->set_value( \
491           std::forward_as_tuple( \
492             BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
493     } \
494   } \
495   /**/
496   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
497 #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
498 
499 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
500 };
501 
502 // For completion signature void(exception_ptr, T1, ..., Tn);
503 template <typename T>
504 class promise_handler_ex_n
505   : public promise_creator<T>
506 {
507 public:
508 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
509 
510   template <typename... Args>
operator ()(const std::exception_ptr & ex,BOOST_ASIO_MOVE_ARG (Args)...args)511   void operator()(const std::exception_ptr& ex,
512       BOOST_ASIO_MOVE_ARG(Args)... args)
513   {
514     if (ex)
515       this->p_->set_exception(ex);
516     else
517     {
518       this->p_->set_value(
519           std::forward_as_tuple(
520             BOOST_ASIO_MOVE_CAST(Args)(args)...));
521     }
522   }
523 
524 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
525 
526 #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
527   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
528   void operator()(const std::exception_ptr& ex, \
529       BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
530   {\
531     if (ex) \
532       this->p_->set_exception(ex); \
533     else \
534     { \
535       this->p_->set_value( \
536           std::forward_as_tuple( \
537             BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
538     } \
539   } \
540   /**/
541   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
542 #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
543 
544 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
545 };
546 
547 // Helper template to choose the appropriate concrete promise handler
548 // implementation based on the supplied completion signature.
549 template <typename> class promise_handler_selector;
550 
551 template <>
552 class promise_handler_selector<void()>
553   : public promise_handler_0 {};
554 
555 template <>
556 class promise_handler_selector<void(boost::system::error_code)>
557   : public promise_handler_ec_0 {};
558 
559 template <>
560 class promise_handler_selector<void(std::exception_ptr)>
561   : public promise_handler_ex_0 {};
562 
563 template <typename Arg>
564 class promise_handler_selector<void(Arg)>
565   : public promise_handler_1<Arg> {};
566 
567 template <typename Arg>
568 class promise_handler_selector<void(boost::system::error_code, Arg)>
569   : public promise_handler_ec_1<Arg> {};
570 
571 template <typename Arg>
572 class promise_handler_selector<void(std::exception_ptr, Arg)>
573   : public promise_handler_ex_1<Arg> {};
574 
575 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
576 
577 template <typename... Arg>
578 class promise_handler_selector<void(Arg...)>
579   : public promise_handler_n<std::tuple<Arg...> > {};
580 
581 template <typename... Arg>
582 class promise_handler_selector<void(boost::system::error_code, Arg...)>
583   : public promise_handler_ec_n<std::tuple<Arg...> > {};
584 
585 template <typename... Arg>
586 class promise_handler_selector<void(std::exception_ptr, Arg...)>
587   : public promise_handler_ex_n<std::tuple<Arg...> > {};
588 
589 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
590 
591 #define BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF(n) \
592   template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
593   class promise_handler_selector< \
594     void(Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
595       : public promise_handler_n< \
596         std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
597   \
598   template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
599   class promise_handler_selector< \
600     void(boost::system::error_code, Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
601       : public promise_handler_ec_n< \
602         std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
603   \
604   template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
605   class promise_handler_selector< \
606     void(std::exception_ptr, Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
607       : public promise_handler_ex_n< \
608         std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
609   /**/
610   BOOST_ASIO_VARIADIC_GENERATE_5(BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF)
611 #undef BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF
612 
613 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
614 
615 // Completion handlers produced from the use_future completion token, when not
616 // using use_future::operator().
617 template <typename Signature, typename Allocator>
618 class promise_handler
619   : public promise_handler_selector<Signature>
620 {
621 public:
622   typedef Allocator allocator_type;
623   typedef void result_type;
624 
promise_handler(use_future_t<Allocator> u)625   promise_handler(use_future_t<Allocator> u)
626     : allocator_(u.get_allocator())
627   {
628     this->create_promise(allocator_);
629   }
630 
get_allocator() const631   allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
632   {
633     return allocator_;
634   }
635 
636 private:
637   Allocator allocator_;
638 };
639 
640 template <typename Function>
641 struct promise_function_wrapper
642 {
promise_function_wrapperboost::asio::detail::promise_function_wrapper643   explicit promise_function_wrapper(Function& f)
644     : function_(BOOST_ASIO_MOVE_CAST(Function)(f))
645   {
646   }
647 
promise_function_wrapperboost::asio::detail::promise_function_wrapper648   explicit promise_function_wrapper(const Function& f)
649     : function_(f)
650   {
651   }
652 
operator ()boost::asio::detail::promise_function_wrapper653   void operator()()
654   {
655     function_();
656   }
657 
658   Function function_;
659 };
660 
661 #if !defined(BOOST_ASIO_NO_DEPRECATED)
662 
663 template <typename Function, typename Signature, typename Allocator>
asio_handler_invoke(Function & f,promise_handler<Signature,Allocator> * h)664 inline void asio_handler_invoke(Function& f,
665     promise_handler<Signature, Allocator>* h)
666 {
667   typename promise_handler<Signature, Allocator>::executor_type
668     ex(h->get_executor());
669   boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
670 }
671 
672 template <typename Function, typename Signature, typename Allocator>
asio_handler_invoke(const Function & f,promise_handler<Signature,Allocator> * h)673 inline void asio_handler_invoke(const Function& f,
674     promise_handler<Signature, Allocator>* h)
675 {
676   typename promise_handler<Signature, Allocator>::executor_type
677     ex(h->get_executor());
678   boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
679 }
680 
681 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
682 
683 // Helper base class for async_result specialisation.
684 template <typename Signature, typename Allocator>
685 class promise_async_result
686 {
687 public:
688   typedef promise_handler<Signature, Allocator> completion_handler_type;
689   typedef typename completion_handler_type::future_type return_type;
690 
promise_async_result(completion_handler_type & h)691   explicit promise_async_result(completion_handler_type& h)
692     : future_(h.get_future())
693   {
694   }
695 
get()696   return_type get()
697   {
698     return BOOST_ASIO_MOVE_CAST(return_type)(future_);
699   }
700 
701 private:
702   return_type future_;
703 };
704 
705 // Return value from use_future::operator().
706 template <typename Function, typename Allocator>
707 class packaged_token
708 {
709 public:
packaged_token(Function f,const Allocator & a)710   packaged_token(Function f, const Allocator& a)
711     : function_(BOOST_ASIO_MOVE_CAST(Function)(f)),
712       allocator_(a)
713   {
714   }
715 
716 //private:
717   Function function_;
718   Allocator allocator_;
719 };
720 
721 // Completion handlers produced from the use_future completion token, when
722 // using use_future::operator().
723 template <typename Function, typename Allocator, typename Result>
724 class packaged_handler
725   : public promise_creator<Result>
726 {
727 public:
728   typedef Allocator allocator_type;
729   typedef void result_type;
730 
packaged_handler(packaged_token<Function,Allocator> t)731   packaged_handler(packaged_token<Function, Allocator> t)
732     : function_(BOOST_ASIO_MOVE_CAST(Function)(t.function_)),
733       allocator_(t.allocator_)
734   {
735     this->create_promise(allocator_);
736   }
737 
get_allocator() const738   allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
739   {
740     return allocator_;
741   }
742 
743 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
744 
745   template <typename... Args>
operator ()(BOOST_ASIO_MOVE_ARG (Args)...args)746   void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
747   {
748     (promise_invoke_and_set)(*this->p_,
749         function_, BOOST_ASIO_MOVE_CAST(Args)(args)...);
750   }
751 
752 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
753 
operator ()()754   void operator()()
755   {
756     (promise_invoke_and_set)(*this->p_, function_);
757   }
758 
759 #define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
760   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
761   void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
762   {\
763     (promise_invoke_and_set)(*this->p_, \
764         function_, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
765   } \
766   /**/
767   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
768 #undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
769 
770 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
771 
772 private:
773   Function function_;
774   Allocator allocator_;
775 };
776 
777 #if !defined(BOOST_ASIO_NO_DEPRECATED)
778 
779 template <typename Function,
780     typename Function1, typename Allocator, typename Result>
asio_handler_invoke(Function & f,packaged_handler<Function1,Allocator,Result> * h)781 inline void asio_handler_invoke(Function& f,
782     packaged_handler<Function1, Allocator, Result>* h)
783 {
784   typename packaged_handler<Function1, Allocator, Result>::executor_type
785     ex(h->get_executor());
786   boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
787 }
788 
789 template <typename Function,
790     typename Function1, typename Allocator, typename Result>
asio_handler_invoke(const Function & f,packaged_handler<Function1,Allocator,Result> * h)791 inline void asio_handler_invoke(const Function& f,
792     packaged_handler<Function1, Allocator, Result>* h)
793 {
794   typename packaged_handler<Function1, Allocator, Result>::executor_type
795     ex(h->get_executor());
796   boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
797 }
798 
799 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
800 
801 // Helper base class for async_result specialisation.
802 template <typename Function, typename Allocator, typename Result>
803 class packaged_async_result
804 {
805 public:
806   typedef packaged_handler<Function, Allocator, Result> completion_handler_type;
807   typedef typename completion_handler_type::future_type return_type;
808 
packaged_async_result(completion_handler_type & h)809   explicit packaged_async_result(completion_handler_type& h)
810     : future_(h.get_future())
811   {
812   }
813 
get()814   return_type get()
815   {
816     return BOOST_ASIO_MOVE_CAST(return_type)(future_);
817   }
818 
819 private:
820   return_type future_;
821 };
822 
823 } // namespace detail
824 
825 template <typename Allocator> template <typename Function>
826 inline detail::packaged_token<typename decay<Function>::type, Allocator>
operator ()(BOOST_ASIO_MOVE_ARG (Function)f) const827 use_future_t<Allocator>::operator()(BOOST_ASIO_MOVE_ARG(Function) f) const
828 {
829   return detail::packaged_token<typename decay<Function>::type, Allocator>(
830       BOOST_ASIO_MOVE_CAST(Function)(f), allocator_);
831 }
832 
833 #if !defined(GENERATING_DOCUMENTATION)
834 
835 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
836 
837 template <typename Allocator, typename Result, typename... Args>
838 class async_result<use_future_t<Allocator>, Result(Args...)>
839   : public detail::promise_async_result<
840       void(typename decay<Args>::type...), Allocator>
841 {
842 public:
async_result(typename detail::promise_async_result<void (typename decay<Args>::type...),Allocator>::completion_handler_type & h)843   explicit async_result(
844     typename detail::promise_async_result<void(typename decay<Args>::type...),
845       Allocator>::completion_handler_type& h)
846     : detail::promise_async_result<
847         void(typename decay<Args>::type...), Allocator>(h)
848   {
849   }
850 };
851 
852 template <typename Function, typename Allocator,
853     typename Result, typename... Args>
854 class async_result<detail::packaged_token<Function, Allocator>, Result(Args...)>
855   : public detail::packaged_async_result<Function, Allocator,
856       typename result_of<Function(Args...)>::type>
857 {
858 public:
async_result(typename detail::packaged_async_result<Function,Allocator,typename result_of<Function (Args...)>::type>::completion_handler_type & h)859   explicit async_result(
860     typename detail::packaged_async_result<Function, Allocator,
861       typename result_of<Function(Args...)>::type>::completion_handler_type& h)
862     : detail::packaged_async_result<Function, Allocator,
863         typename result_of<Function(Args...)>::type>(h)
864   {
865   }
866 };
867 
868 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
869 
870 template <typename Allocator, typename Result>
871 class async_result<use_future_t<Allocator>, Result()>
872   : public detail::promise_async_result<void(), Allocator>
873 {
874 public:
async_result(typename detail::promise_async_result<void (),Allocator>::completion_handler_type & h)875   explicit async_result(
876     typename detail::promise_async_result<
877       void(), Allocator>::completion_handler_type& h)
878     : detail::promise_async_result<void(), Allocator>(h)
879   {
880   }
881 };
882 
883 template <typename Function, typename Allocator, typename Result>
884 class async_result<detail::packaged_token<Function, Allocator>, Result()>
885   : public detail::packaged_async_result<Function, Allocator,
886       typename result_of<Function()>::type>
887 {
888 public:
async_result(typename detail::packaged_async_result<Function,Allocator,typename result_of<Function ()>::type>::completion_handler_type & h)889   explicit async_result(
890     typename detail::packaged_async_result<Function, Allocator,
891       typename result_of<Function()>::type>::completion_handler_type& h)
892     : detail::packaged_async_result<Function, Allocator,
893         typename result_of<Function()>::type>(h)
894   {
895   }
896 };
897 
898 #define BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \
899   template <typename Allocator, \
900       typename Result, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
901   class async_result<use_future_t<Allocator>, \
902       Result(BOOST_ASIO_VARIADIC_TARGS(n))> \
903     : public detail::promise_async_result< \
904         void(BOOST_ASIO_VARIADIC_DECAY(n)), Allocator> \
905   { \
906   public: \
907     explicit async_result( \
908       typename detail::promise_async_result< \
909         void(BOOST_ASIO_VARIADIC_DECAY(n)), \
910         Allocator>::completion_handler_type& h) \
911       : detail::promise_async_result< \
912           void(BOOST_ASIO_VARIADIC_DECAY(n)), Allocator>(h) \
913     { \
914     } \
915   }; \
916   \
917   template <typename Function, typename Allocator, \
918       typename Result, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
919   class async_result<detail::packaged_token<Function, Allocator>, \
920       Result(BOOST_ASIO_VARIADIC_TARGS(n))> \
921     : public detail::packaged_async_result<Function, Allocator, \
922         typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type> \
923   { \
924   public: \
925     explicit async_result( \
926       typename detail::packaged_async_result<Function, Allocator, \
927         typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type \
928         >::completion_handler_type& h) \
929       : detail::packaged_async_result<Function, Allocator, \
930           typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type>(h) \
931     { \
932     } \
933   }; \
934   /**/
935   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF)
936 #undef BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF
937 
938 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
939 
940 namespace traits {
941 
942 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
943 
944 template <typename T, typename Blocking>
945 struct equality_comparable<
946     boost::asio::detail::promise_executor<T, Blocking> >
947 {
948   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
949   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
950 };
951 
952 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
953 
954 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
955 
956 template <typename T, typename Blocking, typename Function>
957 struct execute_member<
958     boost::asio::detail::promise_executor<T, Blocking>, Function>
959 {
960   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
961   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
962   typedef void result_type;
963 };
964 
965 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
966 
967 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)
968 
969 template <typename T, typename Blocking, typename Property>
970 struct query_static_constexpr_member<
971     boost::asio::detail::promise_executor<T, Blocking>,
972     Property,
973     typename boost::asio::enable_if<
974       boost::asio::is_convertible<
975         Property,
976         boost::asio::execution::blocking_t
977       >::value
978     >::type
979   >
980 {
981   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
982   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
983   typedef Blocking result_type;
984 
valueboost::asio::traits::query_static_constexpr_member985   static BOOST_ASIO_CONSTEXPR result_type value() BOOST_ASIO_NOEXCEPT
986   {
987     return Blocking();
988   }
989 };
990 
991 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)
992 
993 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
994 
995 template <typename T, typename Blocking>
996 struct require_member<
997     boost::asio::detail::promise_executor<T, Blocking>,
998     execution::blocking_t::possibly_t
999   >
1000 {
1001   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1002   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1003   typedef boost::asio::detail::promise_executor<T,
1004       execution::blocking_t::possibly_t> result_type;
1005 };
1006 
1007 template <typename T, typename Blocking>
1008 struct require_member<
1009     boost::asio::detail::promise_executor<T, Blocking>,
1010     execution::blocking_t::never_t
1011   >
1012 {
1013   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
1014   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
1015   typedef boost::asio::detail::promise_executor<T,
1016       execution::blocking_t::never_t> result_type;
1017 };
1018 
1019 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
1020 
1021 } // namespace traits
1022 
1023 #endif // !defined(GENERATING_DOCUMENTATION)
1024 
1025 } // namespace asio
1026 } // namespace boost
1027 
1028 #include <boost/asio/detail/pop_options.hpp>
1029 
1030 #endif // BOOST_ASIO_IMPL_USE_FUTURE_HPP
1031