@@ -47,10 +47,10 @@ namespace hpx { namespace lcos { namespace detail
47
47
};
48
48
49
49
// /////////////////////////////////////////////////////////////////////////
50
- static bool run_on_completed_on_new_thread (
51
- util::unique_function_nonser< bool ()> && f, error_code& ec )
50
+ template < typename Callback>
51
+ static void run_on_completed_on_new_thread (Callback && f)
52
52
{
53
- lcos::local::futures_factory<bool ()> p (std::move (f));
53
+ lcos::local::futures_factory<void ()> p (std::forward<Callback> (f));
54
54
55
55
bool is_hpx_thread = nullptr != hpx::threads::get_self_ptr ();
56
56
hpx::launch policy = launch::fork ;
@@ -61,25 +61,17 @@ namespace hpx { namespace lcos { namespace detail
61
61
threads::thread_id_type tid = p.apply (
62
62
policy, threads::thread_priority_boost,
63
63
threads::thread_stacksize_current,
64
- threads::thread_schedule_hint (),
65
- ec);
66
- if (ec) return false ;
64
+ threads::thread_schedule_hint ());
67
65
68
66
// wait for the task to run
69
67
if (is_hpx_thread)
70
68
{
71
69
// make sure this thread is executed last
72
70
hpx::this_thread::yield_to (thread::id (std::move (tid)));
73
- return p.get_future ().get (ec);
74
- }
75
- else
76
- {
77
- // If we are not on a HPX thread, we need to return immediately, to
78
- // allow the newly spawned thread to execute. This might swallow
79
- // possible exceptions bubbling up from the completion handler (which
80
- // shouldn't happen anyway...
81
- return true ;
71
+ return p.get_future ().get ();
82
72
}
73
+ // If we are not on a HPX thread, we need to return immediately, to
74
+ // allow the newly spawned thread to execute.
83
75
}
84
76
85
77
// /////////////////////////////////////////////////////////////////////////
@@ -146,37 +138,27 @@ namespace hpx { namespace lcos { namespace detail
146
138
}
147
139
148
140
// deferred execution of a given continuation
149
- bool future_data_base<traits::detail::future_data_void>::
150
- run_on_completed (completed_callback_type && on_completed,
151
- std::exception_ptr& ptr)
141
+ void future_data_base<traits::detail::future_data_void>::run_on_completed(
142
+ completed_callback_type&& on_completed) noexcept
152
143
{
153
144
try {
154
145
hpx::util::annotate_function annotate (on_completed);
155
146
on_completed ();
156
147
}
157
148
catch (...) {
158
- ptr = std::current_exception ();
159
- return false ;
149
+ // If the completion handler throws an exception, there's nothing
150
+ // we can do, report the exception and terminate.
151
+ hpx::detail::report_exception_and_terminate (std::current_exception ());
160
152
}
161
- return true ;
162
153
}
163
154
164
- bool future_data_base<traits::detail::future_data_void>::
165
- run_on_completed (completed_callback_vector_type && on_completed,
166
- std::exception_ptr& ptr)
155
+ void future_data_base<traits::detail::future_data_void>::run_on_completed(
156
+ completed_callback_vector_type&& on_completed) noexcept
167
157
{
168
- try {
169
- for (auto & func: on_completed)
170
- {
171
- hpx::util::annotate_function annotate (func);
172
- func ();
173
- }
174
- }
175
- catch (...) {
176
- ptr = std::current_exception ();
177
- return false ;
158
+ for (auto && func: on_completed)
159
+ {
160
+ run_on_completed (std::move (func));
178
161
}
179
- return true ;
180
162
}
181
163
182
164
// make sure continuation invocation does not recurse deeper than
@@ -199,37 +181,25 @@ namespace hpx { namespace lcos { namespace detail
199
181
if (!recurse_asynchronously)
200
182
{
201
183
// directly execute continuation on this thread
202
- std::exception_ptr ptr;
203
- if (!run_on_completed (std::forward<Callback>(on_completed), ptr))
204
- {
205
- error_code ec (lightweight);
206
- set_exception (hpx::detail::access_exception (ec));
207
- }
184
+ run_on_completed (std::forward<Callback>(on_completed));
208
185
}
209
186
else
210
187
{
211
188
// re-spawn continuation on a new thread
212
- boost::intrusive_ptr<future_data_base> this_ ( this ) ;
189
+ void (*p)(Callback &&) = &future_data_base::run_on_completed ;
213
190
214
- bool (future_data_base::*p)(Callback&&, std::exception_ptr&) =
215
- &future_data_base::run_on_completed;
216
-
217
- error_code ec (lightweight);
218
- std::exception_ptr ptr;
219
- if (!run_on_completed_on_new_thread (
220
- util::deferred_call (p, std::move (this_),
221
- std::forward<Callback>(on_completed), std::ref (ptr)),
222
- ec))
191
+ try
192
+ {
193
+ run_on_completed_on_new_thread (
194
+ util::deferred_call (
195
+ p, std::forward<Callback>(on_completed)));
196
+ }
197
+ catch (...)
223
198
{
224
- // thread creation went wrong
225
- if (ec) {
226
- set_exception (hpx::detail::access_exception (ec));
227
- return ;
228
- }
229
-
230
- // re-throw exception in this context
231
- HPX_ASSERT (ptr); // exception should have been set
232
- std::rethrow_exception (ptr);
199
+ // If an exception while creating the new task or inside the
200
+ // completion handler is thrown, there is nothing we can do...
201
+ // ... but terminate and report the error
202
+ hpx::detail::report_exception_and_terminate (std::current_exception ());
233
203
}
234
204
}
235
205
}
0 commit comments