Line | % of fetches | Source |
---|---|---|
1 | // Copyright (c) 2007-2016 Hartmut Kaiser | |
2 | // Copyright (c) 2016 Thomas Heller | |
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 | #ifndef HPX_ACTIONS_TRIGGER_HPP | |
8 | #define HPX_ACTIONS_TRIGGER_HPP | |
9 | ||
10 | #include <hpx/exception.hpp> | |
11 | #include <hpx/lcos/future.hpp> | |
12 | #include <hpx/runtime/actions/continuation_fwd.hpp> | |
13 | #include <hpx/traits/is_future.hpp> | |
14 | #include <hpx/util/assert.hpp> | |
15 | #include <hpx/util/bind.hpp> | |
16 | #include <hpx/util/decay.hpp> | |
17 | #include <hpx/util/invoke.hpp> | |
18 | #include <hpx/util/result_of.hpp> | |
19 | #include <hpx/util/unused.hpp> | |
20 | ||
21 | #include <utility> | |
22 | #include <type_traits> | |
23 | ||
24 | namespace hpx { namespace actions { | |
25 | /////////////////////////////////////////////////////////////////////////// | |
26 | namespace detail | |
27 | { | |
28 | ||
29 | // special handling of actions returning a future | |
30 | template <typename Result, typename RemoteResult, typename Future> | |
31 | void deferred_trigger(std::false_type, | |
32 | typed_continuation<Result, RemoteResult>&& cont, Future&& result) | |
33 | { | |
34 | try { | |
35 | HPX_ASSERT(result.is_ready()); | |
36 | cont.trigger_value(hpx::util::detail::decay_copy(result.get())); | |
37 | } | |
38 | catch (...) { | |
39 | // make sure hpx::exceptions are propagated back to the client | |
40 | cont.trigger_error(boost::current_exception()); | |
41 | } | |
42 | } | |
43 | ||
44 | template <typename Result, typename RemoteResult, typename Future> | |
45 | void deferred_trigger(std::true_type, | |
46 | typed_continuation<Result, RemoteResult>&& cont, Future&& result) | |
47 | { | |
48 | try { | |
49 | HPX_ASSERT(result.is_ready()); | |
50 | result.get(); // rethrow exceptions | |
51 | cont.trigger(); | |
52 | } | |
53 | catch (...) { | |
54 | // make sure hpx::exceptions are propagated back to the client | |
55 | cont.trigger_error(boost::current_exception()); | |
56 | } | |
57 | } | |
58 | ||
59 | template <typename Result, typename RemoteResult, typename F, typename ...Ts> | |
60 | void trigger_impl_future(std::true_type, | |
61 | typed_continuation<Result, RemoteResult>&& cont, F&& f, Ts&&... vs) | |
62 | { | |
63 | typedef | |
64 | typename std::is_same<RemoteResult, util::unused_type>::type | |
65 | is_void; | |
66 | ||
67 | auto result = util::invoke(std::forward<F>(f), | |
68 | std::forward<Ts>(vs)...); | |
69 | ||
70 | typedef typename hpx::util::decay<decltype(result)>::type future_type; | |
71 | ||
72 | if(result.is_ready()) | |
73 | { | |
74 | detail::deferred_trigger<Result, RemoteResult>( | |
75 | is_void(), std::move(cont), std::move(result)); | |
76 | return; | |
77 | } | |
78 | ||
79 | void (*fun)(is_void, typed_continuation<Result, RemoteResult>&&, | |
80 | future_type&&) | |
81 | = &detail::deferred_trigger<Result, RemoteResult, future_type>; | |
82 | ||
83 | result.then( | |
84 | hpx::util::bind( | |
85 | hpx::util::one_shot(fun) | |
86 | , is_void() | |
87 | , std::move(cont) //-V575 | |
88 | , util::placeholders::_1 | |
89 | ) | |
90 | ); | |
91 | } | |
92 | ||
93 | template <typename Result, typename RemoteResult, typename F, typename ...Ts> | |
94 | void trigger_impl(std::false_type, | |
95 | typed_continuation<Result, RemoteResult>&& cont, F&& f, Ts&&... vs) | |
96 | { | |
97 | try { | |
98 | cont.trigger_value( | |
99 | util::invoke(std::forward<F>(f), std::forward<Ts>(vs)...)); | |
100 | } | |
101 | catch (...) { | |
102 | // make sure hpx::exceptions are propagated back to the client | |
103 | cont.trigger_error(boost::current_exception()); | |
104 | } | |
105 | } | |
106 | ||
107 | // Overload when return type is "void" aka util::unused_type | |
108 | template <typename Result, typename RemoteResult, typename F, typename ...Ts> | |
109 | void trigger_impl(std::true_type, typed_continuation<Result, RemoteResult>&& cont, | |
110 | F&& f, Ts&&... vs) | |
111 | { | |
112 | try { | |
113 | util::invoke(std::forward<F>(f), std::forward<Ts>(vs)...); | |
114 | cont.trigger(); | |
115 | } | |
116 | catch (...) { | |
117 | // make sure hpx::exceptions are propagated back to the client | |
118 | cont.trigger_error(boost::current_exception()); | |
119 | } | |
120 | } | |
121 | ||
122 | template <typename Result, typename RemoteResult, typename F, typename ...Ts> | |
123 | void trigger_impl_future(std::false_type, | |
124 | typed_continuation<Result, RemoteResult>&& cont, F&& f, Ts&&... vs) | |
125 | { | |
126 | typename std::is_same<RemoteResult, util::unused_type>::type is_void; | |
127 | ||
128 | trigger_impl(is_void, std::move(cont), std::forward<F>(f), | |
129 | std::forward<Ts>(vs)...); | |
130 | } | |
131 | } | |
132 | ||
133 | template <typename Result, typename RemoteResult, typename F, typename ...Ts> | |
134 | void trigger(typed_continuation<Result, RemoteResult>&& cont, | |
135 | F&& f, Ts&&... vs) | |
136 | { | |
137 | typedef typename util::result_of<F(Ts...)>::type result_type; | |
138 | traits::is_future<result_type> is_future; | |
139 | ||
140 | detail::trigger_impl_future(is_future, std::move(cont), | |
141 | std::forward<F>(f), std::forward<Ts>(vs)...); | |
142 | } | |
143 | }} | |
144 | ||
145 | #endif | |
146 |
Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.