1 
2 //          Copyright Oliver Kowalke 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 //    (See accompanying file LICENSE_1_0.txt or copy at
5 //          http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef BOOST_FIBERS_ASYNC_HPP
8 #define BOOST_FIBERS_ASYNC_HPP
9 
10 #include <algorithm>
11 #include <memory>
12 #include <type_traits>
13 #include <utility>
14 
15 #include <boost/config.hpp>
16 
17 #include <boost/fiber/future/future.hpp>
18 #include <boost/fiber/future/packaged_task.hpp>
19 #include <boost/fiber/policy.hpp>
20 
21 namespace boost {
22 namespace fibers {
23 
24 #if defined(BOOST_MSVC) && (_MSC_VER >= 1911 && _MSVC_LANG >= 201703)
25 template <typename>
26 struct result_of;
27 template <typename F, typename... Args>
28 struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
29 #else
30 using std::result_of;
31 #endif
32 
33 
34 template< typename Fn, typename ... Args >
35 future<
36     typename result_of<
37         typename std::enable_if<
38             ! detail::is_launch_policy< typename std::decay< Fn >::type >::value,
39             typename std::decay< Fn >::type
40         >::type( typename std::decay< Args >::type ... )
41     >::type
42 >
async(Fn && fn,Args...args)43 async( Fn && fn, Args ... args) {
44     typedef typename result_of<
45         typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
46     >::type     result_type;
47 
48     packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
49         std::forward< Fn >( fn) };
50     future< result_type > f{ pt.get_future() };
51     fiber{ std::move( pt), std::forward< Args >( args) ... }.detach();
52     return f;
53 }
54 
55 template< typename Policy, typename Fn, typename ... Args >
56 future<
57     typename result_of<
58         typename std::enable_if<
59             detail::is_launch_policy< Policy >::value,
60             typename std::decay< Fn >::type
61         >::type( typename std::decay< Args >::type ...)
62     >::type
63 >
async(Policy policy,Fn && fn,Args...args)64 async( Policy policy, Fn && fn, Args ... args) {
65     typedef typename result_of<
66         typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
67     >::type     result_type;
68 
69     packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
70         std::forward< Fn >( fn) };
71     future< result_type > f{ pt.get_future() };
72     fiber{ policy, std::move( pt), std::forward< Args >( args) ... }.detach();
73     return f;
74 }
75 
76 template< typename Policy, typename StackAllocator, typename Fn, typename ... Args >
77 future<
78     typename result_of<
79         typename std::enable_if<
80             detail::is_launch_policy< Policy >::value,
81             typename std::decay< Fn >::type
82         >::type( typename std::decay< Args >::type ... )
83     >::type
84 >
async(Policy policy,std::allocator_arg_t,StackAllocator salloc,Fn && fn,Args...args)85 async( Policy policy, std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args ... args) {
86     typedef typename result_of<
87         typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
88     >::type     result_type;
89 
90     packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
91         std::forward< Fn >( fn) };
92     future< result_type > f{ pt.get_future() };
93     fiber{ policy, std::allocator_arg, salloc,
94         std::move( pt), std::forward< Args >( args) ... }.detach();
95     return f;
96 }
97 
98 template< typename Policy, typename StackAllocator, typename Allocator, typename Fn, typename ... Args >
99 future<
100     typename result_of<
101         typename std::enable_if<
102             detail::is_launch_policy< Policy >::value,
103             typename std::decay< Fn >::type
104         >::type( typename std::decay< Args >::type ... )
105     >::type
106 >
async(Policy policy,std::allocator_arg_t,StackAllocator salloc,Allocator alloc,Fn && fn,Args...args)107 async( Policy policy, std::allocator_arg_t, StackAllocator salloc, Allocator alloc, Fn && fn, Args ... args) {
108     typedef typename result_of<
109         typename std::decay< Fn >::type( typename std::decay< Args >::type ... )
110     >::type     result_type;
111 
112     packaged_task< result_type( typename std::decay< Args >::type ... ) > pt{
113         std::allocator_arg, alloc, std::forward< Fn >( fn) };
114     future< result_type > f{ pt.get_future() };
115     fiber{ policy, std::allocator_arg, salloc,
116         std::move( pt), std::forward< Args >( args) ... }.detach();
117     return f;
118 }
119 
120 }}
121 
122 #endif // BOOST_FIBERS_ASYNC_HPP
123