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