]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/impl/use_future.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / asio / impl / use_future.hpp
CommitLineData
b32b8144
FG
1//
2// impl/use_future.hpp
3// ~~~~~~~~~~~~~~~~~~~
4//
f67539c2 5// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
b32b8144
FG
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>
b32b8144
FG
19#include <tuple>
20#include <boost/asio/async_result.hpp>
21#include <boost/asio/detail/memory.hpp>
20effc67 22#include <boost/asio/dispatch.hpp>
b32b8144 23#include <boost/system/error_code.hpp>
20effc67 24#include <boost/asio/execution.hpp>
b32b8144
FG
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
31namespace boost {
32namespace asio {
33namespace detail {
34
35#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
36
37template <typename T, typename F, typename... Args>
38inline 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
55template <typename F, typename... Args>
56inline 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
76template <typename T, typename F>
77inline 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
93template <typename F, typename Args>
94inline 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.
173template <typename T, typename F>
174class promise_invoker
175{
176public:
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
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
199private:
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.
20effc67 206template <typename T, typename Blocking = execution::blocking_t::possibly_t>
b32b8144
FG
207class promise_executor
208{
209public:
210 explicit promise_executor(const shared_ptr<std::promise<T> >& p)
211 : p_(p)
212 {
213 }
214
20effc67
TL
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>
221 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>
227 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>
233 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)
b32b8144
FG
241 execution_context& context() const BOOST_ASIO_NOEXCEPT
242 {
243 return system_executor().context();
244 }
245
246 void on_work_started() const BOOST_ASIO_NOEXCEPT {}
247 void on_work_finished() const BOOST_ASIO_NOEXCEPT {}
248
249 template <typename F, typename A>
250 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>
256 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>
263 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 }
20effc67 268#endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
b32b8144
FG
269
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
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
282private:
283 shared_ptr<std::promise<T> > p_;
284};
285
286// The base class for all completion handlers that create promises.
287template <typename T>
288class promise_creator
289{
290public:
291 typedef promise_executor<T> executor_type;
292
293 executor_type get_executor() const BOOST_ASIO_NOEXCEPT
294 {
295 return executor_type(p_);
296 }
297
298 typedef std::future<T> future_type;
299
300 future_type get_future()
301 {
302 return p_->get_future();
303 }
304
305protected:
306 template <typename Allocator>
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().
317class promise_handler_0
318 : public promise_creator<void>
319{
320public:
321 void operator()()
322 {
323 this->p_->set_value();
324 }
325};
326
327// For completion signature void(error_code).
328class promise_handler_ec_0
329 : public promise_creator<void>
330{
331public:
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).
348class promise_handler_ex_0
349 : public promise_creator<void>
350{
351public:
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).
366template <typename T>
367class promise_handler_1
368 : public promise_creator<T>
369{
370public:
371 template <typename 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).
379template <typename T>
380class promise_handler_ec_1
381 : public promise_creator<T>
382{
383public:
384 template <typename 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).
400template <typename T>
401class promise_handler_ex_1
402 : public promise_creator<T>
403{
404public:
405 template <typename 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);
417template <typename T>
418class promise_handler_n
419 : public promise_creator<T>
420{
421public:
422#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
423
424 template <typename... 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);
450template <typename T>
451class promise_handler_ec_n
452 : public promise_creator<T>
453{
454public:
455#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
456
457 template <typename... 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);
503template <typename T>
504class promise_handler_ex_n
505 : public promise_creator<T>
506{
507public:
508#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
509
510 template <typename... 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.
549template <typename> class promise_handler_selector;
550
551template <>
552class promise_handler_selector<void()>
553 : public promise_handler_0 {};
554
555template <>
556class promise_handler_selector<void(boost::system::error_code)>
557 : public promise_handler_ec_0 {};
558
559template <>
560class promise_handler_selector<void(std::exception_ptr)>
561 : public promise_handler_ex_0 {};
562
563template <typename Arg>
564class promise_handler_selector<void(Arg)>
565 : public promise_handler_1<Arg> {};
566
567template <typename Arg>
568class promise_handler_selector<void(boost::system::error_code, Arg)>
569 : public promise_handler_ec_1<Arg> {};
570
571template <typename Arg>
572class 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
577template <typename... Arg>
578class promise_handler_selector<void(Arg...)>
579 : public promise_handler_n<std::tuple<Arg...> > {};
580
581template <typename... Arg>
582class promise_handler_selector<void(boost::system::error_code, Arg...)>
583 : public promise_handler_ec_n<std::tuple<Arg...> > {};
584
585template <typename... Arg>
586class 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 /**/
20effc67 610 BOOST_ASIO_VARIADIC_GENERATE_5(BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF)
b32b8144
FG
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().
617template <typename Signature, typename Allocator>
618class promise_handler
619 : public promise_handler_selector<Signature>
620{
621public:
622 typedef Allocator allocator_type;
623 typedef void result_type;
624
625 promise_handler(use_future_t<Allocator> u)
626 : allocator_(u.get_allocator())
627 {
628 this->create_promise(allocator_);
629 }
630
631 allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
632 {
633 return allocator_;
634 }
635
636private:
637 Allocator allocator_;
638};
639
20effc67
TL
640template <typename Function>
641struct promise_function_wrapper
642{
643 explicit promise_function_wrapper(Function& f)
644 : function_(BOOST_ASIO_MOVE_CAST(Function)(f))
645 {
646 }
647
648 explicit promise_function_wrapper(const Function& f)
649 : function_(f)
650 {
651 }
652
653 void operator()()
654 {
655 function_();
656 }
657
658 Function function_;
659};
660
661#if !defined(BOOST_ASIO_NO_DEPRECATED)
662
b32b8144
FG
663template <typename Function, typename Signature, typename Allocator>
664inline 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());
20effc67 669 boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
b32b8144
FG
670}
671
672template <typename Function, typename Signature, typename Allocator>
673inline 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());
20effc67 678 boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
b32b8144
FG
679}
680
20effc67
TL
681#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
682
b32b8144
FG
683// Helper base class for async_result specialisation.
684template <typename Signature, typename Allocator>
685class promise_async_result
686{
687public:
688 typedef promise_handler<Signature, Allocator> completion_handler_type;
689 typedef typename completion_handler_type::future_type return_type;
690
691 explicit promise_async_result(completion_handler_type& h)
692 : future_(h.get_future())
693 {
694 }
695
696 return_type get()
697 {
698 return BOOST_ASIO_MOVE_CAST(return_type)(future_);
699 }
700
701private:
702 return_type future_;
703};
704
705// Return value from use_future::operator().
706template <typename Function, typename Allocator>
707class packaged_token
708{
709public:
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().
723template <typename Function, typename Allocator, typename Result>
724class packaged_handler
725 : public promise_creator<Result>
726{
727public:
728 typedef Allocator allocator_type;
729 typedef void result_type;
730
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
738 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>
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
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
772private:
773 Function function_;
774 Allocator allocator_;
775};
776
20effc67
TL
777#if !defined(BOOST_ASIO_NO_DEPRECATED)
778
b32b8144
FG
779template <typename Function,
780 typename Function1, typename Allocator, typename Result>
781inline 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());
20effc67 786 boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
b32b8144
FG
787}
788
789template <typename Function,
790 typename Function1, typename Allocator, typename Result>
791inline 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());
20effc67 796 boost::asio::dispatch(ex, promise_function_wrapper<Function>(f));
b32b8144
FG
797}
798
20effc67
TL
799#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
800
b32b8144
FG
801// Helper base class for async_result specialisation.
802template <typename Function, typename Allocator, typename Result>
803class packaged_async_result
804{
805public:
806 typedef packaged_handler<Function, Allocator, Result> completion_handler_type;
807 typedef typename completion_handler_type::future_type return_type;
808
809 explicit packaged_async_result(completion_handler_type& h)
810 : future_(h.get_future())
811 {
812 }
813
814 return_type get()
815 {
816 return BOOST_ASIO_MOVE_CAST(return_type)(future_);
817 }
818
819private:
820 return_type future_;
821};
822
823} // namespace detail
824
825template <typename Allocator> template <typename Function>
826inline detail::packaged_token<typename decay<Function>::type, Allocator>
827use_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
837template <typename Allocator, typename Result, typename... Args>
838class async_result<use_future_t<Allocator>, Result(Args...)>
839 : public detail::promise_async_result<
840 void(typename decay<Args>::type...), Allocator>
841{
842public:
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
852template <typename Function, typename Allocator,
853 typename Result, typename... Args>
854class 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{
858public:
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
870template <typename Allocator, typename Result>
871class async_result<use_future_t<Allocator>, Result()>
872 : public detail::promise_async_result<void(), Allocator>
873{
874public:
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
883template <typename Function, typename Allocator, typename Result>
884class async_result<detail::packaged_token<Function, Allocator>, Result()>
885 : public detail::packaged_async_result<Function, Allocator,
886 typename result_of<Function()>::type>
887{
888public:
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
20effc67
TL
940namespace traits {
941
942#if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
943
944template <typename T, typename Blocking>
945struct 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
956template <typename T, typename Blocking, typename Function>
957struct 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
969template <typename T, typename Blocking, typename Property>
970struct 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
985 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
995template <typename T, typename Blocking>
996struct 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
1007template <typename T, typename Blocking>
1008struct 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
b32b8144
FG
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