Chris@16
|
1 // (C) Copyright 2008-10 Anthony Williams
|
Chris@101
|
2 // (C) Copyright 2011-2015 Vicente J. Botet Escriba
|
Chris@16
|
3 //
|
Chris@16
|
4 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
5 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7
|
Chris@16
|
8 #ifndef BOOST_THREAD_FUTURE_HPP
|
Chris@16
|
9 #define BOOST_THREAD_FUTURE_HPP
|
Chris@16
|
10
|
Chris@16
|
11 #include <boost/thread/detail/config.hpp>
|
Chris@16
|
12
|
Chris@16
|
13 // boost::thread::future requires exception handling
|
Chris@16
|
14 // due to boost::exception::exception_ptr dependency
|
Chris@16
|
15
|
Chris@16
|
16 #ifndef BOOST_NO_EXCEPTIONS
|
Chris@16
|
17
|
Chris@101
|
18 #include <boost/thread/condition_variable.hpp>
|
Chris@16
|
19 #include <boost/thread/detail/move.hpp>
|
Chris@101
|
20 #include <boost/thread/detail/invoker.hpp>
|
Chris@101
|
21 #include <boost/thread/detail/invoke.hpp>
|
Chris@101
|
22 #include <boost/thread/detail/is_convertible.hpp>
|
Chris@101
|
23 #include <boost/thread/exceptional_ptr.hpp>
|
Chris@101
|
24 #include <boost/thread/futures/future_error.hpp>
|
Chris@101
|
25 #include <boost/thread/futures/future_error_code.hpp>
|
Chris@101
|
26 #include <boost/thread/futures/future_status.hpp>
|
Chris@101
|
27 #include <boost/thread/futures/is_future_type.hpp>
|
Chris@101
|
28 #include <boost/thread/futures/launch.hpp>
|
Chris@101
|
29 #include <boost/thread/futures/wait_for_all.hpp>
|
Chris@101
|
30 #include <boost/thread/futures/wait_for_any.hpp>
|
Chris@16
|
31 #include <boost/thread/lock_algorithms.hpp>
|
Chris@16
|
32 #include <boost/thread/lock_types.hpp>
|
Chris@101
|
33 #include <boost/thread/mutex.hpp>
|
Chris@101
|
34 #include <boost/thread/thread_only.hpp>
|
Chris@101
|
35 #include <boost/thread/thread_time.hpp>
|
Chris@101
|
36
|
Chris@101
|
37 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
Chris@101
|
38 #include <boost/optional.hpp>
|
Chris@101
|
39 #else
|
Chris@101
|
40 #include <boost/thread/csbl/memory/unique_ptr.hpp>
|
Chris@101
|
41 #endif
|
Chris@101
|
42
|
Chris@101
|
43 #include <boost/assert.hpp>
|
Chris@16
|
44 #include <boost/bind.hpp>
|
Chris@16
|
45 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
46 #include <boost/chrono/system_clocks.hpp>
|
Chris@16
|
47 #endif
|
Chris@101
|
48 #include <boost/core/enable_if.hpp>
|
Chris@101
|
49 #include <boost/core/ref.hpp>
|
Chris@101
|
50 #include <boost/enable_shared_from_this.hpp>
|
Chris@101
|
51 #include <boost/exception_ptr.hpp>
|
Chris@101
|
52 #include <boost/function.hpp>
|
Chris@101
|
53 #include <boost/next_prior.hpp>
|
Chris@101
|
54 #include <boost/scoped_array.hpp>
|
Chris@101
|
55 #include <boost/shared_ptr.hpp>
|
Chris@101
|
56 #include <boost/throw_exception.hpp>
|
Chris@101
|
57 #include <boost/type_traits/conditional.hpp>
|
Chris@101
|
58 #include <boost/type_traits/decay.hpp>
|
Chris@101
|
59 #include <boost/type_traits/is_copy_constructible.hpp>
|
Chris@101
|
60 #include <boost/type_traits/is_fundamental.hpp>
|
Chris@101
|
61 #include <boost/type_traits/is_void.hpp>
|
Chris@101
|
62 #include <boost/utility/result_of.hpp>
|
Chris@101
|
63
|
Chris@16
|
64
|
Chris@16
|
65 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
66 #include <boost/thread/detail/memory.hpp>
|
Chris@101
|
67 #include <boost/container/scoped_allocator.hpp>
|
Chris@101
|
68 #if ! defined BOOST_NO_CXX11_ALLOCATOR
|
Chris@101
|
69 #include <memory>
|
Chris@16
|
70 #endif
|
Chris@101
|
71 #endif
|
Chris@101
|
72
|
Chris@101
|
73 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
Chris@101
|
74 #include <boost/thread/csbl/tuple.hpp>
|
Chris@101
|
75 #include <boost/thread/csbl/vector.hpp>
|
Chris@101
|
76 #endif
|
Chris@101
|
77
|
Chris@101
|
78 #include <algorithm>
|
Chris@101
|
79 #include <list>
|
Chris@101
|
80 #include <vector>
|
Chris@101
|
81 #include <utility>
|
Chris@16
|
82
|
Chris@16
|
83 #if defined BOOST_THREAD_PROVIDES_FUTURE
|
Chris@16
|
84 #define BOOST_THREAD_FUTURE future
|
Chris@16
|
85 #else
|
Chris@16
|
86 #define BOOST_THREAD_FUTURE unique_future
|
Chris@16
|
87 #endif
|
Chris@16
|
88
|
Chris@16
|
89 namespace boost
|
Chris@16
|
90 {
|
Chris@16
|
91 namespace detail
|
Chris@16
|
92 {
|
Chris@16
|
93 struct relocker
|
Chris@16
|
94 {
|
Chris@16
|
95 boost::unique_lock<boost::mutex>& lock_;
|
Chris@16
|
96
|
Chris@16
|
97 relocker(boost::unique_lock<boost::mutex>& lk):
|
Chris@16
|
98 lock_(lk)
|
Chris@16
|
99 {
|
Chris@16
|
100 lock_.unlock();
|
Chris@16
|
101 }
|
Chris@16
|
102 ~relocker()
|
Chris@16
|
103 {
|
Chris@101
|
104 if (! lock_.owns_lock()) {
|
Chris@16
|
105 lock_.lock();
|
Chris@16
|
106 }
|
Chris@16
|
107 }
|
Chris@16
|
108 void lock() {
|
Chris@101
|
109 if (! lock_.owns_lock()) {
|
Chris@16
|
110 lock_.lock();
|
Chris@16
|
111 }
|
Chris@16
|
112 }
|
Chris@16
|
113 private:
|
Chris@16
|
114 relocker& operator=(relocker const&);
|
Chris@16
|
115 };
|
Chris@16
|
116
|
Chris@16
|
117 struct shared_state_base : enable_shared_from_this<shared_state_base>
|
Chris@16
|
118 {
|
Chris@16
|
119 typedef std::list<boost::condition_variable_any*> waiter_list;
|
Chris@101
|
120 typedef waiter_list::iterator notify_when_ready_handle;
|
Chris@16
|
121 // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
|
Chris@16
|
122 typedef shared_ptr<shared_state_base> continuation_ptr_type;
|
Chris@101
|
123 typedef std::vector<continuation_ptr_type> continuations_type;
|
Chris@16
|
124
|
Chris@16
|
125 boost::exception_ptr exception;
|
Chris@16
|
126 bool done;
|
Chris@101
|
127 bool is_valid_;
|
Chris@16
|
128 bool is_deferred_;
|
Chris@101
|
129 bool is_constructed;
|
Chris@101
|
130 std::size_t cnt_;
|
Chris@16
|
131 launch policy_;
|
Chris@16
|
132 mutable boost::mutex mutex;
|
Chris@16
|
133 boost::condition_variable waiters;
|
Chris@16
|
134 waiter_list external_waiters;
|
Chris@16
|
135 boost::function<void()> callback;
|
Chris@16
|
136 // This declaration should be only included conditionally, but is included to maintain the same layout.
|
Chris@101
|
137 continuations_type continuations;
|
Chris@16
|
138
|
Chris@16
|
139 // This declaration should be only included conditionally, but is included to maintain the same layout.
|
Chris@101
|
140 virtual void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base>)
|
Chris@16
|
141 {
|
Chris@16
|
142 }
|
Chris@16
|
143
|
Chris@16
|
144 shared_state_base():
|
Chris@16
|
145 done(false),
|
Chris@101
|
146 is_valid_(true),
|
Chris@16
|
147 is_deferred_(false),
|
Chris@101
|
148 is_constructed(false),
|
Chris@101
|
149 cnt_(0),
|
Chris@16
|
150 policy_(launch::none),
|
Chris@101
|
151 continuations()
|
Chris@16
|
152 {}
|
Chris@16
|
153 virtual ~shared_state_base()
|
Chris@101
|
154 {
|
Chris@101
|
155 BOOST_ASSERT(cnt_==0);
|
Chris@101
|
156 }
|
Chris@101
|
157 virtual void block_if_needed(boost::unique_lock<boost::mutex>&)
|
Chris@16
|
158 {}
|
Chris@16
|
159
|
Chris@101
|
160 bool valid(boost::unique_lock<boost::mutex>&) { return is_valid_; }
|
Chris@101
|
161 bool valid() {
|
Chris@101
|
162 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@101
|
163 return valid(lk);
|
Chris@101
|
164 }
|
Chris@101
|
165 void invalidate(boost::unique_lock<boost::mutex>&) { is_valid_ = false; }
|
Chris@101
|
166 void invalidate() {
|
Chris@101
|
167 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@101
|
168 invalidate(lk);
|
Chris@101
|
169 }
|
Chris@101
|
170 void validate(boost::unique_lock<boost::mutex>&) { is_valid_ = true; }
|
Chris@101
|
171 void validate() {
|
Chris@101
|
172 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@101
|
173 validate(lk);
|
Chris@101
|
174 }
|
Chris@101
|
175
|
Chris@101
|
176 void inc(boost::unique_lock<boost::mutex>&) { ++cnt_; }
|
Chris@101
|
177 void inc() { boost::unique_lock<boost::mutex> lk(this->mutex); inc(lk); }
|
Chris@101
|
178
|
Chris@101
|
179 void dec(boost::unique_lock<boost::mutex>& lk) {
|
Chris@101
|
180 if (--cnt_ == 0) {
|
Chris@101
|
181 block_if_needed(lk);
|
Chris@101
|
182 }
|
Chris@101
|
183 }
|
Chris@101
|
184 void dec() { boost::unique_lock<boost::mutex> lk(this->mutex); dec(lk); }
|
Chris@101
|
185
|
Chris@16
|
186 void set_deferred()
|
Chris@16
|
187 {
|
Chris@16
|
188 is_deferred_ = true;
|
Chris@16
|
189 policy_ = launch::deferred;
|
Chris@16
|
190 }
|
Chris@16
|
191 void set_async()
|
Chris@16
|
192 {
|
Chris@16
|
193 is_deferred_ = false;
|
Chris@16
|
194 policy_ = launch::async;
|
Chris@16
|
195 }
|
Chris@101
|
196 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
197 void set_executor()
|
Chris@16
|
198 {
|
Chris@101
|
199 is_deferred_ = false;
|
Chris@101
|
200 policy_ = launch::executor;
|
Chris@101
|
201 }
|
Chris@101
|
202 #endif
|
Chris@101
|
203 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
|
Chris@101
|
204 {
|
Chris@101
|
205 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
206 do_callback(lock);
|
Chris@16
|
207 return external_waiters.insert(external_waiters.end(),&cv);
|
Chris@16
|
208 }
|
Chris@16
|
209
|
Chris@101
|
210 void unnotify_when_ready(notify_when_ready_handle it)
|
Chris@16
|
211 {
|
Chris@101
|
212 boost::lock_guard<boost::mutex> lock(this->mutex);
|
Chris@16
|
213 external_waiters.erase(it);
|
Chris@16
|
214 }
|
Chris@16
|
215
|
Chris@16
|
216 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
217 void do_continuation(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
218 {
|
Chris@101
|
219 if (! continuations.empty()) {
|
Chris@101
|
220 continuations_type the_continuations = continuations;
|
Chris@101
|
221 continuations.clear();
|
Chris@101
|
222 relocker rlk(lock);
|
Chris@101
|
223 for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) {
|
Chris@101
|
224 boost::unique_lock<boost::mutex> cont_lock((*it)->mutex);
|
Chris@101
|
225 (*it)->launch_continuation(cont_lock, *it);
|
Chris@101
|
226 }
|
Chris@16
|
227 }
|
Chris@16
|
228 }
|
Chris@16
|
229 #else
|
Chris@16
|
230 void do_continuation(boost::unique_lock<boost::mutex>&)
|
Chris@16
|
231 {
|
Chris@16
|
232 }
|
Chris@16
|
233 #endif
|
Chris@16
|
234 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@101
|
235 virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
236 {
|
Chris@101
|
237 continuations.push_back(continuation);
|
Chris@16
|
238 if (done) {
|
Chris@16
|
239 do_continuation(lock);
|
Chris@16
|
240 }
|
Chris@16
|
241 }
|
Chris@16
|
242 #endif
|
Chris@16
|
243 void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
244 {
|
Chris@16
|
245 done=true;
|
Chris@16
|
246 waiters.notify_all();
|
Chris@16
|
247 for(waiter_list::const_iterator it=external_waiters.begin(),
|
Chris@16
|
248 end=external_waiters.end();it!=end;++it)
|
Chris@16
|
249 {
|
Chris@16
|
250 (*it)->notify_all();
|
Chris@16
|
251 }
|
Chris@16
|
252 do_continuation(lock);
|
Chris@16
|
253 }
|
Chris@16
|
254 void make_ready()
|
Chris@16
|
255 {
|
Chris@101
|
256 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
257 mark_finished_internal(lock);
|
Chris@16
|
258 }
|
Chris@16
|
259
|
Chris@16
|
260 void do_callback(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
261 {
|
Chris@16
|
262 if(callback && !done)
|
Chris@16
|
263 {
|
Chris@16
|
264 boost::function<void()> local_callback=callback;
|
Chris@16
|
265 relocker relock(lock);
|
Chris@16
|
266 local_callback();
|
Chris@16
|
267 }
|
Chris@16
|
268 }
|
Chris@16
|
269
|
Chris@101
|
270 virtual bool run_if_is_deferred()
|
Chris@101
|
271 {
|
Chris@101
|
272 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@101
|
273 if (is_deferred_)
|
Chris@101
|
274 {
|
Chris@101
|
275 is_deferred_=false;
|
Chris@101
|
276 execute(lk);
|
Chris@101
|
277 return true;
|
Chris@101
|
278 }
|
Chris@101
|
279 else
|
Chris@101
|
280 return false;
|
Chris@101
|
281 }
|
Chris@101
|
282 virtual bool run_if_is_deferred_or_ready()
|
Chris@101
|
283 {
|
Chris@101
|
284 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@101
|
285 if (is_deferred_)
|
Chris@101
|
286 {
|
Chris@101
|
287 is_deferred_=false;
|
Chris@101
|
288 execute(lk);
|
Chris@101
|
289
|
Chris@101
|
290 return true;
|
Chris@101
|
291 }
|
Chris@101
|
292 else
|
Chris@101
|
293 return done;
|
Chris@101
|
294 }
|
Chris@16
|
295 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true)
|
Chris@16
|
296 {
|
Chris@16
|
297 do_callback(lk);
|
Chris@101
|
298 if (is_deferred_)
|
Chris@16
|
299 {
|
Chris@101
|
300 is_deferred_=false;
|
Chris@101
|
301 execute(lk);
|
Chris@101
|
302 }
|
Chris@101
|
303 while(!done)
|
Chris@101
|
304 {
|
Chris@101
|
305 waiters.wait(lk);
|
Chris@101
|
306 }
|
Chris@101
|
307 if(rethrow && exception)
|
Chris@101
|
308 {
|
Chris@101
|
309 boost::rethrow_exception(exception);
|
Chris@16
|
310 }
|
Chris@16
|
311 }
|
Chris@16
|
312
|
Chris@101
|
313 virtual void wait(boost::unique_lock<boost::mutex>& lock, bool rethrow=true)
|
Chris@16
|
314 {
|
Chris@16
|
315 wait_internal(lock, rethrow);
|
Chris@16
|
316 }
|
Chris@16
|
317
|
Chris@101
|
318 void wait(bool rethrow=true)
|
Chris@101
|
319 {
|
Chris@101
|
320 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@101
|
321 wait(lock, rethrow);
|
Chris@101
|
322 }
|
Chris@101
|
323
|
Chris@16
|
324 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
325 bool timed_wait_until(boost::system_time const& target_time)
|
Chris@16
|
326 {
|
Chris@101
|
327 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
328 if (is_deferred_)
|
Chris@16
|
329 return false;
|
Chris@16
|
330
|
Chris@16
|
331 do_callback(lock);
|
Chris@16
|
332 while(!done)
|
Chris@16
|
333 {
|
Chris@16
|
334 bool const success=waiters.timed_wait(lock,target_time);
|
Chris@16
|
335 if(!success && !done)
|
Chris@16
|
336 {
|
Chris@16
|
337 return false;
|
Chris@16
|
338 }
|
Chris@16
|
339 }
|
Chris@16
|
340 return true;
|
Chris@16
|
341 }
|
Chris@16
|
342 #endif
|
Chris@16
|
343 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
344
|
Chris@16
|
345 template <class Clock, class Duration>
|
Chris@16
|
346 future_status
|
Chris@16
|
347 wait_until(const chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
348 {
|
Chris@101
|
349 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
350 if (is_deferred_)
|
Chris@16
|
351 return future_status::deferred;
|
Chris@16
|
352 do_callback(lock);
|
Chris@16
|
353 while(!done)
|
Chris@16
|
354 {
|
Chris@16
|
355 cv_status const st=waiters.wait_until(lock,abs_time);
|
Chris@16
|
356 if(st==cv_status::timeout && !done)
|
Chris@16
|
357 {
|
Chris@16
|
358 return future_status::timeout;
|
Chris@16
|
359 }
|
Chris@16
|
360 }
|
Chris@16
|
361 return future_status::ready;
|
Chris@16
|
362 }
|
Chris@16
|
363 #endif
|
Chris@16
|
364 void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
365 {
|
Chris@16
|
366 exception=e;
|
Chris@16
|
367 mark_finished_internal(lock);
|
Chris@16
|
368 }
|
Chris@16
|
369
|
Chris@16
|
370 void mark_exceptional_finish()
|
Chris@16
|
371 {
|
Chris@101
|
372 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
373 mark_exceptional_finish_internal(boost::current_exception(), lock);
|
Chris@16
|
374 }
|
Chris@16
|
375
|
Chris@16
|
376 void set_exception_at_thread_exit(exception_ptr e)
|
Chris@16
|
377 {
|
Chris@101
|
378 unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
379 if (has_value(lk))
|
Chris@16
|
380 {
|
Chris@16
|
381 throw_exception(promise_already_satisfied());
|
Chris@16
|
382 }
|
Chris@16
|
383 exception=e;
|
Chris@16
|
384 this->is_constructed = true;
|
Chris@16
|
385 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
386 }
|
Chris@16
|
387
|
Chris@16
|
388 bool has_value() const
|
Chris@16
|
389 {
|
Chris@101
|
390 boost::lock_guard<boost::mutex> lock(this->mutex);
|
Chris@101
|
391 return done && ! exception;
|
Chris@16
|
392 }
|
Chris@16
|
393
|
Chris@16
|
394 bool has_value(unique_lock<boost::mutex>& ) const
|
Chris@16
|
395 {
|
Chris@101
|
396 return done && ! exception;
|
Chris@16
|
397 }
|
Chris@16
|
398
|
Chris@16
|
399 bool has_exception() const
|
Chris@16
|
400 {
|
Chris@101
|
401 boost::lock_guard<boost::mutex> lock(this->mutex);
|
Chris@101
|
402 return done && exception;
|
Chris@16
|
403 }
|
Chris@16
|
404
|
Chris@16
|
405 launch launch_policy(boost::unique_lock<boost::mutex>&) const
|
Chris@16
|
406 {
|
Chris@16
|
407 return policy_;
|
Chris@16
|
408 }
|
Chris@16
|
409
|
Chris@101
|
410 future_state::state get_state(boost::unique_lock<boost::mutex>& lk) const
|
Chris@16
|
411 {
|
Chris@16
|
412 if(!done)
|
Chris@16
|
413 {
|
Chris@16
|
414 return future_state::waiting;
|
Chris@16
|
415 }
|
Chris@16
|
416 else
|
Chris@16
|
417 {
|
Chris@16
|
418 return future_state::ready;
|
Chris@16
|
419 }
|
Chris@16
|
420 }
|
Chris@101
|
421 future_state::state get_state() const
|
Chris@101
|
422 {
|
Chris@101
|
423 boost::lock_guard<boost::mutex> guard(this->mutex);
|
Chris@101
|
424 if(!done)
|
Chris@101
|
425 {
|
Chris@101
|
426 return future_state::waiting;
|
Chris@101
|
427 }
|
Chris@101
|
428 else
|
Chris@101
|
429 {
|
Chris@101
|
430 return future_state::ready;
|
Chris@101
|
431 }
|
Chris@101
|
432 }
|
Chris@16
|
433
|
Chris@16
|
434 exception_ptr get_exception_ptr()
|
Chris@16
|
435 {
|
Chris@101
|
436 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
437 wait_internal(lock, false);
|
Chris@16
|
438 return exception;
|
Chris@16
|
439 }
|
Chris@16
|
440
|
Chris@16
|
441 template<typename F,typename U>
|
Chris@16
|
442 void set_wait_callback(F f,U* u)
|
Chris@16
|
443 {
|
Chris@101
|
444 boost::lock_guard<boost::mutex> lock(this->mutex);
|
Chris@16
|
445 callback=boost::bind(f,boost::ref(*u));
|
Chris@16
|
446 }
|
Chris@16
|
447
|
Chris@16
|
448 virtual void execute(boost::unique_lock<boost::mutex>&) {}
|
Chris@16
|
449
|
Chris@16
|
450 private:
|
Chris@16
|
451 shared_state_base(shared_state_base const&);
|
Chris@16
|
452 shared_state_base& operator=(shared_state_base const&);
|
Chris@16
|
453 };
|
Chris@16
|
454
|
Chris@16
|
455 // Used to create stand-alone futures
|
Chris@16
|
456 template<typename T>
|
Chris@16
|
457 struct shared_state:
|
Chris@16
|
458 detail::shared_state_base
|
Chris@16
|
459 {
|
Chris@101
|
460 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
Chris@101
|
461 typedef boost::optional<T> storage_type;
|
Chris@101
|
462 #else
|
Chris@101
|
463 typedef boost::csbl::unique_ptr<T> storage_type;
|
Chris@101
|
464 #endif
|
Chris@101
|
465 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
466 typedef T const& source_reference_type;
|
Chris@101
|
467 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
|
Chris@101
|
468 typedef T move_dest_type;
|
Chris@101
|
469 #elif defined BOOST_THREAD_USES_MOVE
|
Chris@101
|
470 typedef typename conditional<boost::is_fundamental<T>::value,T,T const&>::type source_reference_type;
|
Chris@101
|
471 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
|
Chris@101
|
472 typedef T move_dest_type;
|
Chris@101
|
473 #else
|
Chris@101
|
474 typedef T& source_reference_type;
|
Chris@101
|
475 typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
|
Chris@101
|
476 typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
|
Chris@101
|
477 #endif
|
Chris@101
|
478
|
Chris@101
|
479 typedef const T& shared_future_get_result_type;
|
Chris@16
|
480
|
Chris@16
|
481 storage_type result;
|
Chris@16
|
482
|
Chris@16
|
483 shared_state():
|
Chris@101
|
484 result()
|
Chris@16
|
485 {}
|
Chris@16
|
486
|
Chris@16
|
487 ~shared_state()
|
Chris@16
|
488 {}
|
Chris@16
|
489
|
Chris@16
|
490 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
491 {
|
Chris@101
|
492 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
Chris@101
|
493 result = result_;
|
Chris@16
|
494 #else
|
Chris@101
|
495 result.reset(new T(result_));
|
Chris@16
|
496 #endif
|
Chris@16
|
497 this->mark_finished_internal(lock);
|
Chris@16
|
498 }
|
Chris@16
|
499
|
Chris@101
|
500 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
|
Chris@101
|
501 {
|
Chris@101
|
502 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
Chris@101
|
503 result = boost::move(result_);
|
Chris@101
|
504 #elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
505 result.reset(new T(boost::move(result_)));
|
Chris@101
|
506 #else
|
Chris@101
|
507 result.reset(new T(static_cast<rvalue_source_type>(result_)));
|
Chris@101
|
508 #endif
|
Chris@101
|
509 this->mark_finished_internal(lock);
|
Chris@101
|
510 }
|
Chris@101
|
511
|
Chris@101
|
512
|
Chris@101
|
513 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
514 template <class ...Args>
|
Chris@101
|
515 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock, BOOST_THREAD_FWD_REF(Args)... args)
|
Chris@101
|
516 {
|
Chris@101
|
517 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
Chris@101
|
518 result.emplace(boost::forward<Args>(args)...);
|
Chris@101
|
519 #else
|
Chris@101
|
520 result.reset(new T(boost::forward<Args>(args)...));
|
Chris@101
|
521 #endif
|
Chris@101
|
522 this->mark_finished_internal(lock);
|
Chris@101
|
523 }
|
Chris@101
|
524 #endif
|
Chris@101
|
525
|
Chris@16
|
526 void mark_finished_with_result(source_reference_type result_)
|
Chris@16
|
527 {
|
Chris@101
|
528 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
529 this->mark_finished_with_result_internal(result_, lock);
|
Chris@16
|
530 }
|
Chris@16
|
531
|
Chris@16
|
532 void mark_finished_with_result(rvalue_source_type result_)
|
Chris@16
|
533 {
|
Chris@101
|
534 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
535
|
Chris@16
|
536 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
537 mark_finished_with_result_internal(boost::move(result_), lock);
|
Chris@16
|
538 #else
|
Chris@16
|
539 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
|
Chris@16
|
540 #endif
|
Chris@16
|
541 }
|
Chris@16
|
542
|
Chris@101
|
543 storage_type& get_storage(boost::unique_lock<boost::mutex>& lk)
|
Chris@16
|
544 {
|
Chris@101
|
545 wait_internal(lk);
|
Chris@101
|
546 return result;
|
Chris@16
|
547 }
|
Chris@101
|
548 virtual move_dest_type get(boost::unique_lock<boost::mutex>& lk)
|
Chris@16
|
549 {
|
Chris@101
|
550 return boost::move(*get_storage(lk));
|
Chris@16
|
551 }
|
Chris@101
|
552 move_dest_type get()
|
Chris@101
|
553 {
|
Chris@101
|
554 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@101
|
555 return this->get(lk);
|
Chris@101
|
556 }
|
Chris@101
|
557
|
Chris@101
|
558 virtual shared_future_get_result_type get_sh(boost::unique_lock<boost::mutex>& lk)
|
Chris@101
|
559 {
|
Chris@101
|
560 return *get_storage(lk);
|
Chris@101
|
561 }
|
Chris@101
|
562 shared_future_get_result_type get_sh()
|
Chris@101
|
563 {
|
Chris@101
|
564 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@101
|
565 return this->get_sh(lk);
|
Chris@101
|
566 }
|
Chris@101
|
567
|
Chris@16
|
568 void set_value_at_thread_exit(source_reference_type result_)
|
Chris@16
|
569 {
|
Chris@16
|
570 unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
571 if (this->has_value(lk))
|
Chris@16
|
572 {
|
Chris@16
|
573 throw_exception(promise_already_satisfied());
|
Chris@16
|
574 }
|
Chris@101
|
575 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
Chris@101
|
576 result = result_;
|
Chris@101
|
577 #else
|
Chris@16
|
578 result.reset(new T(result_));
|
Chris@101
|
579 #endif
|
Chris@16
|
580
|
Chris@16
|
581 this->is_constructed = true;
|
Chris@16
|
582 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
583 }
|
Chris@16
|
584 void set_value_at_thread_exit(rvalue_source_type result_)
|
Chris@16
|
585 {
|
Chris@16
|
586 unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
587 if (this->has_value(lk))
|
Chris@16
|
588 throw_exception(promise_already_satisfied());
|
Chris@101
|
589
|
Chris@101
|
590 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
591 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
Chris@101
|
592 result = boost::move(result_);
|
Chris@101
|
593 #else
|
Chris@101
|
594 result.reset(new T(boost::move(result_)));
|
Chris@101
|
595 #endif
|
Chris@101
|
596 #else
|
Chris@101
|
597 #if defined BOOST_THREAD_FUTURE_USES_OPTIONAL
|
Chris@101
|
598 result = boost::move(result_);
|
Chris@101
|
599 #else
|
Chris@101
|
600 result.reset(new T(static_cast<rvalue_source_type>(result_)));
|
Chris@101
|
601 #endif
|
Chris@101
|
602 #endif
|
Chris@16
|
603 this->is_constructed = true;
|
Chris@16
|
604 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
605 }
|
Chris@16
|
606
|
Chris@16
|
607 private:
|
Chris@16
|
608 shared_state(shared_state const&);
|
Chris@16
|
609 shared_state& operator=(shared_state const&);
|
Chris@16
|
610 };
|
Chris@16
|
611
|
Chris@16
|
612 template<typename T>
|
Chris@16
|
613 struct shared_state<T&>:
|
Chris@16
|
614 detail::shared_state_base
|
Chris@16
|
615 {
|
Chris@101
|
616 typedef T* storage_type;
|
Chris@101
|
617 typedef T& source_reference_type;
|
Chris@101
|
618 typedef T& move_dest_type;
|
Chris@101
|
619 typedef T& shared_future_get_result_type;
|
Chris@16
|
620
|
Chris@16
|
621 T* result;
|
Chris@16
|
622
|
Chris@16
|
623 shared_state():
|
Chris@16
|
624 result(0)
|
Chris@16
|
625 {}
|
Chris@16
|
626
|
Chris@16
|
627 ~shared_state()
|
Chris@16
|
628 {
|
Chris@16
|
629 }
|
Chris@16
|
630
|
Chris@16
|
631 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
632 {
|
Chris@16
|
633 result= &result_;
|
Chris@16
|
634 mark_finished_internal(lock);
|
Chris@16
|
635 }
|
Chris@16
|
636
|
Chris@16
|
637 void mark_finished_with_result(source_reference_type result_)
|
Chris@16
|
638 {
|
Chris@101
|
639 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
640 mark_finished_with_result_internal(result_, lock);
|
Chris@16
|
641 }
|
Chris@16
|
642
|
Chris@101
|
643 virtual T& get(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
644 {
|
Chris@101
|
645 wait_internal(lock);
|
Chris@16
|
646 return *result;
|
Chris@16
|
647 }
|
Chris@101
|
648 T& get()
|
Chris@16
|
649 {
|
Chris@101
|
650 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@101
|
651 return get(lk);
|
Chris@101
|
652 }
|
Chris@101
|
653
|
Chris@101
|
654 virtual T& get_sh(boost::unique_lock<boost::mutex>& lock)
|
Chris@101
|
655 {
|
Chris@101
|
656 wait_internal(lock);
|
Chris@16
|
657 return *result;
|
Chris@16
|
658 }
|
Chris@101
|
659 T& get_sh()
|
Chris@101
|
660 {
|
Chris@101
|
661 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@101
|
662 return get_sh(lock);
|
Chris@101
|
663 }
|
Chris@16
|
664
|
Chris@16
|
665 void set_value_at_thread_exit(T& result_)
|
Chris@16
|
666 {
|
Chris@16
|
667 unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
668 if (this->has_value(lk))
|
Chris@16
|
669 throw_exception(promise_already_satisfied());
|
Chris@16
|
670 result= &result_;
|
Chris@16
|
671 this->is_constructed = true;
|
Chris@16
|
672 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
673 }
|
Chris@16
|
674
|
Chris@16
|
675 private:
|
Chris@16
|
676 shared_state(shared_state const&);
|
Chris@16
|
677 shared_state& operator=(shared_state const&);
|
Chris@16
|
678 };
|
Chris@16
|
679
|
Chris@16
|
680 template<>
|
Chris@16
|
681 struct shared_state<void>:
|
Chris@16
|
682 detail::shared_state_base
|
Chris@16
|
683 {
|
Chris@101
|
684 typedef void shared_future_get_result_type;
|
Chris@101
|
685 typedef void move_dest_type;
|
Chris@16
|
686
|
Chris@16
|
687 shared_state()
|
Chris@16
|
688 {}
|
Chris@16
|
689
|
Chris@16
|
690 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
691 {
|
Chris@16
|
692 mark_finished_internal(lock);
|
Chris@16
|
693 }
|
Chris@16
|
694
|
Chris@16
|
695 void mark_finished_with_result()
|
Chris@16
|
696 {
|
Chris@101
|
697 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@16
|
698 mark_finished_with_result_internal(lock);
|
Chris@16
|
699 }
|
Chris@16
|
700
|
Chris@101
|
701 virtual void get(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
702 {
|
Chris@101
|
703 this->wait_internal(lock);
|
Chris@16
|
704 }
|
Chris@101
|
705 void get()
|
Chris@16
|
706 {
|
Chris@101
|
707 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@101
|
708 this->get(lock);
|
Chris@101
|
709 }
|
Chris@101
|
710
|
Chris@101
|
711 virtual void get_sh(boost::unique_lock<boost::mutex>& lock)
|
Chris@101
|
712 {
|
Chris@101
|
713 this->wait_internal(lock);
|
Chris@101
|
714 }
|
Chris@101
|
715 void get_sh()
|
Chris@101
|
716 {
|
Chris@101
|
717 boost::unique_lock<boost::mutex> lock(this->mutex);
|
Chris@101
|
718 this->get_sh(lock);
|
Chris@16
|
719 }
|
Chris@16
|
720
|
Chris@16
|
721 void set_value_at_thread_exit()
|
Chris@16
|
722 {
|
Chris@16
|
723 unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
724 if (this->has_value(lk))
|
Chris@16
|
725 {
|
Chris@16
|
726 throw_exception(promise_already_satisfied());
|
Chris@16
|
727 }
|
Chris@16
|
728 this->is_constructed = true;
|
Chris@16
|
729 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
730 }
|
Chris@16
|
731 private:
|
Chris@16
|
732 shared_state(shared_state const&);
|
Chris@16
|
733 shared_state& operator=(shared_state const&);
|
Chris@16
|
734 };
|
Chris@16
|
735
|
Chris@16
|
736 /////////////////////////
|
Chris@16
|
737 /// future_async_shared_state_base
|
Chris@16
|
738 /////////////////////////
|
Chris@16
|
739 template<typename Rp>
|
Chris@16
|
740 struct future_async_shared_state_base: shared_state<Rp>
|
Chris@16
|
741 {
|
Chris@16
|
742 typedef shared_state<Rp> base_type;
|
Chris@16
|
743 protected:
|
Chris@16
|
744 boost::thread thr_;
|
Chris@16
|
745 void join()
|
Chris@16
|
746 {
|
Chris@16
|
747 if (thr_.joinable()) thr_.join();
|
Chris@16
|
748 }
|
Chris@16
|
749 public:
|
Chris@16
|
750 future_async_shared_state_base()
|
Chris@16
|
751 {
|
Chris@16
|
752 this->set_async();
|
Chris@16
|
753 }
|
Chris@101
|
754
|
Chris@101
|
755 virtual void block_if_needed(boost::unique_lock<boost::mutex>& lk)
|
Chris@16
|
756 {
|
Chris@101
|
757 this->wait(lk, false);
|
Chris@16
|
758 }
|
Chris@16
|
759
|
Chris@16
|
760 ~future_async_shared_state_base()
|
Chris@16
|
761 {
|
Chris@16
|
762 join();
|
Chris@16
|
763 }
|
Chris@16
|
764
|
Chris@101
|
765 virtual void wait(boost::unique_lock<boost::mutex>& lk, bool rethrow)
|
Chris@16
|
766 {
|
Chris@101
|
767 {
|
Chris@101
|
768 relocker rlk(lk);
|
Chris@101
|
769 join();
|
Chris@101
|
770 }
|
Chris@101
|
771 this->base_type::wait(lk, rethrow);
|
Chris@16
|
772 }
|
Chris@16
|
773 };
|
Chris@16
|
774
|
Chris@16
|
775 /////////////////////////
|
Chris@16
|
776 /// future_async_shared_state
|
Chris@16
|
777 /////////////////////////
|
Chris@16
|
778 template<typename Rp, typename Fp>
|
Chris@16
|
779 struct future_async_shared_state: future_async_shared_state_base<Rp>
|
Chris@16
|
780 {
|
Chris@101
|
781 future_async_shared_state()
|
Chris@16
|
782 {
|
Chris@16
|
783 }
|
Chris@16
|
784
|
Chris@101
|
785 void init(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
786 {
|
Chris@101
|
787 shared_ptr<boost::detail::shared_state_base> that = this->shared_from_this();
|
Chris@101
|
788 this->thr_ = thread(&future_async_shared_state::run, that, boost::forward<Fp>(f));
|
Chris@101
|
789 }
|
Chris@101
|
790
|
Chris@101
|
791 static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@101
|
792 {
|
Chris@101
|
793 future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get());
|
Chris@16
|
794 try
|
Chris@16
|
795 {
|
Chris@16
|
796 that->mark_finished_with_result(f());
|
Chris@16
|
797 }
|
Chris@16
|
798 catch(...)
|
Chris@16
|
799 {
|
Chris@16
|
800 that->mark_exceptional_finish();
|
Chris@16
|
801 }
|
Chris@16
|
802 }
|
Chris@16
|
803 };
|
Chris@16
|
804
|
Chris@16
|
805 template<typename Fp>
|
Chris@16
|
806 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void>
|
Chris@16
|
807 {
|
Chris@101
|
808 void init(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
809 {
|
Chris@101
|
810 this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f));
|
Chris@16
|
811 }
|
Chris@16
|
812
|
Chris@101
|
813 static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
814 {
|
Chris@101
|
815 future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get());
|
Chris@16
|
816 try
|
Chris@16
|
817 {
|
Chris@16
|
818 f();
|
Chris@16
|
819 that->mark_finished_with_result();
|
Chris@16
|
820 }
|
Chris@16
|
821 catch(...)
|
Chris@16
|
822 {
|
Chris@16
|
823 that->mark_exceptional_finish();
|
Chris@16
|
824 }
|
Chris@16
|
825 }
|
Chris@16
|
826 };
|
Chris@16
|
827
|
Chris@16
|
828 template<typename Rp, typename Fp>
|
Chris@16
|
829 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&>
|
Chris@16
|
830 {
|
Chris@101
|
831 void init(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
832 {
|
Chris@101
|
833 this->thr_ = thread(&future_async_shared_state::run, this->shared_from_this(), boost::move(f));
|
Chris@16
|
834 }
|
Chris@16
|
835
|
Chris@101
|
836 static void run(shared_ptr<boost::detail::shared_state_base> that_, BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
837 {
|
Chris@101
|
838 future_async_shared_state* that = dynamic_cast<future_async_shared_state*>(that_.get());
|
Chris@16
|
839 try
|
Chris@16
|
840 {
|
Chris@16
|
841 that->mark_finished_with_result(f());
|
Chris@16
|
842 }
|
Chris@16
|
843 catch(...)
|
Chris@16
|
844 {
|
Chris@16
|
845 that->mark_exceptional_finish();
|
Chris@16
|
846 }
|
Chris@16
|
847 }
|
Chris@16
|
848 };
|
Chris@16
|
849
|
Chris@16
|
850 //////////////////////////
|
Chris@16
|
851 /// future_deferred_shared_state
|
Chris@16
|
852 //////////////////////////
|
Chris@16
|
853 template<typename Rp, typename Fp>
|
Chris@16
|
854 struct future_deferred_shared_state: shared_state<Rp>
|
Chris@16
|
855 {
|
Chris@16
|
856 typedef shared_state<Rp> base_type;
|
Chris@16
|
857 Fp func_;
|
Chris@16
|
858
|
Chris@16
|
859 public:
|
Chris@16
|
860 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@101
|
861 : func_(boost::move(f))
|
Chris@16
|
862 {
|
Chris@16
|
863 this->set_deferred();
|
Chris@16
|
864 }
|
Chris@16
|
865
|
Chris@16
|
866 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@16
|
867 try
|
Chris@16
|
868 {
|
Chris@16
|
869 Fp local_fuct=boost::move(func_);
|
Chris@16
|
870 relocker relock(lck);
|
Chris@16
|
871 Rp res = local_fuct();
|
Chris@16
|
872 relock.lock();
|
Chris@16
|
873 this->mark_finished_with_result_internal(boost::move(res), lck);
|
Chris@16
|
874 }
|
Chris@16
|
875 catch (...)
|
Chris@16
|
876 {
|
Chris@16
|
877 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@16
|
878 }
|
Chris@16
|
879 }
|
Chris@16
|
880 };
|
Chris@16
|
881 template<typename Rp, typename Fp>
|
Chris@16
|
882 struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
|
Chris@16
|
883 {
|
Chris@16
|
884 typedef shared_state<Rp&> base_type;
|
Chris@16
|
885 Fp func_;
|
Chris@16
|
886
|
Chris@16
|
887 public:
|
Chris@16
|
888 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@101
|
889 : func_(boost::move(f))
|
Chris@16
|
890 {
|
Chris@16
|
891 this->set_deferred();
|
Chris@16
|
892 }
|
Chris@16
|
893
|
Chris@16
|
894 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@16
|
895 try
|
Chris@16
|
896 {
|
Chris@16
|
897 this->mark_finished_with_result_internal(func_(), lck);
|
Chris@16
|
898 }
|
Chris@16
|
899 catch (...)
|
Chris@16
|
900 {
|
Chris@16
|
901 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@16
|
902 }
|
Chris@16
|
903 }
|
Chris@16
|
904 };
|
Chris@16
|
905
|
Chris@16
|
906 template<typename Fp>
|
Chris@16
|
907 struct future_deferred_shared_state<void,Fp>: shared_state<void>
|
Chris@16
|
908 {
|
Chris@16
|
909 typedef shared_state<void> base_type;
|
Chris@16
|
910 Fp func_;
|
Chris@16
|
911
|
Chris@16
|
912 public:
|
Chris@16
|
913 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@101
|
914 : func_(boost::move(f))
|
Chris@16
|
915 {
|
Chris@16
|
916 this->set_deferred();
|
Chris@16
|
917 }
|
Chris@16
|
918
|
Chris@16
|
919 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@16
|
920 try
|
Chris@16
|
921 {
|
Chris@16
|
922 Fp local_fuct=boost::move(func_);
|
Chris@16
|
923 relocker relock(lck);
|
Chris@16
|
924 local_fuct();
|
Chris@16
|
925 relock.lock();
|
Chris@16
|
926 this->mark_finished_with_result_internal(lck);
|
Chris@16
|
927 }
|
Chris@16
|
928 catch (...)
|
Chris@16
|
929 {
|
Chris@16
|
930 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@16
|
931 }
|
Chris@16
|
932 }
|
Chris@16
|
933 };
|
Chris@16
|
934
|
Chris@16
|
935 class future_waiter
|
Chris@16
|
936 {
|
Chris@16
|
937 struct registered_waiter;
|
Chris@16
|
938 typedef std::vector<int>::size_type count_type;
|
Chris@16
|
939
|
Chris@16
|
940 struct registered_waiter
|
Chris@16
|
941 {
|
Chris@16
|
942 boost::shared_ptr<detail::shared_state_base> future_;
|
Chris@101
|
943 detail::shared_state_base::notify_when_ready_handle handle;
|
Chris@16
|
944 count_type index;
|
Chris@16
|
945
|
Chris@16
|
946 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future,
|
Chris@101
|
947 detail::shared_state_base::notify_when_ready_handle handle_,
|
Chris@16
|
948 count_type index_):
|
Chris@101
|
949 future_(a_future),handle(handle_),index(index_)
|
Chris@16
|
950 {}
|
Chris@16
|
951 };
|
Chris@16
|
952
|
Chris@16
|
953 struct all_futures_lock
|
Chris@16
|
954 {
|
Chris@16
|
955 #ifdef _MANAGED
|
Chris@16
|
956 typedef std::ptrdiff_t count_type_portable;
|
Chris@16
|
957 #else
|
Chris@16
|
958 typedef count_type count_type_portable;
|
Chris@16
|
959 #endif
|
Chris@16
|
960 count_type_portable count;
|
Chris@16
|
961 boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
|
Chris@16
|
962
|
Chris@16
|
963 all_futures_lock(std::vector<registered_waiter>& futures):
|
Chris@16
|
964 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
|
Chris@16
|
965 {
|
Chris@16
|
966 for(count_type_portable i=0;i<count;++i)
|
Chris@16
|
967 {
|
Chris@101
|
968 locks[i]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(futures[i].future_->mutex));
|
Chris@16
|
969 }
|
Chris@16
|
970 }
|
Chris@16
|
971
|
Chris@16
|
972 void lock()
|
Chris@16
|
973 {
|
Chris@16
|
974 boost::lock(locks.get(),locks.get()+count);
|
Chris@16
|
975 }
|
Chris@16
|
976
|
Chris@16
|
977 void unlock()
|
Chris@16
|
978 {
|
Chris@16
|
979 for(count_type_portable i=0;i<count;++i)
|
Chris@16
|
980 {
|
Chris@16
|
981 locks[i].unlock();
|
Chris@16
|
982 }
|
Chris@16
|
983 }
|
Chris@16
|
984 };
|
Chris@16
|
985
|
Chris@16
|
986 boost::condition_variable_any cv;
|
Chris@101
|
987 std::vector<registered_waiter> futures_;
|
Chris@16
|
988 count_type future_count;
|
Chris@16
|
989
|
Chris@16
|
990 public:
|
Chris@16
|
991 future_waiter():
|
Chris@16
|
992 future_count(0)
|
Chris@16
|
993 {}
|
Chris@16
|
994
|
Chris@16
|
995 template<typename F>
|
Chris@16
|
996 void add(F& f)
|
Chris@16
|
997 {
|
Chris@16
|
998 if(f.future_)
|
Chris@16
|
999 {
|
Chris@101
|
1000 registered_waiter waiter(f.future_,f.future_->notify_when_ready(cv),future_count);
|
Chris@101
|
1001 try {
|
Chris@101
|
1002 futures_.push_back(waiter);
|
Chris@101
|
1003 } catch(...) {
|
Chris@101
|
1004 f.future_->unnotify_when_ready(waiter.handle);
|
Chris@101
|
1005 throw;
|
Chris@101
|
1006 }
|
Chris@16
|
1007 }
|
Chris@16
|
1008 ++future_count;
|
Chris@16
|
1009 }
|
Chris@16
|
1010
|
Chris@101
|
1011 #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
Chris@101
|
1012 template<typename F1, typename... Fs>
|
Chris@101
|
1013 void add(F1& f1, Fs&... fs)
|
Chris@101
|
1014 {
|
Chris@101
|
1015 add(f1); add(fs...);
|
Chris@101
|
1016 }
|
Chris@101
|
1017 #endif
|
Chris@101
|
1018
|
Chris@16
|
1019 count_type wait()
|
Chris@16
|
1020 {
|
Chris@101
|
1021 all_futures_lock lk(futures_);
|
Chris@16
|
1022 for(;;)
|
Chris@16
|
1023 {
|
Chris@101
|
1024 for(count_type i=0;i<futures_.size();++i)
|
Chris@16
|
1025 {
|
Chris@101
|
1026 if(futures_[i].future_->done)
|
Chris@16
|
1027 {
|
Chris@101
|
1028 return futures_[i].index;
|
Chris@16
|
1029 }
|
Chris@16
|
1030 }
|
Chris@16
|
1031 cv.wait(lk);
|
Chris@16
|
1032 }
|
Chris@16
|
1033 }
|
Chris@16
|
1034
|
Chris@16
|
1035 ~future_waiter()
|
Chris@16
|
1036 {
|
Chris@101
|
1037 for(count_type i=0;i<futures_.size();++i)
|
Chris@16
|
1038 {
|
Chris@101
|
1039 futures_[i].future_->unnotify_when_ready(futures_[i].handle);
|
Chris@16
|
1040 }
|
Chris@16
|
1041 }
|
Chris@16
|
1042 };
|
Chris@16
|
1043
|
Chris@16
|
1044 }
|
Chris@16
|
1045
|
Chris@16
|
1046 template <typename R>
|
Chris@16
|
1047 class BOOST_THREAD_FUTURE;
|
Chris@16
|
1048
|
Chris@16
|
1049 template <typename R>
|
Chris@16
|
1050 class shared_future;
|
Chris@16
|
1051
|
Chris@16
|
1052 template<typename T>
|
Chris@101
|
1053 struct is_future_type<BOOST_THREAD_FUTURE<T> > : true_type
|
Chris@16
|
1054 {
|
Chris@16
|
1055 };
|
Chris@16
|
1056
|
Chris@16
|
1057 template<typename T>
|
Chris@101
|
1058 struct is_future_type<shared_future<T> > : true_type
|
Chris@16
|
1059 {
|
Chris@16
|
1060 };
|
Chris@16
|
1061
|
Chris@101
|
1062 // template<typename Iterator>
|
Chris@101
|
1063 // typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
|
Chris@101
|
1064 // {
|
Chris@101
|
1065 // if(begin==end)
|
Chris@101
|
1066 // return end;
|
Chris@101
|
1067 //
|
Chris@101
|
1068 // detail::future_waiter waiter;
|
Chris@101
|
1069 // for(Iterator current=begin;current!=end;++current)
|
Chris@101
|
1070 // {
|
Chris@101
|
1071 // waiter.add(*current);
|
Chris@101
|
1072 // }
|
Chris@101
|
1073 // return boost::next(begin,waiter.wait());
|
Chris@101
|
1074 // }
|
Chris@101
|
1075
|
Chris@101
|
1076 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
Chris@16
|
1077 template<typename F1,typename F2>
|
Chris@16
|
1078 typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2)
|
Chris@16
|
1079 {
|
Chris@16
|
1080 detail::future_waiter waiter;
|
Chris@16
|
1081 waiter.add(f1);
|
Chris@16
|
1082 waiter.add(f2);
|
Chris@16
|
1083 return waiter.wait();
|
Chris@16
|
1084 }
|
Chris@16
|
1085
|
Chris@16
|
1086 template<typename F1,typename F2,typename F3>
|
Chris@16
|
1087 unsigned wait_for_any(F1& f1,F2& f2,F3& f3)
|
Chris@16
|
1088 {
|
Chris@16
|
1089 detail::future_waiter waiter;
|
Chris@16
|
1090 waiter.add(f1);
|
Chris@16
|
1091 waiter.add(f2);
|
Chris@16
|
1092 waiter.add(f3);
|
Chris@16
|
1093 return waiter.wait();
|
Chris@16
|
1094 }
|
Chris@16
|
1095
|
Chris@16
|
1096 template<typename F1,typename F2,typename F3,typename F4>
|
Chris@16
|
1097 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
|
Chris@16
|
1098 {
|
Chris@16
|
1099 detail::future_waiter waiter;
|
Chris@16
|
1100 waiter.add(f1);
|
Chris@16
|
1101 waiter.add(f2);
|
Chris@16
|
1102 waiter.add(f3);
|
Chris@16
|
1103 waiter.add(f4);
|
Chris@16
|
1104 return waiter.wait();
|
Chris@16
|
1105 }
|
Chris@16
|
1106
|
Chris@16
|
1107 template<typename F1,typename F2,typename F3,typename F4,typename F5>
|
Chris@16
|
1108 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
|
Chris@16
|
1109 {
|
Chris@16
|
1110 detail::future_waiter waiter;
|
Chris@16
|
1111 waiter.add(f1);
|
Chris@16
|
1112 waiter.add(f2);
|
Chris@16
|
1113 waiter.add(f3);
|
Chris@16
|
1114 waiter.add(f4);
|
Chris@16
|
1115 waiter.add(f5);
|
Chris@16
|
1116 return waiter.wait();
|
Chris@16
|
1117 }
|
Chris@101
|
1118 #else
|
Chris@101
|
1119 template<typename F1, typename... Fs>
|
Chris@101
|
1120 typename boost::enable_if<is_future_type<F1>, unsigned>::type wait_for_any(F1& f1, Fs&... fs)
|
Chris@101
|
1121 {
|
Chris@101
|
1122 detail::future_waiter waiter;
|
Chris@101
|
1123 waiter.add(f1, fs...);
|
Chris@101
|
1124 return waiter.wait();
|
Chris@101
|
1125 }
|
Chris@101
|
1126 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@16
|
1127
|
Chris@16
|
1128 template <typename R>
|
Chris@16
|
1129 class promise;
|
Chris@16
|
1130
|
Chris@16
|
1131 template <typename R>
|
Chris@16
|
1132 class packaged_task;
|
Chris@16
|
1133
|
Chris@16
|
1134 namespace detail
|
Chris@16
|
1135 {
|
Chris@16
|
1136 /// Common implementation for all the futures independently of the return type
|
Chris@16
|
1137 class base_future
|
Chris@16
|
1138 {
|
Chris@101
|
1139 public:
|
Chris@16
|
1140 };
|
Chris@16
|
1141 /// Common implementation for future and shared_future.
|
Chris@16
|
1142 template <typename R>
|
Chris@16
|
1143 class basic_future : public base_future
|
Chris@16
|
1144 {
|
Chris@16
|
1145 protected:
|
Chris@16
|
1146 public:
|
Chris@16
|
1147
|
Chris@16
|
1148 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
|
Chris@101
|
1149 typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
|
Chris@101
|
1150
|
Chris@101
|
1151 static //BOOST_CONSTEXPR
|
Chris@101
|
1152 future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) {
|
Chris@101
|
1153 promise<R> p;
|
Chris@101
|
1154 p.set_exception(ex.ptr_);
|
Chris@101
|
1155 return p.get_future().future_;
|
Chris@101
|
1156 }
|
Chris@101
|
1157
|
Chris@101
|
1158 void set_exceptional_if_invalid() {
|
Chris@101
|
1159 if (valid()) return;
|
Chris@101
|
1160 promise<R> p;
|
Chris@101
|
1161 p.set_exception(future_uninitialized());
|
Chris@101
|
1162 future_ = p.get_future().future_;
|
Chris@101
|
1163 }
|
Chris@16
|
1164
|
Chris@16
|
1165 future_ptr future_;
|
Chris@16
|
1166
|
Chris@16
|
1167 basic_future(future_ptr a_future):
|
Chris@16
|
1168 future_(a_future)
|
Chris@16
|
1169 {
|
Chris@101
|
1170 if (a_future) a_future->inc();
|
Chris@16
|
1171 }
|
Chris@16
|
1172
|
Chris@16
|
1173 public:
|
Chris@16
|
1174 typedef future_state::state state;
|
Chris@16
|
1175
|
Chris@101
|
1176 BOOST_THREAD_MOVABLE_ONLY(basic_future)
|
Chris@16
|
1177 basic_future(): future_() {}
|
Chris@101
|
1178
|
Chris@101
|
1179
|
Chris@101
|
1180 //BOOST_CONSTEXPR
|
Chris@101
|
1181 basic_future(exceptional_ptr const& ex)
|
Chris@101
|
1182 : future_(make_exceptional_future_ptr(ex))
|
Chris@101
|
1183 {
|
Chris@101
|
1184 future_->inc();
|
Chris@101
|
1185 }
|
Chris@101
|
1186
|
Chris@101
|
1187 ~basic_future() {
|
Chris@101
|
1188 if (future_) future_->dec();
|
Chris@101
|
1189 }
|
Chris@16
|
1190
|
Chris@16
|
1191 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
|
Chris@16
|
1192 future_(BOOST_THREAD_RV(other).future_)
|
Chris@16
|
1193 {
|
Chris@16
|
1194 BOOST_THREAD_RV(other).future_.reset();
|
Chris@16
|
1195 }
|
Chris@16
|
1196 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
|
Chris@16
|
1197 {
|
Chris@101
|
1198 if (this->future_) {
|
Chris@101
|
1199 this->future_->dec();
|
Chris@101
|
1200 }
|
Chris@16
|
1201 future_=BOOST_THREAD_RV(other).future_;
|
Chris@16
|
1202 BOOST_THREAD_RV(other).future_.reset();
|
Chris@16
|
1203 return *this;
|
Chris@16
|
1204 }
|
Chris@16
|
1205 void swap(basic_future& that) BOOST_NOEXCEPT
|
Chris@16
|
1206 {
|
Chris@16
|
1207 future_.swap(that.future_);
|
Chris@16
|
1208 }
|
Chris@16
|
1209 // functions to check state, and wait for ready
|
Chris@101
|
1210 state get_state(boost::unique_lock<boost::mutex>& lk) const
|
Chris@101
|
1211 {
|
Chris@101
|
1212 if(!future_)
|
Chris@101
|
1213 {
|
Chris@101
|
1214 return future_state::uninitialized;
|
Chris@101
|
1215 }
|
Chris@101
|
1216 return future_->get_state(lk);
|
Chris@101
|
1217 }
|
Chris@16
|
1218 state get_state() const
|
Chris@16
|
1219 {
|
Chris@16
|
1220 if(!future_)
|
Chris@16
|
1221 {
|
Chris@16
|
1222 return future_state::uninitialized;
|
Chris@16
|
1223 }
|
Chris@16
|
1224 return future_->get_state();
|
Chris@16
|
1225 }
|
Chris@16
|
1226
|
Chris@16
|
1227 bool is_ready() const
|
Chris@16
|
1228 {
|
Chris@16
|
1229 return get_state()==future_state::ready;
|
Chris@16
|
1230 }
|
Chris@16
|
1231
|
Chris@101
|
1232 bool is_ready(boost::unique_lock<boost::mutex>& lk) const
|
Chris@101
|
1233 {
|
Chris@101
|
1234 return get_state(lk)==future_state::ready;
|
Chris@101
|
1235 }
|
Chris@16
|
1236 bool has_exception() const
|
Chris@16
|
1237 {
|
Chris@16
|
1238 return future_ && future_->has_exception();
|
Chris@16
|
1239 }
|
Chris@16
|
1240
|
Chris@16
|
1241 bool has_value() const
|
Chris@16
|
1242 {
|
Chris@16
|
1243 return future_ && future_->has_value();
|
Chris@16
|
1244 }
|
Chris@16
|
1245
|
Chris@16
|
1246 launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
|
Chris@16
|
1247 {
|
Chris@16
|
1248 if ( future_ ) return future_->launch_policy(lk);
|
Chris@16
|
1249 else return launch(launch::none);
|
Chris@16
|
1250 }
|
Chris@16
|
1251
|
Chris@16
|
1252 exception_ptr get_exception_ptr()
|
Chris@16
|
1253 {
|
Chris@16
|
1254 return future_
|
Chris@16
|
1255 ? future_->get_exception_ptr()
|
Chris@16
|
1256 : exception_ptr();
|
Chris@16
|
1257 }
|
Chris@16
|
1258
|
Chris@16
|
1259 bool valid() const BOOST_NOEXCEPT
|
Chris@16
|
1260 {
|
Chris@101
|
1261 return future_ != 0 && future_->valid();
|
Chris@16
|
1262 }
|
Chris@16
|
1263
|
Chris@16
|
1264 void wait() const
|
Chris@16
|
1265 {
|
Chris@16
|
1266 if(!future_)
|
Chris@16
|
1267 {
|
Chris@16
|
1268 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1269 }
|
Chris@16
|
1270 future_->wait(false);
|
Chris@16
|
1271 }
|
Chris@16
|
1272
|
Chris@101
|
1273 typedef detail::shared_state_base::notify_when_ready_handle notify_when_ready_handle;
|
Chris@101
|
1274
|
Chris@101
|
1275 boost::mutex& mutex() {
|
Chris@101
|
1276 if(!future_)
|
Chris@101
|
1277 {
|
Chris@101
|
1278 boost::throw_exception(future_uninitialized());
|
Chris@101
|
1279 }
|
Chris@101
|
1280 return future_->mutex;
|
Chris@101
|
1281 };
|
Chris@101
|
1282
|
Chris@101
|
1283 notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv)
|
Chris@101
|
1284 {
|
Chris@101
|
1285 if(!future_)
|
Chris@101
|
1286 {
|
Chris@101
|
1287 boost::throw_exception(future_uninitialized());
|
Chris@101
|
1288 }
|
Chris@101
|
1289 return future_->notify_when_ready(cv);
|
Chris@101
|
1290 }
|
Chris@101
|
1291
|
Chris@101
|
1292 void unnotify_when_ready(notify_when_ready_handle h)
|
Chris@101
|
1293 {
|
Chris@101
|
1294 if(!future_)
|
Chris@101
|
1295 {
|
Chris@101
|
1296 boost::throw_exception(future_uninitialized());
|
Chris@101
|
1297 }
|
Chris@101
|
1298 return future_->unnotify_when_ready(h);
|
Chris@101
|
1299 }
|
Chris@101
|
1300
|
Chris@16
|
1301 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
1302 template<typename Duration>
|
Chris@16
|
1303 bool timed_wait(Duration const& rel_time) const
|
Chris@16
|
1304 {
|
Chris@16
|
1305 return timed_wait_until(boost::get_system_time()+rel_time);
|
Chris@16
|
1306 }
|
Chris@16
|
1307
|
Chris@16
|
1308 bool timed_wait_until(boost::system_time const& abs_time) const
|
Chris@16
|
1309 {
|
Chris@16
|
1310 if(!future_)
|
Chris@16
|
1311 {
|
Chris@16
|
1312 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1313 }
|
Chris@16
|
1314 return future_->timed_wait_until(abs_time);
|
Chris@16
|
1315 }
|
Chris@16
|
1316 #endif
|
Chris@16
|
1317 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
1318 template <class Rep, class Period>
|
Chris@16
|
1319 future_status
|
Chris@16
|
1320 wait_for(const chrono::duration<Rep, Period>& rel_time) const
|
Chris@16
|
1321 {
|
Chris@16
|
1322 return wait_until(chrono::steady_clock::now() + rel_time);
|
Chris@16
|
1323
|
Chris@16
|
1324 }
|
Chris@16
|
1325 template <class Clock, class Duration>
|
Chris@16
|
1326 future_status
|
Chris@16
|
1327 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
|
Chris@16
|
1328 {
|
Chris@16
|
1329 if(!future_)
|
Chris@16
|
1330 {
|
Chris@16
|
1331 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1332 }
|
Chris@16
|
1333 return future_->wait_until(abs_time);
|
Chris@16
|
1334 }
|
Chris@16
|
1335 #endif
|
Chris@16
|
1336
|
Chris@16
|
1337 };
|
Chris@16
|
1338
|
Chris@16
|
1339 } // detail
|
Chris@16
|
1340 BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@16
|
1341
|
Chris@16
|
1342 namespace detail
|
Chris@16
|
1343 {
|
Chris@16
|
1344 #if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
|
Chris@16
|
1345 template <class Rp, class Fp>
|
Chris@16
|
1346 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1347 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1348
|
Chris@16
|
1349 template <class Rp, class Fp>
|
Chris@16
|
1350 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1351 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1352 #endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
|
Chris@16
|
1353 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1354 template<typename F, typename Rp, typename Fp>
|
Chris@16
|
1355 struct future_deferred_continuation_shared_state;
|
Chris@16
|
1356 template<typename F, typename Rp, typename Fp>
|
Chris@16
|
1357 struct future_async_continuation_shared_state;
|
Chris@16
|
1358
|
Chris@16
|
1359 template <class F, class Rp, class Fp>
|
Chris@16
|
1360 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1361 make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
Chris@16
|
1362
|
Chris@16
|
1363 template <class F, class Rp, class Fp>
|
Chris@16
|
1364 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1365 make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
Chris@16
|
1366 #endif
|
Chris@16
|
1367 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1368 template<typename F, typename Rp>
|
Chris@16
|
1369 struct future_unwrap_shared_state;
|
Chris@16
|
1370 template <class F, class Rp>
|
Chris@16
|
1371 inline BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1372 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
|
Chris@16
|
1373 #endif
|
Chris@16
|
1374 }
|
Chris@16
|
1375
|
Chris@16
|
1376 template <typename R>
|
Chris@16
|
1377 class BOOST_THREAD_FUTURE : public detail::basic_future<R>
|
Chris@16
|
1378 {
|
Chris@16
|
1379 private:
|
Chris@16
|
1380 typedef detail::basic_future<R> base_type;
|
Chris@16
|
1381 typedef typename base_type::future_ptr future_ptr;
|
Chris@16
|
1382
|
Chris@16
|
1383 friend class shared_future<R>;
|
Chris@16
|
1384 friend class promise<R>;
|
Chris@16
|
1385 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1386 template <typename, typename, typename>
|
Chris@16
|
1387 friend struct detail::future_async_continuation_shared_state;
|
Chris@16
|
1388 template <typename, typename, typename>
|
Chris@16
|
1389 friend struct detail::future_deferred_continuation_shared_state;
|
Chris@16
|
1390
|
Chris@16
|
1391 template <class F, class Rp, class Fp>
|
Chris@16
|
1392 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1393 detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
Chris@16
|
1394
|
Chris@16
|
1395 template <class F, class Rp, class Fp>
|
Chris@16
|
1396 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1397 detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
Chris@16
|
1398 #endif
|
Chris@16
|
1399 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1400 template<typename F, typename Rp>
|
Chris@16
|
1401 friend struct detail::future_unwrap_shared_state;
|
Chris@16
|
1402 template <class F, class Rp>
|
Chris@16
|
1403 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1404 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
|
Chris@16
|
1405 #endif
|
Chris@16
|
1406 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
1407 template <class> friend class packaged_task; // todo check if this works in windows
|
Chris@16
|
1408 #else
|
Chris@16
|
1409 friend class packaged_task<R>;
|
Chris@16
|
1410 #endif
|
Chris@16
|
1411 friend class detail::future_waiter;
|
Chris@16
|
1412
|
Chris@16
|
1413 template <class Rp, class Fp>
|
Chris@16
|
1414 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1415 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1416
|
Chris@16
|
1417 template <class Rp, class Fp>
|
Chris@16
|
1418 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1419 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1420
|
Chris@16
|
1421
|
Chris@101
|
1422 typedef typename base_type::move_dest_type move_dest_type;
|
Chris@101
|
1423 public: // when_all
|
Chris@16
|
1424
|
Chris@16
|
1425 BOOST_THREAD_FUTURE(future_ptr a_future):
|
Chris@16
|
1426 base_type(a_future)
|
Chris@16
|
1427 {
|
Chris@16
|
1428 }
|
Chris@16
|
1429
|
Chris@16
|
1430 public:
|
Chris@16
|
1431 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
|
Chris@16
|
1432 typedef future_state::state state;
|
Chris@16
|
1433 typedef R value_type; // EXTENSION
|
Chris@16
|
1434
|
Chris@16
|
1435 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
|
Chris@101
|
1436 //BOOST_CONSTEXPR
|
Chris@101
|
1437 BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
|
Chris@101
|
1438 base_type(ex) {}
|
Chris@16
|
1439
|
Chris@16
|
1440 ~BOOST_THREAD_FUTURE() {}
|
Chris@16
|
1441
|
Chris@16
|
1442 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
|
Chris@16
|
1443 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
Chris@16
|
1444 {
|
Chris@16
|
1445 }
|
Chris@16
|
1446 inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
|
Chris@16
|
1447
|
Chris@101
|
1448 explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future<R>) other) :
|
Chris@101
|
1449 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
Chris@101
|
1450 {}
|
Chris@101
|
1451
|
Chris@16
|
1452 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
|
Chris@16
|
1453 {
|
Chris@16
|
1454 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
|
Chris@16
|
1455 return *this;
|
Chris@16
|
1456 }
|
Chris@16
|
1457
|
Chris@16
|
1458 shared_future<R> share()
|
Chris@16
|
1459 {
|
Chris@16
|
1460 return shared_future<R>(::boost::move(*this));
|
Chris@16
|
1461 }
|
Chris@16
|
1462
|
Chris@16
|
1463 void swap(BOOST_THREAD_FUTURE& other)
|
Chris@16
|
1464 {
|
Chris@16
|
1465 static_cast<base_type*>(this)->swap(other);
|
Chris@16
|
1466 }
|
Chris@16
|
1467
|
Chris@16
|
1468 // todo this function must be private and friendship provided to the internal users.
|
Chris@16
|
1469 void set_async()
|
Chris@16
|
1470 {
|
Chris@16
|
1471 this->future_->set_async();
|
Chris@16
|
1472 }
|
Chris@16
|
1473 // todo this function must be private and friendship provided to the internal users.
|
Chris@16
|
1474 void set_deferred()
|
Chris@16
|
1475 {
|
Chris@16
|
1476 this->future_->set_deferred();
|
Chris@16
|
1477 }
|
Chris@101
|
1478 bool run_if_is_deferred() {
|
Chris@101
|
1479 return this->future_->run_if_is_deferred();
|
Chris@101
|
1480 }
|
Chris@101
|
1481 bool run_if_is_deferred_or_ready() {
|
Chris@101
|
1482 return this->future_->run_if_is_deferred_or_ready();
|
Chris@101
|
1483 }
|
Chris@16
|
1484 // retrieving the value
|
Chris@16
|
1485 move_dest_type get()
|
Chris@16
|
1486 {
|
Chris@101
|
1487 if (this->future_ == 0)
|
Chris@16
|
1488 {
|
Chris@16
|
1489 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1490 }
|
Chris@101
|
1491 unique_lock<boost::mutex> lk(this->future_->mutex);
|
Chris@101
|
1492 if (! this->future_->valid(lk))
|
Chris@101
|
1493 {
|
Chris@101
|
1494 boost::throw_exception(future_uninitialized());
|
Chris@101
|
1495 }
|
Chris@16
|
1496 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@101
|
1497 this->future_->invalidate(lk);
|
Chris@16
|
1498 #endif
|
Chris@101
|
1499 return this->future_->get(lk);
|
Chris@16
|
1500 }
|
Chris@16
|
1501
|
Chris@16
|
1502 template <typename R2>
|
Chris@16
|
1503 typename boost::disable_if< is_void<R2>, move_dest_type>::type
|
Chris@16
|
1504 get_or(BOOST_THREAD_RV_REF(R2) v)
|
Chris@16
|
1505 {
|
Chris@101
|
1506
|
Chris@101
|
1507 if (this->future_ == 0)
|
Chris@16
|
1508 {
|
Chris@16
|
1509 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1510 }
|
Chris@101
|
1511 unique_lock<boost::mutex> lk(this->future_->mutex);
|
Chris@101
|
1512 if (! this->future_->valid(lk))
|
Chris@101
|
1513 {
|
Chris@101
|
1514 boost::throw_exception(future_uninitialized());
|
Chris@101
|
1515 }
|
Chris@101
|
1516 this->future_->wait(lk, false);
|
Chris@16
|
1517 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@101
|
1518 this->future_->invalidate(lk);
|
Chris@16
|
1519 #endif
|
Chris@101
|
1520
|
Chris@101
|
1521 if (this->future_->has_value(lk)) {
|
Chris@101
|
1522 return this->future_->get(lk);
|
Chris@16
|
1523 }
|
Chris@16
|
1524 else {
|
Chris@16
|
1525 return boost::move(v);
|
Chris@16
|
1526 }
|
Chris@16
|
1527 }
|
Chris@16
|
1528
|
Chris@16
|
1529 template <typename R2>
|
Chris@16
|
1530 typename boost::disable_if< is_void<R2>, move_dest_type>::type
|
Chris@16
|
1531 get_or(R2 const& v) // EXTENSION
|
Chris@16
|
1532 {
|
Chris@101
|
1533 if (this->future_ == 0)
|
Chris@16
|
1534 {
|
Chris@16
|
1535 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1536 }
|
Chris@101
|
1537 unique_lock<boost::mutex> lk(this->future_->mutex);
|
Chris@101
|
1538 if (! this->future_->valid(lk))
|
Chris@101
|
1539 {
|
Chris@101
|
1540 boost::throw_exception(future_uninitialized());
|
Chris@101
|
1541 }
|
Chris@101
|
1542 this->future_->wait(lk, false);
|
Chris@16
|
1543 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@101
|
1544 this->future_->invalidate(lk);
|
Chris@16
|
1545 #endif
|
Chris@101
|
1546 if (this->future_->has_value(lk)) {
|
Chris@101
|
1547 return this->future_->get(lk);
|
Chris@16
|
1548 }
|
Chris@16
|
1549 else {
|
Chris@16
|
1550 return v;
|
Chris@16
|
1551 }
|
Chris@16
|
1552 }
|
Chris@16
|
1553
|
Chris@16
|
1554 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1555 template<typename F>
|
Chris@16
|
1556 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@16
|
1557 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@16
|
1558 template<typename F>
|
Chris@16
|
1559 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@16
|
1560 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@101
|
1561 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
1562 template<typename Ex, typename F>
|
Chris@101
|
1563 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@101
|
1564 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@101
|
1565 #endif
|
Chris@16
|
1566
|
Chris@16
|
1567 template <typename R2>
|
Chris@16
|
1568 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
|
Chris@16
|
1569 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION
|
Chris@16
|
1570 template <typename R2>
|
Chris@16
|
1571 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
|
Chris@16
|
1572 fallback_to(R2 const& v); // EXTENSION
|
Chris@16
|
1573
|
Chris@16
|
1574 #endif
|
Chris@16
|
1575
|
Chris@16
|
1576 };
|
Chris@16
|
1577
|
Chris@16
|
1578 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@16
|
1579
|
Chris@16
|
1580 template <typename R2>
|
Chris@16
|
1581 class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
|
Chris@16
|
1582 {
|
Chris@16
|
1583 typedef BOOST_THREAD_FUTURE<R2> R;
|
Chris@16
|
1584
|
Chris@16
|
1585 private:
|
Chris@16
|
1586 typedef detail::basic_future<R> base_type;
|
Chris@16
|
1587 typedef typename base_type::future_ptr future_ptr;
|
Chris@16
|
1588
|
Chris@16
|
1589 friend class shared_future<R>;
|
Chris@16
|
1590 friend class promise<R>;
|
Chris@16
|
1591 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1592 template <typename, typename, typename>
|
Chris@16
|
1593 friend struct detail::future_async_continuation_shared_state;
|
Chris@16
|
1594 template <typename, typename, typename>
|
Chris@16
|
1595 friend struct detail::future_deferred_continuation_shared_state;
|
Chris@16
|
1596
|
Chris@16
|
1597 template <class F, class Rp, class Fp>
|
Chris@16
|
1598 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1599 detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
Chris@16
|
1600
|
Chris@16
|
1601 template <class F, class Rp, class Fp>
|
Chris@16
|
1602 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1603 detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
Chris@16
|
1604 #endif
|
Chris@16
|
1605 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1606 template<typename F, typename Rp>
|
Chris@16
|
1607 friend struct detail::future_unwrap_shared_state;
|
Chris@16
|
1608 template <class F, class Rp>
|
Chris@16
|
1609 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1610 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
|
Chris@16
|
1611 #endif
|
Chris@16
|
1612 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
1613 template <class> friend class packaged_task; // todo check if this works in windows
|
Chris@16
|
1614 #else
|
Chris@16
|
1615 friend class packaged_task<R>;
|
Chris@16
|
1616 #endif
|
Chris@16
|
1617 friend class detail::future_waiter;
|
Chris@16
|
1618
|
Chris@16
|
1619 template <class Rp, class Fp>
|
Chris@16
|
1620 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1621 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1622
|
Chris@16
|
1623 template <class Rp, class Fp>
|
Chris@16
|
1624 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1625 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1626
|
Chris@101
|
1627 typedef typename base_type::move_dest_type move_dest_type;
|
Chris@16
|
1628
|
Chris@16
|
1629 BOOST_THREAD_FUTURE(future_ptr a_future):
|
Chris@16
|
1630 base_type(a_future)
|
Chris@16
|
1631 {
|
Chris@16
|
1632 }
|
Chris@16
|
1633
|
Chris@16
|
1634 public:
|
Chris@16
|
1635 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
|
Chris@16
|
1636 typedef future_state::state state;
|
Chris@16
|
1637 typedef R value_type; // EXTENSION
|
Chris@16
|
1638
|
Chris@16
|
1639 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
|
Chris@101
|
1640 //BOOST_CONSTEXPR
|
Chris@101
|
1641 BOOST_THREAD_FUTURE(exceptional_ptr const& ex):
|
Chris@101
|
1642 base_type(ex) {}
|
Chris@16
|
1643
|
Chris@16
|
1644 ~BOOST_THREAD_FUTURE() {}
|
Chris@16
|
1645
|
Chris@16
|
1646 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
|
Chris@16
|
1647 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
Chris@16
|
1648 {
|
Chris@16
|
1649 }
|
Chris@16
|
1650
|
Chris@16
|
1651 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
|
Chris@16
|
1652 {
|
Chris@16
|
1653 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
|
Chris@16
|
1654 return *this;
|
Chris@16
|
1655 }
|
Chris@16
|
1656
|
Chris@16
|
1657 shared_future<R> share()
|
Chris@16
|
1658 {
|
Chris@16
|
1659 return shared_future<R>(::boost::move(*this));
|
Chris@16
|
1660 }
|
Chris@16
|
1661
|
Chris@16
|
1662 void swap(BOOST_THREAD_FUTURE& other)
|
Chris@16
|
1663 {
|
Chris@16
|
1664 static_cast<base_type*>(this)->swap(other);
|
Chris@16
|
1665 }
|
Chris@16
|
1666
|
Chris@16
|
1667 // todo this function must be private and friendship provided to the internal users.
|
Chris@16
|
1668 void set_async()
|
Chris@16
|
1669 {
|
Chris@16
|
1670 this->future_->set_async();
|
Chris@16
|
1671 }
|
Chris@16
|
1672 // todo this function must be private and friendship provided to the internal users.
|
Chris@16
|
1673 void set_deferred()
|
Chris@16
|
1674 {
|
Chris@16
|
1675 this->future_->set_deferred();
|
Chris@16
|
1676 }
|
Chris@101
|
1677 bool run_if_is_deferred() {
|
Chris@101
|
1678 return this->future_->run_if_is_deferred();
|
Chris@101
|
1679 }
|
Chris@101
|
1680 bool run_if_is_deferred_or_ready() {
|
Chris@101
|
1681 return this->future_->run_if_is_deferred_or_ready();
|
Chris@101
|
1682 }
|
Chris@16
|
1683 // retrieving the value
|
Chris@16
|
1684 move_dest_type get()
|
Chris@16
|
1685 {
|
Chris@101
|
1686 if (this->future_ == 0)
|
Chris@16
|
1687 {
|
Chris@16
|
1688 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1689 }
|
Chris@101
|
1690 unique_lock<boost::mutex> lk(this->future_->mutex);
|
Chris@101
|
1691 if (! this->future_->valid(lk))
|
Chris@101
|
1692 {
|
Chris@101
|
1693 boost::throw_exception(future_uninitialized());
|
Chris@101
|
1694 }
|
Chris@16
|
1695 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@101
|
1696 this->future_->invalidate(lk);
|
Chris@16
|
1697 #endif
|
Chris@101
|
1698 return this->future_->get(lk);
|
Chris@16
|
1699 }
|
Chris@16
|
1700 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
|
Chris@16
|
1701 {
|
Chris@101
|
1702 if (this->future_ == 0)
|
Chris@16
|
1703 {
|
Chris@16
|
1704 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1705 }
|
Chris@101
|
1706 unique_lock<boost::mutex> lk(this->future_->mutex);
|
Chris@101
|
1707 if (! this->future_->valid(lk))
|
Chris@16
|
1708 {
|
Chris@16
|
1709 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1710 }
|
Chris@101
|
1711 this->future_->wait(lk, false);
|
Chris@16
|
1712 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@101
|
1713 this->future_->invalidate(lk);
|
Chris@16
|
1714 #endif
|
Chris@101
|
1715 if (this->future_->has_value(lk)) return this->future_->get(lk);
|
Chris@101
|
1716 else return boost::move(v);
|
Chris@101
|
1717 }
|
Chris@101
|
1718
|
Chris@101
|
1719 move_dest_type get_or(R const& v) // EXTENSION
|
Chris@101
|
1720 {
|
Chris@101
|
1721 if (this->future_ == 0)
|
Chris@101
|
1722 {
|
Chris@101
|
1723 boost::throw_exception(future_uninitialized());
|
Chris@101
|
1724 }
|
Chris@101
|
1725 unique_lock<boost::mutex> lk(this->future_->mutex);
|
Chris@101
|
1726 if (! this->future_->valid(lk))
|
Chris@101
|
1727 {
|
Chris@101
|
1728 boost::throw_exception(future_uninitialized());
|
Chris@101
|
1729 }
|
Chris@101
|
1730 this->future_->wait(lk, false);
|
Chris@101
|
1731 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@101
|
1732 this->future_->invalidate(lk);
|
Chris@101
|
1733 #endif
|
Chris@101
|
1734 if (this->future_->has_value(lk)) return this->future_->get(lk);
|
Chris@16
|
1735 else return v;
|
Chris@16
|
1736 }
|
Chris@16
|
1737
|
Chris@16
|
1738
|
Chris@16
|
1739 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1740 template<typename F>
|
Chris@16
|
1741 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@16
|
1742 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@16
|
1743 template<typename F>
|
Chris@16
|
1744 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@16
|
1745 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@101
|
1746 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
1747 template<typename Ex, typename F>
|
Chris@101
|
1748 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@101
|
1749 then(Ex &ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@101
|
1750 #endif
|
Chris@16
|
1751 #endif
|
Chris@16
|
1752
|
Chris@16
|
1753 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1754 inline
|
Chris@16
|
1755 BOOST_THREAD_FUTURE<R2>
|
Chris@16
|
1756 unwrap(); // EXTENSION
|
Chris@16
|
1757 #endif
|
Chris@16
|
1758
|
Chris@16
|
1759 };
|
Chris@16
|
1760
|
Chris@16
|
1761 template <typename R>
|
Chris@16
|
1762 class shared_future : public detail::basic_future<R>
|
Chris@16
|
1763 {
|
Chris@16
|
1764 typedef detail::basic_future<R> base_type;
|
Chris@16
|
1765 typedef typename base_type::future_ptr future_ptr;
|
Chris@16
|
1766
|
Chris@16
|
1767 friend class detail::future_waiter;
|
Chris@16
|
1768 friend class promise<R>;
|
Chris@16
|
1769
|
Chris@16
|
1770 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1771 template <typename, typename, typename>
|
Chris@16
|
1772 friend struct detail::future_async_continuation_shared_state;
|
Chris@16
|
1773 template <typename, typename, typename>
|
Chris@16
|
1774 friend struct detail::future_deferred_continuation_shared_state;
|
Chris@16
|
1775
|
Chris@16
|
1776 template <class F, class Rp, class Fp>
|
Chris@16
|
1777 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1778 detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
Chris@16
|
1779
|
Chris@16
|
1780 template <class F, class Rp, class Fp>
|
Chris@16
|
1781 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1782 detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c);
|
Chris@16
|
1783 #endif
|
Chris@16
|
1784 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
1785 template <class> friend class packaged_task;// todo check if this works in windows
|
Chris@16
|
1786 #else
|
Chris@16
|
1787 friend class packaged_task<R>;
|
Chris@16
|
1788 #endif
|
Chris@16
|
1789 shared_future(future_ptr a_future):
|
Chris@16
|
1790 base_type(a_future)
|
Chris@16
|
1791 {}
|
Chris@16
|
1792
|
Chris@16
|
1793 public:
|
Chris@101
|
1794 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future)
|
Chris@16
|
1795 typedef R value_type; // EXTENSION
|
Chris@16
|
1796
|
Chris@16
|
1797 shared_future(shared_future const& other):
|
Chris@101
|
1798 base_type(other.future_)
|
Chris@16
|
1799 {}
|
Chris@16
|
1800
|
Chris@16
|
1801 typedef future_state::state state;
|
Chris@16
|
1802
|
Chris@16
|
1803 BOOST_CONSTEXPR shared_future()
|
Chris@16
|
1804 {}
|
Chris@101
|
1805 //BOOST_CONSTEXPR
|
Chris@101
|
1806 shared_future(exceptional_ptr const& ex):
|
Chris@101
|
1807 base_type(ex) {}
|
Chris@16
|
1808 ~shared_future()
|
Chris@16
|
1809 {}
|
Chris@16
|
1810
|
Chris@101
|
1811 shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other)
|
Chris@16
|
1812 {
|
Chris@101
|
1813 if (other.future_) {
|
Chris@101
|
1814 other.future_->inc();
|
Chris@101
|
1815 }
|
Chris@101
|
1816 if (this->future_) {
|
Chris@101
|
1817 this->future_->dec();
|
Chris@101
|
1818 }
|
Chris@101
|
1819 this->future_ = other.future_;
|
Chris@16
|
1820 return *this;
|
Chris@16
|
1821 }
|
Chris@101
|
1822
|
Chris@16
|
1823 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
|
Chris@16
|
1824 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
Chris@16
|
1825 {
|
Chris@16
|
1826 }
|
Chris@16
|
1827 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
|
Chris@16
|
1828 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
Chris@16
|
1829 {
|
Chris@16
|
1830 }
|
Chris@16
|
1831
|
Chris@16
|
1832 shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
|
Chris@16
|
1833 {
|
Chris@16
|
1834 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
|
Chris@16
|
1835 return *this;
|
Chris@16
|
1836 }
|
Chris@16
|
1837 shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
|
Chris@16
|
1838 {
|
Chris@16
|
1839 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
|
Chris@16
|
1840 return *this;
|
Chris@16
|
1841 }
|
Chris@16
|
1842
|
Chris@16
|
1843 void swap(shared_future& other) BOOST_NOEXCEPT
|
Chris@16
|
1844 {
|
Chris@16
|
1845 static_cast<base_type*>(this)->swap(other);
|
Chris@16
|
1846 }
|
Chris@101
|
1847 bool run_if_is_deferred() {
|
Chris@101
|
1848 return this->future_->run_if_is_deferred();
|
Chris@101
|
1849 }
|
Chris@101
|
1850 bool run_if_is_deferred_or_ready() {
|
Chris@101
|
1851 return this->future_->run_if_is_deferred_or_ready();
|
Chris@101
|
1852 }
|
Chris@16
|
1853 // retrieving the value
|
Chris@101
|
1854 typename detail::shared_state<R>::shared_future_get_result_type get() const
|
Chris@16
|
1855 {
|
Chris@16
|
1856 if(!this->future_)
|
Chris@16
|
1857 {
|
Chris@16
|
1858 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1859 }
|
Chris@16
|
1860 return this->future_->get_sh();
|
Chris@16
|
1861 }
|
Chris@16
|
1862
|
Chris@16
|
1863 template <typename R2>
|
Chris@16
|
1864 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
|
Chris@101
|
1865 get_or(BOOST_THREAD_RV_REF(R2) v) const // EXTENSION
|
Chris@16
|
1866 {
|
Chris@16
|
1867 if(!this->future_)
|
Chris@16
|
1868 {
|
Chris@16
|
1869 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1870 }
|
Chris@101
|
1871 this->future_->wait();
|
Chris@101
|
1872 if (this->future_->has_value()) return this->future_->get_sh();
|
Chris@16
|
1873 else return boost::move(v);
|
Chris@16
|
1874 }
|
Chris@16
|
1875
|
Chris@16
|
1876 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1877 template<typename F>
|
Chris@16
|
1878 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
|
Chris@101
|
1879 then(BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
|
Chris@16
|
1880 template<typename F>
|
Chris@16
|
1881 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
|
Chris@101
|
1882 then(launch policy, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
|
Chris@101
|
1883 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
1884 template<typename Ex, typename F>
|
Chris@101
|
1885 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
|
Chris@101
|
1886 then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION
|
Chris@101
|
1887 #endif
|
Chris@16
|
1888 #endif
|
Chris@16
|
1889
|
Chris@16
|
1890 };
|
Chris@16
|
1891
|
Chris@16
|
1892 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@16
|
1893
|
Chris@16
|
1894 template <typename R>
|
Chris@16
|
1895 class promise
|
Chris@16
|
1896 {
|
Chris@16
|
1897 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
|
Chris@16
|
1898
|
Chris@101
|
1899 typedef typename detail::shared_state<R>::source_reference_type source_reference_type;
|
Chris@101
|
1900 typedef typename detail::shared_state<R>::rvalue_source_type rvalue_source_type;
|
Chris@101
|
1901 typedef typename detail::shared_state<R>::move_dest_type move_dest_type;
|
Chris@101
|
1902 typedef typename detail::shared_state<R>::shared_future_get_result_type shared_future_get_result_type;
|
Chris@101
|
1903
|
Chris@16
|
1904 future_ptr future_;
|
Chris@16
|
1905 bool future_obtained;
|
Chris@16
|
1906
|
Chris@16
|
1907 void lazy_init()
|
Chris@16
|
1908 {
|
Chris@16
|
1909 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
1910 #include <boost/detail/atomic_undef_macros.hpp>
|
Chris@16
|
1911 if(!atomic_load(&future_))
|
Chris@16
|
1912 {
|
Chris@16
|
1913 future_ptr blank;
|
Chris@16
|
1914 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
|
Chris@16
|
1915 }
|
Chris@16
|
1916 #include <boost/detail/atomic_redef_macros.hpp>
|
Chris@16
|
1917 #endif
|
Chris@16
|
1918 }
|
Chris@16
|
1919
|
Chris@16
|
1920 public:
|
Chris@16
|
1921 BOOST_THREAD_MOVABLE_ONLY(promise)
|
Chris@16
|
1922 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
1923 template <class Allocator>
|
Chris@16
|
1924 promise(boost::allocator_arg_t, Allocator a)
|
Chris@16
|
1925 {
|
Chris@16
|
1926 typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2;
|
Chris@16
|
1927 A2 a2(a);
|
Chris@16
|
1928 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
1929
|
Chris@16
|
1930 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) );
|
Chris@16
|
1931 future_obtained = false;
|
Chris@16
|
1932 }
|
Chris@16
|
1933 #endif
|
Chris@16
|
1934 promise():
|
Chris@16
|
1935 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
1936 future_(),
|
Chris@16
|
1937 #else
|
Chris@16
|
1938 future_(new detail::shared_state<R>()),
|
Chris@16
|
1939 #endif
|
Chris@16
|
1940 future_obtained(false)
|
Chris@16
|
1941 {}
|
Chris@16
|
1942
|
Chris@16
|
1943 ~promise()
|
Chris@16
|
1944 {
|
Chris@16
|
1945 if(future_)
|
Chris@16
|
1946 {
|
Chris@16
|
1947 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
1948
|
Chris@16
|
1949 if(!future_->done && !future_->is_constructed)
|
Chris@16
|
1950 {
|
Chris@16
|
1951 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
|
Chris@16
|
1952 }
|
Chris@16
|
1953 }
|
Chris@16
|
1954 }
|
Chris@16
|
1955
|
Chris@16
|
1956 // Assignment
|
Chris@16
|
1957 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
|
Chris@16
|
1958 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
|
Chris@16
|
1959 {
|
Chris@16
|
1960 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
1961 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
1962 }
|
Chris@16
|
1963 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
|
Chris@16
|
1964 {
|
Chris@16
|
1965 future_=BOOST_THREAD_RV(rhs).future_;
|
Chris@16
|
1966 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
|
Chris@16
|
1967 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
1968 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
1969 return *this;
|
Chris@16
|
1970 }
|
Chris@16
|
1971
|
Chris@16
|
1972 void swap(promise& other)
|
Chris@16
|
1973 {
|
Chris@16
|
1974 future_.swap(other.future_);
|
Chris@16
|
1975 std::swap(future_obtained,other.future_obtained);
|
Chris@16
|
1976 }
|
Chris@16
|
1977
|
Chris@16
|
1978 // Result retrieval
|
Chris@16
|
1979 BOOST_THREAD_FUTURE<R> get_future()
|
Chris@16
|
1980 {
|
Chris@16
|
1981 lazy_init();
|
Chris@16
|
1982 if (future_.get()==0)
|
Chris@16
|
1983 {
|
Chris@16
|
1984 boost::throw_exception(promise_moved());
|
Chris@16
|
1985 }
|
Chris@16
|
1986 if (future_obtained)
|
Chris@16
|
1987 {
|
Chris@16
|
1988 boost::throw_exception(future_already_retrieved());
|
Chris@16
|
1989 }
|
Chris@16
|
1990 future_obtained=true;
|
Chris@16
|
1991 return BOOST_THREAD_FUTURE<R>(future_);
|
Chris@16
|
1992 }
|
Chris@16
|
1993
|
Chris@101
|
1994 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
1995 template <class TR>
|
Chris@101
|
1996 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value(TR const & r)
|
Chris@16
|
1997 {
|
Chris@16
|
1998 lazy_init();
|
Chris@16
|
1999 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2000 if(future_->done)
|
Chris@16
|
2001 {
|
Chris@16
|
2002 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2003 }
|
Chris@16
|
2004 future_->mark_finished_with_result_internal(r, lock);
|
Chris@16
|
2005 }
|
Chris@101
|
2006 #else
|
Chris@101
|
2007 void set_value(source_reference_type r)
|
Chris@101
|
2008 {
|
Chris@101
|
2009 lazy_init();
|
Chris@101
|
2010 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@101
|
2011 if(future_->done)
|
Chris@101
|
2012 {
|
Chris@101
|
2013 boost::throw_exception(promise_already_satisfied());
|
Chris@101
|
2014 }
|
Chris@101
|
2015 future_->mark_finished_with_result_internal(r, lock);
|
Chris@101
|
2016 }
|
Chris@101
|
2017 #endif
|
Chris@101
|
2018
|
Chris@101
|
2019 void set_value(rvalue_source_type r)
|
Chris@16
|
2020 {
|
Chris@16
|
2021 lazy_init();
|
Chris@16
|
2022 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2023 if(future_->done)
|
Chris@16
|
2024 {
|
Chris@16
|
2025 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2026 }
|
Chris@16
|
2027 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
2028 future_->mark_finished_with_result_internal(boost::move(r), lock);
|
Chris@16
|
2029 #else
|
Chris@101
|
2030 future_->mark_finished_with_result_internal(static_cast<rvalue_source_type>(r), lock);
|
Chris@16
|
2031 #endif
|
Chris@16
|
2032 }
|
Chris@16
|
2033
|
Chris@101
|
2034 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
2035 template <class ...Args>
|
Chris@101
|
2036 void emplace(BOOST_THREAD_FWD_REF(Args) ...args)
|
Chris@101
|
2037 {
|
Chris@101
|
2038 lazy_init();
|
Chris@101
|
2039 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@101
|
2040 if(future_->done)
|
Chris@101
|
2041 {
|
Chris@101
|
2042 boost::throw_exception(promise_already_satisfied());
|
Chris@101
|
2043 }
|
Chris@101
|
2044 future_->mark_finished_with_result_internal(lock, boost::forward<Args>(args)...);
|
Chris@101
|
2045 }
|
Chris@101
|
2046
|
Chris@101
|
2047 #endif
|
Chris@101
|
2048
|
Chris@16
|
2049 void set_exception(boost::exception_ptr p)
|
Chris@16
|
2050 {
|
Chris@16
|
2051 lazy_init();
|
Chris@16
|
2052 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2053 if(future_->done)
|
Chris@16
|
2054 {
|
Chris@16
|
2055 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2056 }
|
Chris@16
|
2057 future_->mark_exceptional_finish_internal(p, lock);
|
Chris@16
|
2058 }
|
Chris@16
|
2059 template <typename E>
|
Chris@16
|
2060 void set_exception(E ex)
|
Chris@16
|
2061 {
|
Chris@101
|
2062 set_exception(boost::copy_exception(ex));
|
Chris@16
|
2063 }
|
Chris@16
|
2064 // setting the result with deferred notification
|
Chris@101
|
2065 #if defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
2066 template <class TR>
|
Chris@101
|
2067 typename boost::enable_if_c<is_copy_constructible<TR>::value && is_same<R, TR>::value, void>::type set_value_at_thread_exit(TR const& r)
|
Chris@16
|
2068 {
|
Chris@16
|
2069 if (future_.get()==0)
|
Chris@16
|
2070 {
|
Chris@16
|
2071 boost::throw_exception(promise_moved());
|
Chris@16
|
2072 }
|
Chris@16
|
2073 future_->set_value_at_thread_exit(r);
|
Chris@16
|
2074 }
|
Chris@101
|
2075 #else
|
Chris@101
|
2076 void set_value_at_thread_exit(source_reference_type r)
|
Chris@101
|
2077 {
|
Chris@101
|
2078 if (future_.get()==0)
|
Chris@101
|
2079 {
|
Chris@101
|
2080 boost::throw_exception(promise_moved());
|
Chris@101
|
2081 }
|
Chris@101
|
2082 future_->set_value_at_thread_exit(r);
|
Chris@101
|
2083 }
|
Chris@101
|
2084 #endif
|
Chris@16
|
2085 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
|
Chris@16
|
2086 {
|
Chris@16
|
2087 if (future_.get()==0)
|
Chris@16
|
2088 {
|
Chris@16
|
2089 boost::throw_exception(promise_moved());
|
Chris@16
|
2090 }
|
Chris@16
|
2091 future_->set_value_at_thread_exit(boost::move(r));
|
Chris@16
|
2092 }
|
Chris@16
|
2093 void set_exception_at_thread_exit(exception_ptr e)
|
Chris@16
|
2094 {
|
Chris@16
|
2095 if (future_.get()==0)
|
Chris@16
|
2096 {
|
Chris@16
|
2097 boost::throw_exception(promise_moved());
|
Chris@16
|
2098 }
|
Chris@16
|
2099 future_->set_exception_at_thread_exit(e);
|
Chris@16
|
2100 }
|
Chris@16
|
2101 template <typename E>
|
Chris@16
|
2102 void set_exception_at_thread_exit(E ex)
|
Chris@16
|
2103 {
|
Chris@101
|
2104 set_exception_at_thread_exit(boost::copy_exception(ex));
|
Chris@16
|
2105 }
|
Chris@16
|
2106
|
Chris@16
|
2107 template<typename F>
|
Chris@16
|
2108 void set_wait_callback(F f)
|
Chris@16
|
2109 {
|
Chris@16
|
2110 lazy_init();
|
Chris@16
|
2111 future_->set_wait_callback(f,this);
|
Chris@16
|
2112 }
|
Chris@16
|
2113
|
Chris@16
|
2114 };
|
Chris@16
|
2115
|
Chris@16
|
2116 template <typename R>
|
Chris@16
|
2117 class promise<R&>
|
Chris@16
|
2118 {
|
Chris@16
|
2119 typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr;
|
Chris@16
|
2120
|
Chris@16
|
2121 future_ptr future_;
|
Chris@16
|
2122 bool future_obtained;
|
Chris@16
|
2123
|
Chris@16
|
2124 void lazy_init()
|
Chris@16
|
2125 {
|
Chris@16
|
2126 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
2127 #include <boost/detail/atomic_undef_macros.hpp>
|
Chris@16
|
2128 if(!atomic_load(&future_))
|
Chris@16
|
2129 {
|
Chris@16
|
2130 future_ptr blank;
|
Chris@16
|
2131 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
|
Chris@16
|
2132 }
|
Chris@16
|
2133 #include <boost/detail/atomic_redef_macros.hpp>
|
Chris@16
|
2134 #endif
|
Chris@16
|
2135 }
|
Chris@16
|
2136
|
Chris@16
|
2137 public:
|
Chris@16
|
2138 BOOST_THREAD_MOVABLE_ONLY(promise)
|
Chris@16
|
2139 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
2140 template <class Allocator>
|
Chris@16
|
2141 promise(boost::allocator_arg_t, Allocator a)
|
Chris@16
|
2142 {
|
Chris@16
|
2143 typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2;
|
Chris@16
|
2144 A2 a2(a);
|
Chris@16
|
2145 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
2146
|
Chris@16
|
2147 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
|
Chris@16
|
2148 future_obtained = false;
|
Chris@16
|
2149 }
|
Chris@16
|
2150 #endif
|
Chris@16
|
2151 promise():
|
Chris@16
|
2152 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
2153 future_(),
|
Chris@16
|
2154 #else
|
Chris@16
|
2155 future_(new detail::shared_state<R&>()),
|
Chris@16
|
2156 #endif
|
Chris@16
|
2157 future_obtained(false)
|
Chris@16
|
2158 {}
|
Chris@16
|
2159
|
Chris@16
|
2160 ~promise()
|
Chris@16
|
2161 {
|
Chris@16
|
2162 if(future_)
|
Chris@16
|
2163 {
|
Chris@16
|
2164 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2165
|
Chris@16
|
2166 if(!future_->done && !future_->is_constructed)
|
Chris@16
|
2167 {
|
Chris@16
|
2168 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
|
Chris@16
|
2169 }
|
Chris@16
|
2170 }
|
Chris@16
|
2171 }
|
Chris@16
|
2172
|
Chris@16
|
2173 // Assignment
|
Chris@16
|
2174 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
|
Chris@16
|
2175 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
|
Chris@16
|
2176 {
|
Chris@16
|
2177 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2178 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2179 }
|
Chris@16
|
2180 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
|
Chris@16
|
2181 {
|
Chris@16
|
2182 future_=BOOST_THREAD_RV(rhs).future_;
|
Chris@16
|
2183 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
|
Chris@16
|
2184 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2185 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2186 return *this;
|
Chris@16
|
2187 }
|
Chris@16
|
2188
|
Chris@16
|
2189 void swap(promise& other)
|
Chris@16
|
2190 {
|
Chris@16
|
2191 future_.swap(other.future_);
|
Chris@16
|
2192 std::swap(future_obtained,other.future_obtained);
|
Chris@16
|
2193 }
|
Chris@16
|
2194
|
Chris@16
|
2195 // Result retrieval
|
Chris@16
|
2196 BOOST_THREAD_FUTURE<R&> get_future()
|
Chris@16
|
2197 {
|
Chris@16
|
2198 lazy_init();
|
Chris@16
|
2199 if (future_.get()==0)
|
Chris@16
|
2200 {
|
Chris@16
|
2201 boost::throw_exception(promise_moved());
|
Chris@16
|
2202 }
|
Chris@16
|
2203 if (future_obtained)
|
Chris@16
|
2204 {
|
Chris@16
|
2205 boost::throw_exception(future_already_retrieved());
|
Chris@16
|
2206 }
|
Chris@16
|
2207 future_obtained=true;
|
Chris@16
|
2208 return BOOST_THREAD_FUTURE<R&>(future_);
|
Chris@16
|
2209 }
|
Chris@16
|
2210
|
Chris@16
|
2211 void set_value(R& r)
|
Chris@16
|
2212 {
|
Chris@16
|
2213 lazy_init();
|
Chris@16
|
2214 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2215 if(future_->done)
|
Chris@16
|
2216 {
|
Chris@16
|
2217 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2218 }
|
Chris@16
|
2219 future_->mark_finished_with_result_internal(r, lock);
|
Chris@16
|
2220 }
|
Chris@16
|
2221
|
Chris@16
|
2222 void set_exception(boost::exception_ptr p)
|
Chris@16
|
2223 {
|
Chris@16
|
2224 lazy_init();
|
Chris@16
|
2225 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2226 if(future_->done)
|
Chris@16
|
2227 {
|
Chris@16
|
2228 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2229 }
|
Chris@16
|
2230 future_->mark_exceptional_finish_internal(p, lock);
|
Chris@16
|
2231 }
|
Chris@16
|
2232 template <typename E>
|
Chris@16
|
2233 void set_exception(E ex)
|
Chris@16
|
2234 {
|
Chris@101
|
2235 set_exception(boost::copy_exception(ex));
|
Chris@16
|
2236 }
|
Chris@16
|
2237
|
Chris@16
|
2238 // setting the result with deferred notification
|
Chris@16
|
2239 void set_value_at_thread_exit(R& r)
|
Chris@16
|
2240 {
|
Chris@16
|
2241 if (future_.get()==0)
|
Chris@16
|
2242 {
|
Chris@16
|
2243 boost::throw_exception(promise_moved());
|
Chris@16
|
2244 }
|
Chris@16
|
2245 future_->set_value_at_thread_exit(r);
|
Chris@16
|
2246 }
|
Chris@16
|
2247
|
Chris@16
|
2248 void set_exception_at_thread_exit(exception_ptr e)
|
Chris@16
|
2249 {
|
Chris@16
|
2250 if (future_.get()==0)
|
Chris@16
|
2251 {
|
Chris@16
|
2252 boost::throw_exception(promise_moved());
|
Chris@16
|
2253 }
|
Chris@16
|
2254 future_->set_exception_at_thread_exit(e);
|
Chris@16
|
2255 }
|
Chris@16
|
2256 template <typename E>
|
Chris@16
|
2257 void set_exception_at_thread_exit(E ex)
|
Chris@16
|
2258 {
|
Chris@101
|
2259 set_exception_at_thread_exit(boost::copy_exception(ex));
|
Chris@16
|
2260 }
|
Chris@16
|
2261
|
Chris@16
|
2262 template<typename F>
|
Chris@16
|
2263 void set_wait_callback(F f)
|
Chris@16
|
2264 {
|
Chris@16
|
2265 lazy_init();
|
Chris@16
|
2266 future_->set_wait_callback(f,this);
|
Chris@16
|
2267 }
|
Chris@16
|
2268 };
|
Chris@101
|
2269
|
Chris@16
|
2270 template <>
|
Chris@16
|
2271 class promise<void>
|
Chris@16
|
2272 {
|
Chris@16
|
2273 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr;
|
Chris@16
|
2274
|
Chris@16
|
2275 future_ptr future_;
|
Chris@16
|
2276 bool future_obtained;
|
Chris@16
|
2277
|
Chris@16
|
2278 void lazy_init()
|
Chris@16
|
2279 {
|
Chris@16
|
2280 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
2281 if(!atomic_load(&future_))
|
Chris@16
|
2282 {
|
Chris@16
|
2283 future_ptr blank;
|
Chris@16
|
2284 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>));
|
Chris@16
|
2285 }
|
Chris@16
|
2286 #endif
|
Chris@16
|
2287 }
|
Chris@16
|
2288 public:
|
Chris@16
|
2289 BOOST_THREAD_MOVABLE_ONLY(promise)
|
Chris@16
|
2290
|
Chris@16
|
2291 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
2292 template <class Allocator>
|
Chris@16
|
2293 promise(boost::allocator_arg_t, Allocator a)
|
Chris@16
|
2294 {
|
Chris@16
|
2295 typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2;
|
Chris@16
|
2296 A2 a2(a);
|
Chris@16
|
2297 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
2298
|
Chris@16
|
2299 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
|
Chris@16
|
2300 future_obtained = false;
|
Chris@16
|
2301 }
|
Chris@16
|
2302 #endif
|
Chris@16
|
2303 promise():
|
Chris@16
|
2304 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
2305 future_(),
|
Chris@16
|
2306 #else
|
Chris@16
|
2307 future_(new detail::shared_state<void>),
|
Chris@16
|
2308 #endif
|
Chris@16
|
2309 future_obtained(false)
|
Chris@16
|
2310 {}
|
Chris@16
|
2311
|
Chris@16
|
2312 ~promise()
|
Chris@16
|
2313 {
|
Chris@16
|
2314 if(future_)
|
Chris@16
|
2315 {
|
Chris@16
|
2316 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2317
|
Chris@16
|
2318 if(!future_->done && !future_->is_constructed)
|
Chris@16
|
2319 {
|
Chris@16
|
2320 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
|
Chris@16
|
2321 }
|
Chris@16
|
2322 }
|
Chris@16
|
2323 }
|
Chris@16
|
2324
|
Chris@16
|
2325 // Assignment
|
Chris@16
|
2326 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
|
Chris@16
|
2327 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
|
Chris@16
|
2328 {
|
Chris@16
|
2329 // we need to release the future as shared_ptr doesn't implements move semantics
|
Chris@16
|
2330 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2331 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2332 }
|
Chris@16
|
2333
|
Chris@16
|
2334 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
|
Chris@16
|
2335 {
|
Chris@16
|
2336 future_=BOOST_THREAD_RV(rhs).future_;
|
Chris@16
|
2337 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
|
Chris@16
|
2338 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2339 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2340 return *this;
|
Chris@16
|
2341 }
|
Chris@16
|
2342
|
Chris@16
|
2343 void swap(promise& other)
|
Chris@16
|
2344 {
|
Chris@16
|
2345 future_.swap(other.future_);
|
Chris@16
|
2346 std::swap(future_obtained,other.future_obtained);
|
Chris@16
|
2347 }
|
Chris@16
|
2348
|
Chris@16
|
2349 // Result retrieval
|
Chris@16
|
2350 BOOST_THREAD_FUTURE<void> get_future()
|
Chris@16
|
2351 {
|
Chris@16
|
2352 lazy_init();
|
Chris@16
|
2353
|
Chris@16
|
2354 if (future_.get()==0)
|
Chris@16
|
2355 {
|
Chris@16
|
2356 boost::throw_exception(promise_moved());
|
Chris@16
|
2357 }
|
Chris@16
|
2358 if(future_obtained)
|
Chris@16
|
2359 {
|
Chris@16
|
2360 boost::throw_exception(future_already_retrieved());
|
Chris@16
|
2361 }
|
Chris@16
|
2362 future_obtained=true;
|
Chris@101
|
2363 //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<void>(future_));
|
Chris@16
|
2364 return BOOST_THREAD_FUTURE<void>(future_);
|
Chris@16
|
2365 }
|
Chris@16
|
2366
|
Chris@16
|
2367 void set_value()
|
Chris@16
|
2368 {
|
Chris@16
|
2369 lazy_init();
|
Chris@16
|
2370 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2371 if(future_->done)
|
Chris@16
|
2372 {
|
Chris@16
|
2373 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2374 }
|
Chris@16
|
2375 future_->mark_finished_with_result_internal(lock);
|
Chris@16
|
2376 }
|
Chris@16
|
2377
|
Chris@16
|
2378 void set_exception(boost::exception_ptr p)
|
Chris@16
|
2379 {
|
Chris@16
|
2380 lazy_init();
|
Chris@16
|
2381 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2382 if(future_->done)
|
Chris@16
|
2383 {
|
Chris@16
|
2384 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2385 }
|
Chris@16
|
2386 future_->mark_exceptional_finish_internal(p,lock);
|
Chris@16
|
2387 }
|
Chris@16
|
2388 template <typename E>
|
Chris@16
|
2389 void set_exception(E ex)
|
Chris@16
|
2390 {
|
Chris@101
|
2391 set_exception(boost::copy_exception(ex));
|
Chris@16
|
2392 }
|
Chris@16
|
2393
|
Chris@16
|
2394 // setting the result with deferred notification
|
Chris@16
|
2395 void set_value_at_thread_exit()
|
Chris@16
|
2396 {
|
Chris@16
|
2397 if (future_.get()==0)
|
Chris@16
|
2398 {
|
Chris@16
|
2399 boost::throw_exception(promise_moved());
|
Chris@16
|
2400 }
|
Chris@16
|
2401 future_->set_value_at_thread_exit();
|
Chris@16
|
2402 }
|
Chris@16
|
2403
|
Chris@16
|
2404 void set_exception_at_thread_exit(exception_ptr e)
|
Chris@16
|
2405 {
|
Chris@16
|
2406 if (future_.get()==0)
|
Chris@16
|
2407 {
|
Chris@16
|
2408 boost::throw_exception(promise_moved());
|
Chris@16
|
2409 }
|
Chris@16
|
2410 future_->set_exception_at_thread_exit(e);
|
Chris@16
|
2411 }
|
Chris@16
|
2412 template <typename E>
|
Chris@16
|
2413 void set_exception_at_thread_exit(E ex)
|
Chris@16
|
2414 {
|
Chris@101
|
2415 set_exception_at_thread_exit(boost::copy_exception(ex));
|
Chris@16
|
2416 }
|
Chris@16
|
2417
|
Chris@16
|
2418 template<typename F>
|
Chris@16
|
2419 void set_wait_callback(F f)
|
Chris@16
|
2420 {
|
Chris@16
|
2421 lazy_init();
|
Chris@16
|
2422 future_->set_wait_callback(f,this);
|
Chris@16
|
2423 }
|
Chris@16
|
2424
|
Chris@16
|
2425 };
|
Chris@101
|
2426 }
|
Chris@16
|
2427 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@101
|
2428 namespace boost { namespace container {
|
Chris@101
|
2429 template <class R, class Alloc>
|
Chris@101
|
2430 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
|
Chris@16
|
2431 {
|
Chris@101
|
2432 };
|
Chris@101
|
2433 }}
|
Chris@101
|
2434 #if ! defined BOOST_NO_CXX11_ALLOCATOR
|
Chris@101
|
2435 namespace std {
|
Chris@101
|
2436 template <class R, class Alloc>
|
Chris@101
|
2437 struct uses_allocator< ::boost::promise<R> , Alloc> : true_type
|
Chris@101
|
2438 {
|
Chris@101
|
2439 };
|
Chris@101
|
2440 }
|
Chris@16
|
2441 #endif
|
Chris@101
|
2442 #endif
|
Chris@101
|
2443
|
Chris@101
|
2444 namespace boost
|
Chris@101
|
2445 {
|
Chris@16
|
2446
|
Chris@16
|
2447 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@16
|
2448
|
Chris@16
|
2449 namespace detail
|
Chris@16
|
2450 {
|
Chris@16
|
2451 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2452 template<typename R>
|
Chris@16
|
2453 struct task_base_shared_state;
|
Chris@16
|
2454 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2455 template<typename R, typename ...ArgTypes>
|
Chris@16
|
2456 struct task_base_shared_state<R(ArgTypes...)>:
|
Chris@16
|
2457 #else
|
Chris@16
|
2458 template<typename R>
|
Chris@16
|
2459 struct task_base_shared_state<R()>:
|
Chris@16
|
2460 #endif
|
Chris@16
|
2461 #else
|
Chris@16
|
2462 template<typename R>
|
Chris@16
|
2463 struct task_base_shared_state:
|
Chris@16
|
2464 #endif
|
Chris@16
|
2465 detail::shared_state<R>
|
Chris@16
|
2466 {
|
Chris@16
|
2467 bool started;
|
Chris@16
|
2468
|
Chris@16
|
2469 task_base_shared_state():
|
Chris@16
|
2470 started(false)
|
Chris@16
|
2471 {}
|
Chris@16
|
2472
|
Chris@16
|
2473 void reset()
|
Chris@16
|
2474 {
|
Chris@101
|
2475 // todo The packaged_task::reset must be as if an assignemnt froma new packaged_task with the same function
|
Chris@101
|
2476 // the reset function is an optimization that avoids reallocating a new task.
|
Chris@16
|
2477 started=false;
|
Chris@101
|
2478 this->validate();
|
Chris@16
|
2479 }
|
Chris@16
|
2480 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2481 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
|
Chris@16
|
2482 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2483 #else
|
Chris@16
|
2484 virtual void do_run()=0;
|
Chris@16
|
2485 void run()
|
Chris@16
|
2486 #endif
|
Chris@16
|
2487 {
|
Chris@16
|
2488 {
|
Chris@16
|
2489 boost::lock_guard<boost::mutex> lk(this->mutex);
|
Chris@16
|
2490 if(started)
|
Chris@16
|
2491 {
|
Chris@16
|
2492 boost::throw_exception(task_already_started());
|
Chris@16
|
2493 }
|
Chris@16
|
2494 started=true;
|
Chris@16
|
2495 }
|
Chris@16
|
2496 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
2497 do_run(boost::move(args)...);
|
Chris@16
|
2498 #else
|
Chris@16
|
2499 do_run();
|
Chris@16
|
2500 #endif
|
Chris@16
|
2501 }
|
Chris@16
|
2502
|
Chris@16
|
2503 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2504 virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
|
Chris@16
|
2505 void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2506 #else
|
Chris@16
|
2507 virtual void do_apply()=0;
|
Chris@16
|
2508 void apply()
|
Chris@16
|
2509 #endif
|
Chris@16
|
2510 {
|
Chris@16
|
2511 {
|
Chris@16
|
2512 boost::lock_guard<boost::mutex> lk(this->mutex);
|
Chris@16
|
2513 if(started)
|
Chris@16
|
2514 {
|
Chris@16
|
2515 boost::throw_exception(task_already_started());
|
Chris@16
|
2516 }
|
Chris@16
|
2517 started=true;
|
Chris@16
|
2518 }
|
Chris@16
|
2519 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
2520 do_apply(boost::move(args)...);
|
Chris@16
|
2521 #else
|
Chris@16
|
2522 do_apply();
|
Chris@16
|
2523 #endif
|
Chris@16
|
2524 }
|
Chris@16
|
2525
|
Chris@16
|
2526 void owner_destroyed()
|
Chris@16
|
2527 {
|
Chris@16
|
2528 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
2529 if(!started)
|
Chris@16
|
2530 {
|
Chris@16
|
2531 started=true;
|
Chris@16
|
2532 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
|
Chris@16
|
2533 }
|
Chris@16
|
2534 }
|
Chris@16
|
2535 };
|
Chris@16
|
2536
|
Chris@16
|
2537 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2538 template<typename F, typename R>
|
Chris@16
|
2539 struct task_shared_state;
|
Chris@16
|
2540 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2541 template<typename F, typename R, typename ...ArgTypes>
|
Chris@16
|
2542 struct task_shared_state<F, R(ArgTypes...)>:
|
Chris@16
|
2543 task_base_shared_state<R(ArgTypes...)>
|
Chris@16
|
2544 #else
|
Chris@16
|
2545 template<typename F, typename R>
|
Chris@16
|
2546 struct task_shared_state<F, R()>:
|
Chris@16
|
2547 task_base_shared_state<R()>
|
Chris@16
|
2548 #endif
|
Chris@16
|
2549 #else
|
Chris@16
|
2550 template<typename F, typename R>
|
Chris@16
|
2551 struct task_shared_state:
|
Chris@16
|
2552 task_base_shared_state<R>
|
Chris@16
|
2553 #endif
|
Chris@16
|
2554 {
|
Chris@16
|
2555 private:
|
Chris@16
|
2556 task_shared_state(task_shared_state&);
|
Chris@16
|
2557 public:
|
Chris@16
|
2558 F f;
|
Chris@16
|
2559 task_shared_state(F const& f_):
|
Chris@16
|
2560 f(f_)
|
Chris@16
|
2561 {}
|
Chris@16
|
2562 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
|
Chris@16
|
2563 f(boost::move(f_))
|
Chris@16
|
2564 {}
|
Chris@16
|
2565
|
Chris@101
|
2566 F callable()
|
Chris@101
|
2567 {
|
Chris@101
|
2568 return boost::move(f);
|
Chris@101
|
2569 }
|
Chris@101
|
2570
|
Chris@16
|
2571 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2572 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2573 {
|
Chris@16
|
2574 try
|
Chris@16
|
2575 {
|
Chris@101
|
2576 this->set_value_at_thread_exit(f(boost::move(args)...));
|
Chris@16
|
2577 }
|
Chris@16
|
2578 #else
|
Chris@16
|
2579 void do_apply()
|
Chris@16
|
2580 {
|
Chris@16
|
2581 try
|
Chris@16
|
2582 {
|
Chris@16
|
2583 this->set_value_at_thread_exit(f());
|
Chris@16
|
2584 }
|
Chris@16
|
2585 #endif
|
Chris@16
|
2586 catch(...)
|
Chris@16
|
2587 {
|
Chris@16
|
2588 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2589 }
|
Chris@16
|
2590 }
|
Chris@16
|
2591
|
Chris@16
|
2592 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2593 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2594 {
|
Chris@16
|
2595 try
|
Chris@16
|
2596 {
|
Chris@101
|
2597 this->mark_finished_with_result(f(boost::move(args)...));
|
Chris@16
|
2598 }
|
Chris@16
|
2599 #else
|
Chris@16
|
2600 void do_run()
|
Chris@16
|
2601 {
|
Chris@16
|
2602 try
|
Chris@16
|
2603 {
|
Chris@16
|
2604 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2605 R res((f()));
|
Chris@16
|
2606 this->mark_finished_with_result(boost::move(res));
|
Chris@16
|
2607 #else
|
Chris@16
|
2608 this->mark_finished_with_result(f());
|
Chris@16
|
2609 #endif
|
Chris@16
|
2610 }
|
Chris@16
|
2611 #endif
|
Chris@16
|
2612 catch(...)
|
Chris@16
|
2613 {
|
Chris@16
|
2614 this->mark_exceptional_finish();
|
Chris@16
|
2615 }
|
Chris@16
|
2616 }
|
Chris@16
|
2617 };
|
Chris@16
|
2618
|
Chris@16
|
2619 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2620 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2621 template<typename F, typename R, typename ...ArgTypes>
|
Chris@16
|
2622 struct task_shared_state<F, R&(ArgTypes...)>:
|
Chris@16
|
2623 task_base_shared_state<R&(ArgTypes...)>
|
Chris@16
|
2624 #else
|
Chris@16
|
2625 template<typename F, typename R>
|
Chris@16
|
2626 struct task_shared_state<F, R&()>:
|
Chris@16
|
2627 task_base_shared_state<R&()>
|
Chris@16
|
2628 #endif
|
Chris@16
|
2629 #else
|
Chris@16
|
2630 template<typename F, typename R>
|
Chris@16
|
2631 struct task_shared_state<F,R&>:
|
Chris@16
|
2632 task_base_shared_state<R&>
|
Chris@16
|
2633 #endif
|
Chris@16
|
2634 {
|
Chris@16
|
2635 private:
|
Chris@16
|
2636 task_shared_state(task_shared_state&);
|
Chris@16
|
2637 public:
|
Chris@16
|
2638 F f;
|
Chris@16
|
2639 task_shared_state(F const& f_):
|
Chris@16
|
2640 f(f_)
|
Chris@16
|
2641 {}
|
Chris@16
|
2642 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
|
Chris@16
|
2643 f(boost::move(f_))
|
Chris@16
|
2644 {}
|
Chris@16
|
2645
|
Chris@101
|
2646 F callable()
|
Chris@101
|
2647 {
|
Chris@101
|
2648 return f;
|
Chris@101
|
2649 }
|
Chris@101
|
2650
|
Chris@16
|
2651 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2652 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2653 {
|
Chris@16
|
2654 try
|
Chris@16
|
2655 {
|
Chris@101
|
2656 this->set_value_at_thread_exit(f(boost::move(args)...));
|
Chris@16
|
2657 }
|
Chris@16
|
2658 #else
|
Chris@16
|
2659 void do_apply()
|
Chris@16
|
2660 {
|
Chris@16
|
2661 try
|
Chris@16
|
2662 {
|
Chris@16
|
2663 this->set_value_at_thread_exit(f());
|
Chris@16
|
2664 }
|
Chris@16
|
2665 #endif
|
Chris@16
|
2666 catch(...)
|
Chris@16
|
2667 {
|
Chris@16
|
2668 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2669 }
|
Chris@16
|
2670 }
|
Chris@16
|
2671
|
Chris@16
|
2672 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2673 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2674 {
|
Chris@16
|
2675 try
|
Chris@16
|
2676 {
|
Chris@101
|
2677 this->mark_finished_with_result(f(boost::move(args)...));
|
Chris@16
|
2678 }
|
Chris@16
|
2679 #else
|
Chris@16
|
2680 void do_run()
|
Chris@16
|
2681 {
|
Chris@16
|
2682 try
|
Chris@16
|
2683 {
|
Chris@16
|
2684 R& res((f()));
|
Chris@16
|
2685 this->mark_finished_with_result(res);
|
Chris@16
|
2686 }
|
Chris@16
|
2687 #endif
|
Chris@16
|
2688 catch(...)
|
Chris@16
|
2689 {
|
Chris@16
|
2690 this->mark_exceptional_finish();
|
Chris@16
|
2691 }
|
Chris@16
|
2692 }
|
Chris@16
|
2693 };
|
Chris@16
|
2694
|
Chris@16
|
2695 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
2696
|
Chris@16
|
2697 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2698 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2699 template<typename R, typename ...ArgTypes>
|
Chris@16
|
2700 struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>:
|
Chris@16
|
2701 task_base_shared_state<R(ArgTypes...)>
|
Chris@16
|
2702 #else
|
Chris@16
|
2703 template<typename R>
|
Chris@16
|
2704 struct task_shared_state<R (*)(), R()>:
|
Chris@16
|
2705 task_base_shared_state<R()>
|
Chris@16
|
2706 #endif
|
Chris@16
|
2707 #else
|
Chris@16
|
2708 template<typename R>
|
Chris@16
|
2709 struct task_shared_state<R (*)(), R> :
|
Chris@16
|
2710 task_base_shared_state<R>
|
Chris@16
|
2711 #endif
|
Chris@16
|
2712 {
|
Chris@16
|
2713 private:
|
Chris@16
|
2714 task_shared_state(task_shared_state&);
|
Chris@101
|
2715 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
2716 typedef R (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... );
|
Chris@101
|
2717 #else
|
Chris@101
|
2718 typedef R (*CallableType)();
|
Chris@101
|
2719 #endif
|
Chris@16
|
2720 public:
|
Chris@101
|
2721 CallableType f;
|
Chris@101
|
2722 task_shared_state(CallableType f_):
|
Chris@16
|
2723 f(f_)
|
Chris@16
|
2724 {}
|
Chris@16
|
2725
|
Chris@101
|
2726 CallableType callable()
|
Chris@101
|
2727 {
|
Chris@101
|
2728 return f;
|
Chris@101
|
2729 }
|
Chris@16
|
2730
|
Chris@16
|
2731 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2732 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2733 {
|
Chris@16
|
2734 try
|
Chris@16
|
2735 {
|
Chris@101
|
2736 this->set_value_at_thread_exit(f(boost::move(args)...));
|
Chris@16
|
2737 }
|
Chris@16
|
2738 #else
|
Chris@16
|
2739 void do_apply()
|
Chris@16
|
2740 {
|
Chris@16
|
2741 try
|
Chris@16
|
2742 {
|
Chris@16
|
2743 R r((f()));
|
Chris@16
|
2744 this->set_value_at_thread_exit(boost::move(r));
|
Chris@16
|
2745 }
|
Chris@16
|
2746 #endif
|
Chris@16
|
2747 catch(...)
|
Chris@16
|
2748 {
|
Chris@16
|
2749 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2750 }
|
Chris@16
|
2751 }
|
Chris@16
|
2752
|
Chris@16
|
2753
|
Chris@16
|
2754 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2755 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2756 {
|
Chris@16
|
2757 try
|
Chris@16
|
2758 {
|
Chris@101
|
2759 this->mark_finished_with_result(f(boost::move(args)...));
|
Chris@16
|
2760 }
|
Chris@16
|
2761 #else
|
Chris@16
|
2762 void do_run()
|
Chris@16
|
2763 {
|
Chris@16
|
2764 try
|
Chris@16
|
2765 {
|
Chris@16
|
2766 R res((f()));
|
Chris@16
|
2767 this->mark_finished_with_result(boost::move(res));
|
Chris@16
|
2768 }
|
Chris@16
|
2769 #endif
|
Chris@16
|
2770 catch(...)
|
Chris@16
|
2771 {
|
Chris@16
|
2772 this->mark_exceptional_finish();
|
Chris@16
|
2773 }
|
Chris@16
|
2774 }
|
Chris@16
|
2775 };
|
Chris@16
|
2776 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2777 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2778 template<typename R, typename ...ArgTypes>
|
Chris@16
|
2779 struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>:
|
Chris@16
|
2780 task_base_shared_state<R&(ArgTypes...)>
|
Chris@16
|
2781 #else
|
Chris@16
|
2782 template<typename R>
|
Chris@16
|
2783 struct task_shared_state<R& (*)(), R&()>:
|
Chris@16
|
2784 task_base_shared_state<R&()>
|
Chris@16
|
2785 #endif
|
Chris@16
|
2786 #else
|
Chris@16
|
2787 template<typename R>
|
Chris@16
|
2788 struct task_shared_state<R& (*)(), R&> :
|
Chris@16
|
2789 task_base_shared_state<R&>
|
Chris@16
|
2790 #endif
|
Chris@16
|
2791 {
|
Chris@16
|
2792 private:
|
Chris@16
|
2793 task_shared_state(task_shared_state&);
|
Chris@16
|
2794 public:
|
Chris@101
|
2795 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
2796 typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... );
|
Chris@101
|
2797 #else
|
Chris@101
|
2798 typedef R& (*CallableType)();
|
Chris@101
|
2799 #endif
|
Chris@101
|
2800 CallableType f;
|
Chris@101
|
2801 task_shared_state(CallableType f_):
|
Chris@16
|
2802 f(f_)
|
Chris@16
|
2803 {}
|
Chris@16
|
2804
|
Chris@101
|
2805 CallableType callable()
|
Chris@101
|
2806 {
|
Chris@101
|
2807 return boost::move(f);
|
Chris@101
|
2808 }
|
Chris@16
|
2809
|
Chris@16
|
2810 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2811 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2812 {
|
Chris@16
|
2813 try
|
Chris@16
|
2814 {
|
Chris@101
|
2815 this->set_value_at_thread_exit(f(boost::move(args)...));
|
Chris@16
|
2816 }
|
Chris@16
|
2817 #else
|
Chris@16
|
2818 void do_apply()
|
Chris@16
|
2819 {
|
Chris@16
|
2820 try
|
Chris@16
|
2821 {
|
Chris@16
|
2822 this->set_value_at_thread_exit(f());
|
Chris@16
|
2823 }
|
Chris@16
|
2824 #endif
|
Chris@16
|
2825 catch(...)
|
Chris@16
|
2826 {
|
Chris@16
|
2827 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2828 }
|
Chris@16
|
2829 }
|
Chris@16
|
2830
|
Chris@16
|
2831
|
Chris@16
|
2832 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2833 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2834 {
|
Chris@16
|
2835 try
|
Chris@16
|
2836 {
|
Chris@101
|
2837 this->mark_finished_with_result(f(boost::move(args)...));
|
Chris@16
|
2838 }
|
Chris@16
|
2839 #else
|
Chris@16
|
2840 void do_run()
|
Chris@16
|
2841 {
|
Chris@16
|
2842 try
|
Chris@16
|
2843 {
|
Chris@16
|
2844 this->mark_finished_with_result(f());
|
Chris@16
|
2845 }
|
Chris@16
|
2846 #endif
|
Chris@16
|
2847 catch(...)
|
Chris@16
|
2848 {
|
Chris@16
|
2849 this->mark_exceptional_finish();
|
Chris@16
|
2850 }
|
Chris@16
|
2851 }
|
Chris@16
|
2852 };
|
Chris@16
|
2853 #endif
|
Chris@16
|
2854 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2855 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2856 template<typename F, typename ...ArgTypes>
|
Chris@16
|
2857 struct task_shared_state<F, void(ArgTypes...)>:
|
Chris@16
|
2858 task_base_shared_state<void(ArgTypes...)>
|
Chris@16
|
2859 #else
|
Chris@16
|
2860 template<typename F>
|
Chris@16
|
2861 struct task_shared_state<F, void()>:
|
Chris@16
|
2862 task_base_shared_state<void()>
|
Chris@16
|
2863 #endif
|
Chris@16
|
2864 #else
|
Chris@16
|
2865 template<typename F>
|
Chris@16
|
2866 struct task_shared_state<F,void>:
|
Chris@16
|
2867 task_base_shared_state<void>
|
Chris@16
|
2868 #endif
|
Chris@16
|
2869 {
|
Chris@16
|
2870 private:
|
Chris@16
|
2871 task_shared_state(task_shared_state&);
|
Chris@16
|
2872 public:
|
Chris@101
|
2873 typedef F CallableType;
|
Chris@16
|
2874 F f;
|
Chris@16
|
2875 task_shared_state(F const& f_):
|
Chris@16
|
2876 f(f_)
|
Chris@16
|
2877 {}
|
Chris@16
|
2878 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
|
Chris@16
|
2879 f(boost::move(f_))
|
Chris@16
|
2880 {}
|
Chris@101
|
2881 F callable()
|
Chris@101
|
2882 {
|
Chris@101
|
2883 return boost::move(f);
|
Chris@101
|
2884 }
|
Chris@16
|
2885 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2886 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2887 {
|
Chris@16
|
2888 try
|
Chris@16
|
2889 {
|
Chris@101
|
2890 f(boost::move(args)...);
|
Chris@16
|
2891 #else
|
Chris@16
|
2892 void do_apply()
|
Chris@16
|
2893 {
|
Chris@16
|
2894 try
|
Chris@16
|
2895 {
|
Chris@16
|
2896 f();
|
Chris@16
|
2897 #endif
|
Chris@16
|
2898 this->set_value_at_thread_exit();
|
Chris@16
|
2899 }
|
Chris@16
|
2900 catch(...)
|
Chris@16
|
2901 {
|
Chris@16
|
2902 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2903 }
|
Chris@16
|
2904 }
|
Chris@16
|
2905
|
Chris@16
|
2906 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2907 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2908 {
|
Chris@16
|
2909 try
|
Chris@16
|
2910 {
|
Chris@101
|
2911 f(boost::move(args)...);
|
Chris@16
|
2912 #else
|
Chris@16
|
2913 void do_run()
|
Chris@16
|
2914 {
|
Chris@16
|
2915 try
|
Chris@16
|
2916 {
|
Chris@16
|
2917 f();
|
Chris@16
|
2918 #endif
|
Chris@16
|
2919 this->mark_finished_with_result();
|
Chris@16
|
2920 }
|
Chris@16
|
2921 catch(...)
|
Chris@16
|
2922 {
|
Chris@16
|
2923 this->mark_exceptional_finish();
|
Chris@16
|
2924 }
|
Chris@16
|
2925 }
|
Chris@16
|
2926 };
|
Chris@16
|
2927
|
Chris@16
|
2928 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2929 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2930 template<typename ...ArgTypes>
|
Chris@16
|
2931 struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>:
|
Chris@16
|
2932 task_base_shared_state<void(ArgTypes...)>
|
Chris@16
|
2933 #else
|
Chris@16
|
2934 template<>
|
Chris@16
|
2935 struct task_shared_state<void (*)(), void()>:
|
Chris@16
|
2936 task_base_shared_state<void()>
|
Chris@16
|
2937 #endif
|
Chris@16
|
2938 #else
|
Chris@16
|
2939 template<>
|
Chris@16
|
2940 struct task_shared_state<void (*)(),void>:
|
Chris@16
|
2941 task_base_shared_state<void>
|
Chris@16
|
2942 #endif
|
Chris@16
|
2943 {
|
Chris@16
|
2944 private:
|
Chris@16
|
2945 task_shared_state(task_shared_state&);
|
Chris@101
|
2946 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
2947 typedef void (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes)...);
|
Chris@101
|
2948 #else
|
Chris@101
|
2949 typedef void (*CallableType)();
|
Chris@101
|
2950 #endif
|
Chris@16
|
2951 public:
|
Chris@101
|
2952 CallableType f;
|
Chris@101
|
2953 task_shared_state(CallableType f_):
|
Chris@16
|
2954 f(f_)
|
Chris@16
|
2955 {}
|
Chris@101
|
2956 CallableType callable()
|
Chris@101
|
2957 {
|
Chris@101
|
2958 return f;
|
Chris@101
|
2959 }
|
Chris@16
|
2960 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2961 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2962 {
|
Chris@16
|
2963 try
|
Chris@16
|
2964 {
|
Chris@101
|
2965 f(boost::move(args)...);
|
Chris@16
|
2966 #else
|
Chris@16
|
2967 void do_apply()
|
Chris@16
|
2968 {
|
Chris@16
|
2969 try
|
Chris@16
|
2970 {
|
Chris@16
|
2971 f();
|
Chris@16
|
2972 #endif
|
Chris@16
|
2973 this->set_value_at_thread_exit();
|
Chris@16
|
2974 }
|
Chris@16
|
2975 catch(...)
|
Chris@16
|
2976 {
|
Chris@16
|
2977 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2978 }
|
Chris@16
|
2979 }
|
Chris@16
|
2980
|
Chris@16
|
2981 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2982 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2983 {
|
Chris@16
|
2984 try
|
Chris@16
|
2985 {
|
Chris@101
|
2986 f(boost::move(args)...);
|
Chris@16
|
2987 #else
|
Chris@16
|
2988 void do_run()
|
Chris@16
|
2989 {
|
Chris@16
|
2990 try
|
Chris@16
|
2991 {
|
Chris@16
|
2992 f();
|
Chris@16
|
2993 #endif
|
Chris@16
|
2994 this->mark_finished_with_result();
|
Chris@16
|
2995 }
|
Chris@16
|
2996 catch(...)
|
Chris@16
|
2997 {
|
Chris@16
|
2998 this->mark_exceptional_finish();
|
Chris@16
|
2999 }
|
Chris@16
|
3000 }
|
Chris@16
|
3001 };
|
Chris@16
|
3002 }
|
Chris@16
|
3003
|
Chris@16
|
3004 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3005 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3006 template<typename R, typename ...ArgTypes>
|
Chris@16
|
3007 class packaged_task<R(ArgTypes...)>
|
Chris@16
|
3008 {
|
Chris@16
|
3009 typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr;
|
Chris@16
|
3010 boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task;
|
Chris@16
|
3011 #else
|
Chris@16
|
3012 template<typename R>
|
Chris@16
|
3013 class packaged_task<R()>
|
Chris@16
|
3014 {
|
Chris@16
|
3015 typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr;
|
Chris@16
|
3016 boost::shared_ptr<detail::task_base_shared_state<R()> > task;
|
Chris@16
|
3017 #endif
|
Chris@16
|
3018 #else
|
Chris@16
|
3019 template<typename R>
|
Chris@16
|
3020 class packaged_task
|
Chris@16
|
3021 {
|
Chris@16
|
3022 typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr;
|
Chris@16
|
3023 boost::shared_ptr<detail::task_base_shared_state<R> > task;
|
Chris@16
|
3024 #endif
|
Chris@16
|
3025 bool future_obtained;
|
Chris@16
|
3026 struct dummy;
|
Chris@16
|
3027
|
Chris@16
|
3028 public:
|
Chris@16
|
3029 typedef R result_type;
|
Chris@16
|
3030 BOOST_THREAD_MOVABLE_ONLY(packaged_task)
|
Chris@16
|
3031
|
Chris@16
|
3032 packaged_task():
|
Chris@16
|
3033 future_obtained(false)
|
Chris@16
|
3034 {}
|
Chris@16
|
3035
|
Chris@16
|
3036 // construction and destruction
|
Chris@16
|
3037 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
3038
|
Chris@16
|
3039 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3040 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3041 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
|
Chris@16
|
3042 {
|
Chris@16
|
3043 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
|
Chris@16
|
3044 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
|
Chris@101
|
3045 task= task_ptr(new task_shared_state_type(f, boost::move(args)...));
|
Chris@16
|
3046 future_obtained=false;
|
Chris@16
|
3047 }
|
Chris@16
|
3048 #else
|
Chris@16
|
3049 explicit packaged_task(R(*f)())
|
Chris@16
|
3050 {
|
Chris@16
|
3051 typedef R(*FR)();
|
Chris@16
|
3052 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
|
Chris@16
|
3053 task= task_ptr(new task_shared_state_type(f));
|
Chris@16
|
3054 future_obtained=false;
|
Chris@16
|
3055 }
|
Chris@16
|
3056 #endif
|
Chris@16
|
3057 #else
|
Chris@16
|
3058 explicit packaged_task(R(*f)())
|
Chris@16
|
3059 {
|
Chris@16
|
3060 typedef R(*FR)();
|
Chris@16
|
3061 typedef detail::task_shared_state<FR,R> task_shared_state_type;
|
Chris@16
|
3062 task= task_ptr(new task_shared_state_type(f));
|
Chris@16
|
3063 future_obtained=false;
|
Chris@16
|
3064 }
|
Chris@16
|
3065 #endif
|
Chris@16
|
3066 #endif
|
Chris@16
|
3067 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3068 template <class F>
|
Chris@16
|
3069 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
|
Chris@16
|
3070 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
|
Chris@16
|
3071 )
|
Chris@16
|
3072 {
|
Chris@101
|
3073 typedef typename decay<F>::type FR;
|
Chris@16
|
3074 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3075 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3076 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3077 #else
|
Chris@16
|
3078 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
|
Chris@16
|
3079 #endif
|
Chris@16
|
3080 #else
|
Chris@16
|
3081 typedef detail::task_shared_state<FR,R> task_shared_state_type;
|
Chris@16
|
3082 #endif
|
Chris@16
|
3083 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
|
Chris@16
|
3084 future_obtained = false;
|
Chris@16
|
3085
|
Chris@16
|
3086 }
|
Chris@16
|
3087
|
Chris@16
|
3088 #else
|
Chris@16
|
3089 template <class F>
|
Chris@16
|
3090 explicit packaged_task(F const& f
|
Chris@16
|
3091 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
|
Chris@16
|
3092 )
|
Chris@16
|
3093 {
|
Chris@16
|
3094 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3095 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3096 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3097 #else
|
Chris@16
|
3098 typedef detail::task_shared_state<F,R()> task_shared_state_type;
|
Chris@16
|
3099 #endif
|
Chris@16
|
3100 #else
|
Chris@16
|
3101 typedef detail::task_shared_state<F,R> task_shared_state_type;
|
Chris@16
|
3102 #endif
|
Chris@16
|
3103 task = task_ptr(new task_shared_state_type(f));
|
Chris@16
|
3104 future_obtained=false;
|
Chris@16
|
3105 }
|
Chris@16
|
3106 template <class F>
|
Chris@16
|
3107 explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
|
Chris@16
|
3108 {
|
Chris@16
|
3109 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3110 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3111 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
|
Chris@101
|
3112 task = task_ptr(new task_shared_state_type(boost::move(f)));
|
Chris@16
|
3113 #else
|
Chris@16
|
3114 typedef detail::task_shared_state<F,R()> task_shared_state_type;
|
Chris@101
|
3115 task = task_ptr(new task_shared_state_type(boost::move(f)));
|
Chris@16
|
3116 #endif
|
Chris@16
|
3117 #else
|
Chris@16
|
3118 typedef detail::task_shared_state<F,R> task_shared_state_type;
|
Chris@101
|
3119 task = task_ptr(new task_shared_state_type(boost::move(f)));
|
Chris@16
|
3120 #endif
|
Chris@16
|
3121 future_obtained=false;
|
Chris@16
|
3122
|
Chris@16
|
3123 }
|
Chris@16
|
3124 #endif
|
Chris@16
|
3125
|
Chris@16
|
3126 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
3127 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
3128 template <class Allocator>
|
Chris@16
|
3129 packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
|
Chris@16
|
3130 {
|
Chris@16
|
3131 typedef R(*FR)();
|
Chris@16
|
3132 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3133 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3134 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3135 #else
|
Chris@16
|
3136 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
|
Chris@16
|
3137 #endif
|
Chris@16
|
3138 #else
|
Chris@16
|
3139 typedef detail::task_shared_state<FR,R> task_shared_state_type;
|
Chris@16
|
3140 #endif
|
Chris@16
|
3141 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
|
Chris@16
|
3142 A2 a2(a);
|
Chris@16
|
3143 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
3144
|
Chris@16
|
3145 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
|
Chris@16
|
3146 future_obtained = false;
|
Chris@16
|
3147 }
|
Chris@16
|
3148 #endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@16
|
3149
|
Chris@16
|
3150 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3151 template <class F, class Allocator>
|
Chris@16
|
3152 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
|
Chris@16
|
3153 {
|
Chris@101
|
3154 typedef typename decay<F>::type FR;
|
Chris@101
|
3155
|
Chris@16
|
3156 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3157 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3158 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3159 #else
|
Chris@16
|
3160 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
|
Chris@16
|
3161 #endif
|
Chris@16
|
3162 #else
|
Chris@16
|
3163 typedef detail::task_shared_state<FR,R> task_shared_state_type;
|
Chris@16
|
3164 #endif
|
Chris@16
|
3165 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
|
Chris@16
|
3166 A2 a2(a);
|
Chris@16
|
3167 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
3168
|
Chris@16
|
3169 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
|
Chris@16
|
3170 future_obtained = false;
|
Chris@16
|
3171 }
|
Chris@16
|
3172 #else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3173 template <class F, class Allocator>
|
Chris@16
|
3174 packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
|
Chris@16
|
3175 {
|
Chris@16
|
3176 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3177 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3178 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3179 #else
|
Chris@16
|
3180 typedef detail::task_shared_state<F,R()> task_shared_state_type;
|
Chris@16
|
3181 #endif
|
Chris@16
|
3182 #else
|
Chris@16
|
3183 typedef detail::task_shared_state<F,R> task_shared_state_type;
|
Chris@16
|
3184 #endif
|
Chris@16
|
3185 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
|
Chris@16
|
3186 A2 a2(a);
|
Chris@16
|
3187 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
3188
|
Chris@16
|
3189 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
|
Chris@16
|
3190 future_obtained = false;
|
Chris@16
|
3191 }
|
Chris@16
|
3192 template <class F, class Allocator>
|
Chris@16
|
3193 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
|
Chris@16
|
3194 {
|
Chris@16
|
3195 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3196 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3197 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3198 #else
|
Chris@16
|
3199 typedef detail::task_shared_state<F,R()> task_shared_state_type;
|
Chris@16
|
3200 #endif
|
Chris@16
|
3201 #else
|
Chris@16
|
3202 typedef detail::task_shared_state<F,R> task_shared_state_type;
|
Chris@16
|
3203 #endif
|
Chris@16
|
3204 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
|
Chris@16
|
3205 A2 a2(a);
|
Chris@16
|
3206 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
3207
|
Chris@101
|
3208 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) );
|
Chris@16
|
3209 future_obtained = false;
|
Chris@16
|
3210 }
|
Chris@16
|
3211
|
Chris@16
|
3212 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3213 #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
3214
|
Chris@101
|
3215 ~packaged_task() {
|
Chris@101
|
3216 if(task) {
|
Chris@16
|
3217 task->owner_destroyed();
|
Chris@16
|
3218 }
|
Chris@16
|
3219 }
|
Chris@16
|
3220
|
Chris@16
|
3221 // assignment
|
Chris@101
|
3222 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
|
Chris@101
|
3223 : future_obtained(BOOST_THREAD_RV(other).future_obtained) {
|
Chris@16
|
3224 task.swap(BOOST_THREAD_RV(other).task);
|
Chris@16
|
3225 BOOST_THREAD_RV(other).future_obtained=false;
|
Chris@16
|
3226 }
|
Chris@101
|
3227 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT {
|
Chris@101
|
3228
|
Chris@16
|
3229 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3230 packaged_task temp(boost::move(other));
|
Chris@16
|
3231 #else
|
Chris@16
|
3232 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
|
Chris@16
|
3233 #endif
|
Chris@16
|
3234 swap(temp);
|
Chris@16
|
3235 return *this;
|
Chris@16
|
3236 }
|
Chris@16
|
3237
|
Chris@101
|
3238 void reset() {
|
Chris@16
|
3239 if (!valid())
|
Chris@16
|
3240 throw future_error(system::make_error_code(future_errc::no_state));
|
Chris@101
|
3241
|
Chris@101
|
3242 // As if *this = packaged_task(task->callable());
|
Chris@101
|
3243
|
Chris@16
|
3244 task->reset();
|
Chris@16
|
3245 future_obtained=false;
|
Chris@16
|
3246 }
|
Chris@16
|
3247
|
Chris@101
|
3248 void swap(packaged_task& other) BOOST_NOEXCEPT {
|
Chris@16
|
3249 task.swap(other.task);
|
Chris@16
|
3250 std::swap(future_obtained,other.future_obtained);
|
Chris@16
|
3251 }
|
Chris@101
|
3252 bool valid() const BOOST_NOEXCEPT {
|
Chris@16
|
3253 return task.get()!=0;
|
Chris@16
|
3254 }
|
Chris@16
|
3255
|
Chris@16
|
3256 // result retrieval
|
Chris@101
|
3257 BOOST_THREAD_FUTURE<R> get_future() {
|
Chris@101
|
3258 if(!task) {
|
Chris@101
|
3259 boost::throw_exception(task_moved());
|
Chris@101
|
3260 } else if(!future_obtained) {
|
Chris@101
|
3261 future_obtained=true;
|
Chris@101
|
3262 return BOOST_THREAD_FUTURE<R>(task);
|
Chris@101
|
3263 } else {
|
Chris@101
|
3264 boost::throw_exception(future_already_retrieved());
|
Chris@101
|
3265 }
|
Chris@101
|
3266 }
|
Chris@101
|
3267
|
Chris@101
|
3268 // execution
|
Chris@101
|
3269 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
3270 void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args) {
|
Chris@101
|
3271 if(!task) {
|
Chris@16
|
3272 boost::throw_exception(task_moved());
|
Chris@16
|
3273 }
|
Chris@101
|
3274 task->run(boost::move(args)...);
|
Chris@16
|
3275 }
|
Chris@101
|
3276 void make_ready_at_thread_exit(ArgTypes... args) {
|
Chris@101
|
3277 if(!task) {
|
Chris@16
|
3278 boost::throw_exception(task_moved());
|
Chris@16
|
3279 }
|
Chris@101
|
3280 if (task->has_value()) {
|
Chris@16
|
3281 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
3282 }
|
Chris@101
|
3283 task->apply(boost::move(args)...);
|
Chris@16
|
3284 }
|
Chris@16
|
3285 #else
|
Chris@101
|
3286 void operator()() {
|
Chris@101
|
3287 if(!task) {
|
Chris@16
|
3288 boost::throw_exception(task_moved());
|
Chris@16
|
3289 }
|
Chris@16
|
3290 task->run();
|
Chris@16
|
3291 }
|
Chris@101
|
3292 void make_ready_at_thread_exit() {
|
Chris@101
|
3293 if(!task) {
|
Chris@16
|
3294 boost::throw_exception(task_moved());
|
Chris@16
|
3295 }
|
Chris@101
|
3296 if (task->has_value()) boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
3297 task->apply();
|
Chris@16
|
3298 }
|
Chris@16
|
3299 #endif
|
Chris@16
|
3300 template<typename F>
|
Chris@101
|
3301 void set_wait_callback(F f) {
|
Chris@16
|
3302 task->set_wait_callback(f,this);
|
Chris@16
|
3303 }
|
Chris@16
|
3304 };
|
Chris@101
|
3305 }
|
Chris@16
|
3306 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@101
|
3307 namespace boost { namespace container {
|
Chris@101
|
3308 template <class R, class Alloc>
|
Chris@101
|
3309 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
|
Chris@101
|
3310 {};
|
Chris@101
|
3311 }}
|
Chris@101
|
3312 #if ! defined BOOST_NO_CXX11_ALLOCATOR
|
Chris@101
|
3313 namespace std {
|
Chris@101
|
3314 template <class R, class Alloc>
|
Chris@101
|
3315 struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type
|
Chris@101
|
3316 {};
|
Chris@101
|
3317 }
|
Chris@16
|
3318 #endif
|
Chris@101
|
3319 #endif
|
Chris@101
|
3320
|
Chris@101
|
3321 namespace boost
|
Chris@101
|
3322 {
|
Chris@101
|
3323 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@101
|
3324
|
Chris@101
|
3325 namespace detail
|
Chris@101
|
3326 {
|
Chris@101
|
3327 ////////////////////////////////
|
Chris@101
|
3328 // make_future_deferred_shared_state
|
Chris@101
|
3329 ////////////////////////////////
|
Chris@101
|
3330 template <class Rp, class Fp>
|
Chris@101
|
3331 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
3332 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
|
Chris@101
|
3333 shared_ptr<future_deferred_shared_state<Rp, Fp> >
|
Chris@101
|
3334 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
|
Chris@101
|
3335 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@101
|
3336 }
|
Chris@101
|
3337
|
Chris@101
|
3338 ////////////////////////////////
|
Chris@101
|
3339 // make_future_async_shared_state
|
Chris@101
|
3340 ////////////////////////////////
|
Chris@101
|
3341 template <class Rp, class Fp>
|
Chris@101
|
3342 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
3343 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) {
|
Chris@101
|
3344 shared_ptr<future_async_shared_state<Rp, Fp> >
|
Chris@101
|
3345 h(new future_async_shared_state<Rp, Fp>());
|
Chris@101
|
3346 h->init(boost::forward<Fp>(f));
|
Chris@101
|
3347 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@101
|
3348 }
|
Chris@101
|
3349 }
|
Chris@16
|
3350
|
Chris@16
|
3351 ////////////////////////////////
|
Chris@16
|
3352 // template <class F, class... ArgTypes>
|
Chris@16
|
3353 // future<R> async(launch policy, F&&, ArgTypes&&...);
|
Chris@16
|
3354 ////////////////////////////////
|
Chris@16
|
3355
|
Chris@16
|
3356 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@16
|
3357
|
Chris@101
|
3358 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
3359 template <class R, class... ArgTypes>
|
Chris@101
|
3360 BOOST_THREAD_FUTURE<R>
|
Chris@101
|
3361 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
|
Chris@101
|
3362 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
|
Chris@101
|
3363 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
|
Chris@101
|
3364 typedef typename BF::result_type Rp;
|
Chris@101
|
3365
|
Chris@101
|
3366 if (underlying_cast<int>(policy) & int(launch::async)) {
|
Chris@101
|
3367 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
|
Chris@16
|
3368 BF(
|
Chris@101
|
3369 f
|
Chris@16
|
3370 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@16
|
3371 )
|
Chris@16
|
3372 ));
|
Chris@101
|
3373 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
Chris@101
|
3374 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
|
Chris@16
|
3375 BF(
|
Chris@101
|
3376 f
|
Chris@16
|
3377 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@16
|
3378 )
|
Chris@16
|
3379 ));
|
Chris@101
|
3380 } else {
|
Chris@101
|
3381 std::terminate();
|
Chris@101
|
3382 BOOST_THREAD_FUTURE<R> ret;
|
Chris@101
|
3383 return ::boost::move(ret);
|
Chris@101
|
3384 }
|
Chris@101
|
3385 }
|
Chris@101
|
3386
|
Chris@101
|
3387 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
3388
|
Chris@101
|
3389 template <class R>
|
Chris@101
|
3390 BOOST_THREAD_FUTURE<R>
|
Chris@101
|
3391 async(launch policy, R(*f)()) {
|
Chris@101
|
3392 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@101
|
3393 typedef packaged_task<R()> packaged_task_type;
|
Chris@101
|
3394 #else
|
Chris@101
|
3395 typedef packaged_task<R> packaged_task_type;
|
Chris@101
|
3396 #endif
|
Chris@101
|
3397
|
Chris@101
|
3398 if (underlying_cast<int>(policy) & int(launch::async)) {
|
Chris@101
|
3399 packaged_task_type pt( f );
|
Chris@101
|
3400 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
|
Chris@101
|
3401 ret.set_async();
|
Chris@101
|
3402 boost::thread( boost::move(pt) ).detach();
|
Chris@101
|
3403 return ::boost::move(ret);
|
Chris@101
|
3404 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
Chris@101
|
3405 std::terminate();
|
Chris@101
|
3406 BOOST_THREAD_FUTURE<R> ret;
|
Chris@101
|
3407 return ::boost::move(ret);
|
Chris@101
|
3408 } else {
|
Chris@101
|
3409 std::terminate();
|
Chris@101
|
3410 BOOST_THREAD_FUTURE<R> ret;
|
Chris@101
|
3411 return ::boost::move(ret);
|
Chris@101
|
3412 }
|
Chris@101
|
3413 }
|
Chris@16
|
3414 #endif
|
Chris@101
|
3415 #endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@101
|
3416
|
Chris@101
|
3417 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
3418
|
Chris@101
|
3419 template <class F, class ...ArgTypes>
|
Chris@101
|
3420 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
|
Chris@101
|
3421 typename decay<ArgTypes>::type...
|
Chris@101
|
3422 )>::type>
|
Chris@101
|
3423 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
|
Chris@101
|
3424 typedef typename boost::result_of<typename decay<F>::type(
|
Chris@101
|
3425 typename decay<ArgTypes>::type...
|
Chris@101
|
3426 )>::type R;
|
Chris@101
|
3427 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
|
Chris@101
|
3428 typedef typename BF::result_type Rp;
|
Chris@101
|
3429
|
Chris@101
|
3430 if (underlying_cast<int>(policy) & int(launch::async)) {
|
Chris@101
|
3431 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
|
Chris@16
|
3432 BF(
|
Chris@16
|
3433 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@101
|
3434 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@16
|
3435 )
|
Chris@16
|
3436 ));
|
Chris@101
|
3437 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
Chris@101
|
3438 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
|
Chris@16
|
3439 BF(
|
Chris@16
|
3440 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@101
|
3441 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@16
|
3442 )
|
Chris@16
|
3443 ));
|
Chris@101
|
3444 } else {
|
Chris@101
|
3445 std::terminate();
|
Chris@101
|
3446 BOOST_THREAD_FUTURE<R> ret;
|
Chris@101
|
3447 return ::boost::move(ret);
|
Chris@101
|
3448 }
|
Chris@101
|
3449 }
|
Chris@101
|
3450
|
Chris@101
|
3451 #else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
3452
|
Chris@101
|
3453 template <class F>
|
Chris@101
|
3454 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
|
Chris@101
|
3455 async(launch policy, BOOST_THREAD_FWD_REF(F) f) {
|
Chris@101
|
3456 typedef typename boost::result_of<typename decay<F>::type()>::type R;
|
Chris@101
|
3457 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@101
|
3458 typedef packaged_task<R()> packaged_task_type;
|
Chris@101
|
3459 #else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@101
|
3460 typedef packaged_task<R> packaged_task_type;
|
Chris@101
|
3461 #endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@101
|
3462
|
Chris@101
|
3463 if (underlying_cast<int>(policy) & int(launch::async)) {
|
Chris@101
|
3464 packaged_task_type pt( boost::forward<F>(f) );
|
Chris@101
|
3465 BOOST_THREAD_FUTURE<R> ret = pt.get_future();
|
Chris@101
|
3466 ret.set_async();
|
Chris@101
|
3467 boost::thread( boost::move(pt) ).detach();
|
Chris@101
|
3468 return ::boost::move(ret);
|
Chris@101
|
3469 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
Chris@101
|
3470 std::terminate();
|
Chris@101
|
3471 BOOST_THREAD_FUTURE<R> ret;
|
Chris@101
|
3472 return ::boost::move(ret);
|
Chris@101
|
3473 // return boost::detail::make_future_deferred_shared_state<Rp>(
|
Chris@101
|
3474 // BF(
|
Chris@101
|
3475 // thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@101
|
3476 // )
|
Chris@101
|
3477 // );
|
Chris@101
|
3478 } else {
|
Chris@101
|
3479 std::terminate();
|
Chris@101
|
3480 BOOST_THREAD_FUTURE<R> ret;
|
Chris@101
|
3481 return ::boost::move(ret);
|
Chris@101
|
3482 }
|
Chris@101
|
3483 }
|
Chris@101
|
3484 #endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
3485
|
Chris@101
|
3486 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
3487 namespace detail {
|
Chris@101
|
3488 /////////////////////////
|
Chris@101
|
3489 /// shared_state_nullary_task
|
Chris@101
|
3490 /////////////////////////
|
Chris@101
|
3491 template<typename Rp, typename Fp>
|
Chris@101
|
3492 struct shared_state_nullary_task
|
Chris@101
|
3493 {
|
Chris@101
|
3494 shared_state<Rp>* that;
|
Chris@101
|
3495 Fp f_;
|
Chris@101
|
3496 public:
|
Chris@101
|
3497
|
Chris@101
|
3498 shared_state_nullary_task(shared_state<Rp>* st, BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@101
|
3499 : that(st), f_(boost::move(f))
|
Chris@101
|
3500 {};
|
Chris@101
|
3501 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@101
|
3502 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
|
Chris@101
|
3503 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
|
Chris@101
|
3504 : that(x.that), f_(x.f_)
|
Chris@101
|
3505 {}
|
Chris@101
|
3506 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
|
Chris@101
|
3507 {
|
Chris@101
|
3508 if (this != &x) {
|
Chris@101
|
3509 that=x.that;
|
Chris@101
|
3510 f_=x.f_;
|
Chris@101
|
3511 }
|
Chris@101
|
3512 return *this;
|
Chris@101
|
3513 }
|
Chris@101
|
3514 // move
|
Chris@101
|
3515 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
|
Chris@101
|
3516 : that(x.that), f_(boost::move(x.f_))
|
Chris@101
|
3517 {
|
Chris@101
|
3518 x.that=0;
|
Chris@101
|
3519 }
|
Chris@101
|
3520 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
|
Chris@101
|
3521 {
|
Chris@101
|
3522 if (this != &x) {
|
Chris@101
|
3523 that=x.that;
|
Chris@101
|
3524 f_=boost::move(x.f_);
|
Chris@101
|
3525 x.that=0;
|
Chris@101
|
3526 }
|
Chris@101
|
3527 return *this;
|
Chris@101
|
3528 }
|
Chris@101
|
3529 #endif
|
Chris@101
|
3530 void operator()() {
|
Chris@101
|
3531 try {
|
Chris@101
|
3532 that->mark_finished_with_result(f_());
|
Chris@101
|
3533 } catch(...) {
|
Chris@101
|
3534 that->mark_exceptional_finish();
|
Chris@101
|
3535 }
|
Chris@101
|
3536 }
|
Chris@101
|
3537 };
|
Chris@101
|
3538
|
Chris@101
|
3539 template<typename Fp>
|
Chris@101
|
3540 struct shared_state_nullary_task<void, Fp>
|
Chris@101
|
3541 {
|
Chris@101
|
3542 shared_state<void>* that;
|
Chris@101
|
3543 Fp f_;
|
Chris@101
|
3544 public:
|
Chris@101
|
3545 shared_state_nullary_task(shared_state<void>* st, BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@101
|
3546 : that(st), f_(boost::move(f))
|
Chris@101
|
3547 {};
|
Chris@101
|
3548 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@101
|
3549 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
|
Chris@101
|
3550 shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT
|
Chris@101
|
3551 : that(x.that), f_(x.f_)
|
Chris@101
|
3552 {}
|
Chris@101
|
3553 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT
|
Chris@101
|
3554 {
|
Chris@101
|
3555 if (this != &x) {
|
Chris@101
|
3556 that=x.that;
|
Chris@101
|
3557 f_=x.f_;
|
Chris@101
|
3558 }
|
Chris@101
|
3559 return *this;
|
Chris@101
|
3560 }
|
Chris@101
|
3561 // move
|
Chris@101
|
3562 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT
|
Chris@101
|
3563 : that(x.that), f_(boost::move(x.f_))
|
Chris@101
|
3564 {
|
Chris@101
|
3565 x.that=0;
|
Chris@101
|
3566 }
|
Chris@101
|
3567 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
|
Chris@101
|
3568 if (this != &x) {
|
Chris@101
|
3569 that=x.that;
|
Chris@101
|
3570 f_=boost::move(x.f_);
|
Chris@101
|
3571 x.that=0;
|
Chris@101
|
3572 }
|
Chris@101
|
3573 return *this;
|
Chris@101
|
3574 }
|
Chris@101
|
3575 #endif
|
Chris@101
|
3576 void operator()() {
|
Chris@101
|
3577 try {
|
Chris@101
|
3578 f_();
|
Chris@101
|
3579 that->mark_finished_with_result();
|
Chris@101
|
3580 } catch(...) {
|
Chris@101
|
3581 that->mark_exceptional_finish();
|
Chris@101
|
3582 }
|
Chris@101
|
3583 }
|
Chris@101
|
3584 };
|
Chris@101
|
3585
|
Chris@101
|
3586 template<typename Rp, typename Fp>
|
Chris@101
|
3587 struct shared_state_nullary_task<Rp&, Fp>
|
Chris@101
|
3588 {
|
Chris@101
|
3589 shared_state<Rp&>* that;
|
Chris@101
|
3590 Fp f_;
|
Chris@101
|
3591 public:
|
Chris@101
|
3592 shared_state_nullary_task(shared_state<Rp&>* st, BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@101
|
3593 : that(st), f_(boost::move(f))
|
Chris@101
|
3594 {}
|
Chris@101
|
3595 #if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@101
|
3596 BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task)
|
Chris@101
|
3597 shared_state_nullary_task(shared_state_nullary_task const& x) BOOST_NOEXCEPT
|
Chris@101
|
3598 : that(x.that), f_(x.f_) {}
|
Chris@101
|
3599
|
Chris@101
|
3600 shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
|
Chris@101
|
3601 if (this != &x){
|
Chris@101
|
3602 that=x.that;
|
Chris@101
|
3603 f_=x.f_;
|
Chris@101
|
3604 }
|
Chris@101
|
3605 return *this;
|
Chris@101
|
3606 }
|
Chris@101
|
3607 // move
|
Chris@101
|
3608 shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT
|
Chris@101
|
3609 : that(x.that), f_(boost::move(x.f_))
|
Chris@101
|
3610 {
|
Chris@101
|
3611 x.that=0;
|
Chris@101
|
3612 }
|
Chris@101
|
3613 shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT {
|
Chris@101
|
3614 if (this != &x) {
|
Chris@101
|
3615 that=x.that;
|
Chris@101
|
3616 f_=boost::move(x.f_);
|
Chris@101
|
3617 x.that=0;
|
Chris@101
|
3618 }
|
Chris@101
|
3619 return *this;
|
Chris@101
|
3620 }
|
Chris@101
|
3621 #endif
|
Chris@101
|
3622 void operator()() {
|
Chris@101
|
3623 try {
|
Chris@101
|
3624 that->mark_finished_with_result(f_());
|
Chris@101
|
3625 } catch(...) {
|
Chris@101
|
3626 that->mark_exceptional_finish();
|
Chris@101
|
3627 }
|
Chris@101
|
3628 }
|
Chris@101
|
3629 };
|
Chris@101
|
3630
|
Chris@101
|
3631 /////////////////////////
|
Chris@101
|
3632 /// future_executor_shared_state_base
|
Chris@101
|
3633 /////////////////////////
|
Chris@101
|
3634 template<typename Rp, typename Executor>
|
Chris@101
|
3635 struct future_executor_shared_state: shared_state<Rp>
|
Chris@101
|
3636 {
|
Chris@101
|
3637 typedef shared_state<Rp> base_type;
|
Chris@101
|
3638 protected:
|
Chris@101
|
3639 public:
|
Chris@101
|
3640 template<typename Fp>
|
Chris@101
|
3641 future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) {
|
Chris@101
|
3642 this->set_executor();
|
Chris@101
|
3643 shared_state_nullary_task<Rp,Fp> t(this, boost::forward<Fp>(f));
|
Chris@101
|
3644 ex.submit(boost::move(t));
|
Chris@101
|
3645 }
|
Chris@101
|
3646
|
Chris@101
|
3647 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
|
Chris@101
|
3648 {
|
Chris@101
|
3649 this->wait(lk, false);
|
Chris@101
|
3650 }
|
Chris@101
|
3651
|
Chris@101
|
3652 ~future_executor_shared_state() {}
|
Chris@101
|
3653 };
|
Chris@101
|
3654
|
Chris@101
|
3655 ////////////////////////////////
|
Chris@101
|
3656 // make_future_executor_shared_state
|
Chris@101
|
3657 ////////////////////////////////
|
Chris@101
|
3658 template <class Rp, class Fp, class Executor>
|
Chris@101
|
3659 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
3660 make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) {
|
Chris@101
|
3661 shared_ptr<future_executor_shared_state<Rp, Executor> >
|
Chris@101
|
3662 h(new future_executor_shared_state<Rp, Executor>(ex, boost::forward<Fp>(f)));
|
Chris@101
|
3663 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@101
|
3664 }
|
Chris@101
|
3665
|
Chris@101
|
3666 } // detail
|
Chris@101
|
3667
|
Chris@101
|
3668 ////////////////////////////////
|
Chris@101
|
3669 // template <class Executor, class F, class... ArgTypes>
|
Chris@101
|
3670 // future<R> async(Executor& ex, F&&, ArgTypes&&...);
|
Chris@101
|
3671 ////////////////////////////////
|
Chris@101
|
3672
|
Chris@101
|
3673 //#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
3674 #if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE)
|
Chris@101
|
3675
|
Chris@101
|
3676 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@101
|
3677
|
Chris@101
|
3678 template <class Executor, class R, class... ArgTypes>
|
Chris@101
|
3679 BOOST_THREAD_FUTURE<R>
|
Chris@101
|
3680 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
|
Chris@101
|
3681 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
|
Chris@101
|
3682 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
|
Chris@101
|
3683 typedef typename BF::result_type Rp;
|
Chris@101
|
3684
|
Chris@101
|
3685 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
|
Chris@101
|
3686 BF(
|
Chris@101
|
3687 f
|
Chris@101
|
3688 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@101
|
3689 )
|
Chris@101
|
3690 ));
|
Chris@101
|
3691 }
|
Chris@101
|
3692 #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@101
|
3693
|
Chris@101
|
3694 template <class Executor, class F, class ...ArgTypes>
|
Chris@101
|
3695 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
|
Chris@101
|
3696 typename decay<ArgTypes>::type...
|
Chris@101
|
3697 )>::type>
|
Chris@101
|
3698 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
|
Chris@101
|
3699 typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
|
Chris@101
|
3700 typedef typename BF::result_type Rp;
|
Chris@101
|
3701
|
Chris@101
|
3702 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
|
Chris@101
|
3703 BF(
|
Chris@101
|
3704 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@101
|
3705 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@101
|
3706 )
|
Chris@101
|
3707 ));
|
Chris@101
|
3708 }
|
Chris@101
|
3709
|
Chris@101
|
3710 #else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
3711 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@101
|
3712
|
Chris@101
|
3713 template <class Executor, class R>
|
Chris@101
|
3714 BOOST_THREAD_FUTURE<R>
|
Chris@101
|
3715 async(Executor& ex, R(*f)()) {
|
Chris@101
|
3716 typedef R(*F)();
|
Chris@101
|
3717 typedef detail::invoker<F> BF;
|
Chris@101
|
3718 typedef typename BF::result_type Rp;
|
Chris@101
|
3719
|
Chris@101
|
3720 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
|
Chris@101
|
3721 BF(
|
Chris@101
|
3722 f
|
Chris@101
|
3723 )
|
Chris@101
|
3724 ));
|
Chris@101
|
3725 }
|
Chris@101
|
3726
|
Chris@101
|
3727 template <class Executor, class R, class A1>
|
Chris@101
|
3728 BOOST_THREAD_FUTURE<R>
|
Chris@101
|
3729 async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) {
|
Chris@101
|
3730 typedef R(*F)(BOOST_THREAD_FWD_REF(A1));
|
Chris@101
|
3731 typedef detail::invoker<F, typename decay<A1>::type> BF;
|
Chris@101
|
3732 typedef typename BF::result_type Rp;
|
Chris@101
|
3733
|
Chris@101
|
3734 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
|
Chris@101
|
3735 BF(
|
Chris@101
|
3736 f
|
Chris@101
|
3737 , thread_detail::decay_copy(boost::forward<A1>(a1))
|
Chris@101
|
3738 )
|
Chris@101
|
3739 ));
|
Chris@101
|
3740 }
|
Chris@101
|
3741 #endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@101
|
3742
|
Chris@101
|
3743 template <class Executor, class F>
|
Chris@101
|
3744 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
|
Chris@101
|
3745 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) {
|
Chris@101
|
3746 typedef detail::invoker<typename decay<F>::type> BF;
|
Chris@101
|
3747 typedef typename BF::result_type Rp;
|
Chris@101
|
3748
|
Chris@101
|
3749 return boost::detail::make_future_executor_shared_state<Rp>(ex,
|
Chris@101
|
3750 BF(
|
Chris@101
|
3751 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@101
|
3752 )
|
Chris@101
|
3753 );
|
Chris@101
|
3754 }
|
Chris@101
|
3755
|
Chris@101
|
3756 template <class Executor, class F, class A1>
|
Chris@101
|
3757 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
|
Chris@101
|
3758 typename decay<A1>::type
|
Chris@101
|
3759 )>::type>
|
Chris@101
|
3760 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) {
|
Chris@101
|
3761 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type> BF;
|
Chris@101
|
3762 typedef typename BF::result_type Rp;
|
Chris@101
|
3763
|
Chris@101
|
3764 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
|
Chris@101
|
3765 BF(
|
Chris@101
|
3766 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@101
|
3767 , thread_detail::decay_copy(boost::forward<A1>(a1))
|
Chris@101
|
3768 )
|
Chris@101
|
3769 ));
|
Chris@101
|
3770 }
|
Chris@101
|
3771
|
Chris@101
|
3772 template <class Executor, class F, class A1, class A2>
|
Chris@101
|
3773 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
|
Chris@101
|
3774 typename decay<A1>::type, typename decay<A2>::type
|
Chris@101
|
3775 )>::type>
|
Chris@101
|
3776 async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) {
|
Chris@101
|
3777 typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type, typename decay<A2>::type> BF;
|
Chris@101
|
3778 typedef typename BF::result_type Rp;
|
Chris@101
|
3779
|
Chris@101
|
3780 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex,
|
Chris@101
|
3781 BF(
|
Chris@101
|
3782 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@101
|
3783 , thread_detail::decay_copy(boost::forward<A1>(a1))
|
Chris@101
|
3784 , thread_detail::decay_copy(boost::forward<A2>(a2))
|
Chris@101
|
3785 )
|
Chris@101
|
3786 ));
|
Chris@101
|
3787 }
|
Chris@101
|
3788
|
Chris@101
|
3789 #endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
3790 #endif
|
Chris@101
|
3791
|
Chris@101
|
3792 ////////////////////////////////
|
Chris@101
|
3793 // template <class F, class... ArgTypes>
|
Chris@101
|
3794 // future<R> async(F&&, ArgTypes&&...);
|
Chris@101
|
3795 ////////////////////////////////
|
Chris@101
|
3796
|
Chris@101
|
3797 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@101
|
3798 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
3799 template <class R, class... ArgTypes>
|
Chris@101
|
3800 BOOST_THREAD_FUTURE<R>
|
Chris@101
|
3801 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) {
|
Chris@101
|
3802 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
|
Chris@101
|
3803 }
|
Chris@101
|
3804 #else
|
Chris@101
|
3805 template <class R>
|
Chris@101
|
3806 BOOST_THREAD_FUTURE<R>
|
Chris@101
|
3807 async(R(*f)()) {
|
Chris@101
|
3808 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
|
Chris@101
|
3809 }
|
Chris@101
|
3810 #endif
|
Chris@101
|
3811 #endif
|
Chris@101
|
3812
|
Chris@101
|
3813 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@101
|
3814 template <class F, class ...ArgTypes>
|
Chris@101
|
3815 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
|
Chris@101
|
3816 typename decay<ArgTypes>::type...
|
Chris@101
|
3817 )>::type>
|
Chris@101
|
3818 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) {
|
Chris@101
|
3819 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
|
Chris@101
|
3820 }
|
Chris@16
|
3821 #else
|
Chris@101
|
3822 template <class F>
|
Chris@101
|
3823 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
|
Chris@101
|
3824 async(BOOST_THREAD_FWD_REF(F) f) {
|
Chris@101
|
3825 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
|
Chris@101
|
3826 }
|
Chris@16
|
3827 #endif
|
Chris@16
|
3828
|
Chris@16
|
3829 ////////////////////////////////
|
Chris@16
|
3830 // make_future deprecated
|
Chris@16
|
3831 ////////////////////////////////
|
Chris@16
|
3832 template <typename T>
|
Chris@101
|
3833 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) {
|
Chris@16
|
3834 typedef typename decay<T>::type future_value_type;
|
Chris@16
|
3835 promise<future_value_type> p;
|
Chris@16
|
3836 p.set_value(boost::forward<future_value_type>(value));
|
Chris@16
|
3837 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3838 }
|
Chris@16
|
3839
|
Chris@16
|
3840 #if defined BOOST_THREAD_USES_MOVE
|
Chris@101
|
3841 inline BOOST_THREAD_FUTURE<void> make_future() {
|
Chris@16
|
3842 promise<void> p;
|
Chris@16
|
3843 p.set_value();
|
Chris@16
|
3844 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3845 }
|
Chris@16
|
3846 #endif
|
Chris@16
|
3847
|
Chris@16
|
3848 ////////////////////////////////
|
Chris@16
|
3849 // make_ready_future
|
Chris@16
|
3850 ////////////////////////////////
|
Chris@101
|
3851 namespace detail {
|
Chris@101
|
3852 template <class T>
|
Chris@101
|
3853 struct deduced_type_impl
|
Chris@101
|
3854 {
|
Chris@101
|
3855 typedef T type;
|
Chris@101
|
3856 };
|
Chris@101
|
3857
|
Chris@101
|
3858 template <class T>
|
Chris@101
|
3859 struct deduced_type_impl<reference_wrapper<T> const>
|
Chris@101
|
3860 {
|
Chris@101
|
3861 typedef T& type;
|
Chris@101
|
3862 };
|
Chris@101
|
3863 template <class T>
|
Chris@101
|
3864 struct deduced_type_impl<reference_wrapper<T> >
|
Chris@101
|
3865 {
|
Chris@101
|
3866 typedef T& type;
|
Chris@101
|
3867 };
|
Chris@101
|
3868 #if __cplusplus > 201103L
|
Chris@101
|
3869 template <class T>
|
Chris@101
|
3870 struct deduced_type_impl<std::reference_wrapper<T> >
|
Chris@101
|
3871 {
|
Chris@101
|
3872 typedef T& type;
|
Chris@101
|
3873 };
|
Chris@101
|
3874 #endif
|
Chris@101
|
3875 template <class T>
|
Chris@101
|
3876 struct deduced_type
|
Chris@101
|
3877 {
|
Chris@101
|
3878 typedef typename detail::deduced_type_impl<typename decay<T>::type>::type type;
|
Chris@101
|
3879 };
|
Chris@101
|
3880
|
Chris@101
|
3881 }
|
Chris@101
|
3882
|
Chris@101
|
3883
|
Chris@101
|
3884 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
3885 template <int = 0, int..., class T>
|
Chris@101
|
3886 #else
|
Chris@101
|
3887 template <class T>
|
Chris@101
|
3888 #endif
|
Chris@101
|
3889 BOOST_THREAD_FUTURE<typename detail::deduced_type<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) {
|
Chris@101
|
3890 typedef typename detail::deduced_type<T>::type future_value_type;
|
Chris@16
|
3891 promise<future_value_type> p;
|
Chris@101
|
3892 p.set_value(boost::forward<T>(value));
|
Chris@16
|
3893 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3894 }
|
Chris@16
|
3895
|
Chris@101
|
3896 // explicit overloads
|
Chris@101
|
3897 template <class T>
|
Chris@101
|
3898 BOOST_THREAD_FUTURE<T> make_ready_future(typename remove_reference<T>::type & x)
|
Chris@16
|
3899 {
|
Chris@101
|
3900 promise<T> p;
|
Chris@101
|
3901 p.set_value(x);
|
Chris@101
|
3902 return p.get_future();
|
Chris@101
|
3903 }
|
Chris@101
|
3904
|
Chris@101
|
3905 template <class T>
|
Chris@101
|
3906 BOOST_THREAD_FUTURE<T> make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference<T>::type) x)
|
Chris@101
|
3907 {
|
Chris@101
|
3908 promise<T> p;
|
Chris@101
|
3909 p.set_value(forward<typename remove_reference<T>::type>(x));
|
Chris@101
|
3910 return p.get_future();
|
Chris@101
|
3911 }
|
Chris@101
|
3912
|
Chris@101
|
3913 // variadic overload
|
Chris@101
|
3914 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
3915 template <class T, class ...Args>
|
Chris@101
|
3916 BOOST_THREAD_FUTURE<T> make_ready_future(Args&&... args)
|
Chris@101
|
3917 {
|
Chris@101
|
3918 promise<T> p;
|
Chris@101
|
3919 p.emplace(forward<Args>(args)...);
|
Chris@101
|
3920 return p.get_future();
|
Chris@101
|
3921
|
Chris@101
|
3922 }
|
Chris@101
|
3923 #endif
|
Chris@101
|
3924
|
Chris@101
|
3925 template <typename T, typename T1>
|
Chris@101
|
3926 BOOST_THREAD_FUTURE<T> make_ready_no_decay_future(T1 value) {
|
Chris@101
|
3927 typedef T future_value_type;
|
Chris@101
|
3928 promise<future_value_type> p;
|
Chris@101
|
3929 p.set_value(value);
|
Chris@101
|
3930 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@101
|
3931 }
|
Chris@101
|
3932
|
Chris@101
|
3933 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined BOOST_THREAD_USES_MOVE
|
Chris@101
|
3934 inline BOOST_THREAD_FUTURE<void> make_ready_future() {
|
Chris@16
|
3935 promise<void> p;
|
Chris@16
|
3936 p.set_value();
|
Chris@101
|
3937 return p.get_future();
|
Chris@16
|
3938 }
|
Chris@16
|
3939 #endif
|
Chris@16
|
3940
|
Chris@16
|
3941 template <typename T>
|
Chris@101
|
3942 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) {
|
Chris@16
|
3943 promise<T> p;
|
Chris@16
|
3944 p.set_exception(ex);
|
Chris@16
|
3945 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3946 }
|
Chris@101
|
3947
|
Chris@101
|
3948 template <typename T>
|
Chris@101
|
3949 BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) {
|
Chris@101
|
3950 promise<T> p;
|
Chris@101
|
3951 p.set_exception(ex);
|
Chris@101
|
3952 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@101
|
3953 }
|
Chris@101
|
3954
|
Chris@16
|
3955 template <typename T, typename E>
|
Chris@101
|
3956 BOOST_THREAD_FUTURE<T> make_exceptional_future(E ex) {
|
Chris@16
|
3957 promise<T> p;
|
Chris@16
|
3958 p.set_exception(boost::copy_exception(ex));
|
Chris@16
|
3959 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3960 }
|
Chris@16
|
3961
|
Chris@101
|
3962 template <typename T>
|
Chris@101
|
3963 BOOST_THREAD_FUTURE<T> make_exceptional_future() {
|
Chris@101
|
3964 promise<T> p;
|
Chris@101
|
3965 p.set_exception(boost::current_exception());
|
Chris@101
|
3966 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@101
|
3967 }
|
Chris@101
|
3968
|
Chris@101
|
3969 template <typename T>
|
Chris@101
|
3970 BOOST_THREAD_FUTURE<T> make_exceptional_future_if_invalid(BOOST_THREAD_FWD_REF(BOOST_THREAD_FUTURE<T>) fut) {
|
Chris@101
|
3971 fut.set_exceptional_if_invalid();
|
Chris@101
|
3972 return boost::move(fut);
|
Chris@101
|
3973 }
|
Chris@101
|
3974 template <typename T>
|
Chris@101
|
3975 shared_future<T> make_exceptional_future_if_invalid(shared_future<T> fut) {
|
Chris@101
|
3976 fut.set_exceptional_if_invalid();
|
Chris@101
|
3977 return fut;
|
Chris@101
|
3978 }
|
Chris@101
|
3979
|
Chris@16
|
3980 #if 0
|
Chris@16
|
3981 template<typename CLOSURE>
|
Chris@16
|
3982 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
|
Chris@16
|
3983 typedef decltype(closure()) T;
|
Chris@16
|
3984 promise<T> p;
|
Chris@101
|
3985 try {
|
Chris@16
|
3986 p.set_value(closure());
|
Chris@101
|
3987 } catch(...) {
|
Chris@16
|
3988 p.set_exception(std::current_exception());
|
Chris@16
|
3989 }
|
Chris@16
|
3990 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3991 }
|
Chris@16
|
3992 #endif
|
Chris@16
|
3993
|
Chris@16
|
3994 ////////////////////////////////
|
Chris@16
|
3995 // make_shared_future deprecated
|
Chris@16
|
3996 ////////////////////////////////
|
Chris@16
|
3997 template <typename T>
|
Chris@101
|
3998 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) {
|
Chris@16
|
3999 typedef typename decay<T>::type future_type;
|
Chris@16
|
4000 promise<future_type> p;
|
Chris@16
|
4001 p.set_value(boost::forward<T>(value));
|
Chris@16
|
4002 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
|
Chris@16
|
4003 }
|
Chris@16
|
4004
|
Chris@101
|
4005 inline shared_future<void> make_shared_future() {
|
Chris@16
|
4006 promise<void> p;
|
Chris@16
|
4007 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
|
Chris@16
|
4008 }
|
Chris@16
|
4009
|
Chris@16
|
4010 ////////////////////////////////
|
Chris@16
|
4011 // detail::future_async_continuation_shared_state
|
Chris@16
|
4012 ////////////////////////////////
|
Chris@16
|
4013 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@101
|
4014 namespace detail
|
Chris@101
|
4015 {
|
Chris@101
|
4016
|
Chris@101
|
4017 /////////////////////////
|
Chris@101
|
4018 /// future_async_continuation_shared_state
|
Chris@101
|
4019 /////////////////////////
|
Chris@101
|
4020
|
Chris@101
|
4021 template<typename F, typename Rp, typename Fp>
|
Chris@101
|
4022 struct future_async_continuation_shared_state: future_async_shared_state_base<Rp>
|
Chris@16
|
4023 {
|
Chris@101
|
4024 F parent;
|
Chris@101
|
4025 Fp continuation;
|
Chris@101
|
4026 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4027
|
Chris@101
|
4028 public:
|
Chris@101
|
4029 future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4030 : parent(boost::move(f)),
|
Chris@101
|
4031 continuation(boost::move(c)),
|
Chris@101
|
4032 centinel(parent.future_) {
|
Chris@101
|
4033 }
|
Chris@101
|
4034
|
Chris@101
|
4035
|
Chris@101
|
4036 void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) {
|
Chris@101
|
4037 this->thr_ = thread(&future_async_continuation_shared_state::run, that);
|
Chris@101
|
4038 }
|
Chris@101
|
4039
|
Chris@101
|
4040 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
4041 future_async_continuation_shared_state* that = dynamic_cast<future_async_continuation_shared_state*>(that_.get());
|
Chris@101
|
4042 try {
|
Chris@101
|
4043 that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
|
Chris@101
|
4044 } catch(...) {
|
Chris@101
|
4045 that->mark_exceptional_finish();
|
Chris@101
|
4046 }
|
Chris@101
|
4047 }
|
Chris@101
|
4048
|
Chris@101
|
4049 ~future_async_continuation_shared_state() {
|
Chris@101
|
4050 }
|
Chris@101
|
4051 };
|
Chris@101
|
4052
|
Chris@101
|
4053 template<typename F, typename Fp>
|
Chris@101
|
4054 struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void>
|
Chris@101
|
4055 {
|
Chris@101
|
4056 F parent;
|
Chris@101
|
4057 Fp continuation;
|
Chris@101
|
4058 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4059
|
Chris@101
|
4060 public:
|
Chris@101
|
4061 future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4062 : parent(boost::move(f)),
|
Chris@101
|
4063 continuation(boost::move(c)),
|
Chris@101
|
4064 centinel(parent.future_) {
|
Chris@101
|
4065 }
|
Chris@101
|
4066
|
Chris@101
|
4067 void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) {
|
Chris@101
|
4068 this->thr_ = thread(&future_async_continuation_shared_state::run, that);
|
Chris@101
|
4069 }
|
Chris@101
|
4070
|
Chris@101
|
4071 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
4072 future_async_continuation_shared_state* that = dynamic_cast<future_async_continuation_shared_state*>(that_.get());
|
Chris@101
|
4073 try {
|
Chris@101
|
4074 that->continuation(boost::move(that->parent));
|
Chris@101
|
4075 that->mark_finished_with_result();
|
Chris@101
|
4076 } catch(...) {
|
Chris@101
|
4077 that->mark_exceptional_finish();
|
Chris@101
|
4078 }
|
Chris@101
|
4079 }
|
Chris@101
|
4080
|
Chris@101
|
4081 ~future_async_continuation_shared_state() {}
|
Chris@101
|
4082
|
Chris@101
|
4083 };
|
Chris@101
|
4084
|
Chris@101
|
4085 /////////////////////////
|
Chris@101
|
4086 /// future_executor_continuation_shared_state
|
Chris@101
|
4087 /////////////////////////
|
Chris@101
|
4088 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
4089
|
Chris@101
|
4090 template <typename FutureExecutorContinuationSharedState>
|
Chris@101
|
4091 struct run_it {
|
Chris@101
|
4092 shared_ptr<boost::detail::shared_state_base> that_;
|
Chris@101
|
4093
|
Chris@101
|
4094 run_it(shared_ptr<boost::detail::shared_state_base> that) : that_ (that) {}
|
Chris@101
|
4095 void operator()()
|
Chris@16
|
4096 {
|
Chris@101
|
4097 FutureExecutorContinuationSharedState* that = dynamic_cast<FutureExecutorContinuationSharedState*>(that_.get());
|
Chris@101
|
4098 that->run(that_);
|
Chris@101
|
4099 }
|
Chris@101
|
4100 };
|
Chris@101
|
4101
|
Chris@101
|
4102 template<typename Ex, typename F, typename Rp, typename Fp>
|
Chris@101
|
4103 struct future_executor_continuation_shared_state: shared_state<Rp>
|
Chris@101
|
4104 {
|
Chris@101
|
4105 Ex* ex;
|
Chris@101
|
4106 F parent;
|
Chris@101
|
4107 Fp continuation;
|
Chris@101
|
4108 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4109
|
Chris@101
|
4110 public:
|
Chris@101
|
4111 future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4112 : ex(&ex), parent(boost::move(f)),
|
Chris@101
|
4113 continuation(boost::move(c)),
|
Chris@101
|
4114 centinel(parent.future_) {
|
Chris@101
|
4115 this->set_executor();
|
Chris@101
|
4116 }
|
Chris@101
|
4117
|
Chris@101
|
4118 void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that ) {
|
Chris@101
|
4119 relocker relock(lck);
|
Chris@101
|
4120 run_it<future_executor_continuation_shared_state> fct(that);
|
Chris@101
|
4121 ex->submit(fct);
|
Chris@101
|
4122 }
|
Chris@101
|
4123
|
Chris@101
|
4124 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
4125 future_executor_continuation_shared_state* that = dynamic_cast<future_executor_continuation_shared_state*>(that_.get());
|
Chris@101
|
4126 try {
|
Chris@101
|
4127 that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
|
Chris@101
|
4128 } catch(...) {
|
Chris@101
|
4129 that->mark_exceptional_finish();
|
Chris@16
|
4130 }
|
Chris@101
|
4131 }
|
Chris@101
|
4132
|
Chris@101
|
4133 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
|
Chris@101
|
4134 {
|
Chris@101
|
4135 this->wait(lk, false);
|
Chris@101
|
4136 }
|
Chris@101
|
4137
|
Chris@101
|
4138 ~future_executor_continuation_shared_state() {}
|
Chris@101
|
4139 };
|
Chris@101
|
4140
|
Chris@101
|
4141 template<typename Ex, typename F, typename Fp>
|
Chris@101
|
4142 struct future_executor_continuation_shared_state<Ex, F, void, Fp>: public shared_state<void>
|
Chris@101
|
4143 {
|
Chris@101
|
4144 Ex* ex;
|
Chris@101
|
4145 F parent;
|
Chris@101
|
4146 Fp continuation;
|
Chris@101
|
4147 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4148
|
Chris@101
|
4149 public:
|
Chris@101
|
4150 future_executor_continuation_shared_state(Ex& ex, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4151 : ex(&ex), parent(boost::move(f)),
|
Chris@101
|
4152 continuation(boost::move(c)),
|
Chris@101
|
4153 centinel(parent.future_) {
|
Chris@101
|
4154 this->set_executor();
|
Chris@101
|
4155 }
|
Chris@101
|
4156
|
Chris@101
|
4157 void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that ) {
|
Chris@101
|
4158 relocker relock(lck);
|
Chris@101
|
4159 run_it<future_executor_continuation_shared_state> fct(that);
|
Chris@101
|
4160 ex->submit(fct);
|
Chris@101
|
4161 }
|
Chris@101
|
4162
|
Chris@101
|
4163 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
4164 future_executor_continuation_shared_state* that = dynamic_cast<future_executor_continuation_shared_state*>(that_.get());
|
Chris@101
|
4165 try {
|
Chris@101
|
4166 that->continuation(boost::move(that->parent));
|
Chris@101
|
4167 that->mark_finished_with_result();
|
Chris@101
|
4168 } catch(...) {
|
Chris@101
|
4169 that->mark_exceptional_finish();
|
Chris@16
|
4170 }
|
Chris@101
|
4171 }
|
Chris@101
|
4172
|
Chris@101
|
4173 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
|
Chris@101
|
4174 {
|
Chris@101
|
4175 this->wait(lk, false);
|
Chris@101
|
4176 }
|
Chris@101
|
4177
|
Chris@101
|
4178 ~future_executor_continuation_shared_state() {}
|
Chris@101
|
4179 };
|
Chris@16
|
4180 #endif
|
Chris@101
|
4181
|
Chris@101
|
4182 /////////////////////////
|
Chris@101
|
4183 /// shared_future_async_continuation_shared_state
|
Chris@101
|
4184 /////////////////////////
|
Chris@101
|
4185
|
Chris@101
|
4186 template<typename F, typename Rp, typename Fp>
|
Chris@101
|
4187 struct shared_future_async_continuation_shared_state: future_async_shared_state_base<Rp>
|
Chris@101
|
4188 {
|
Chris@101
|
4189 F parent;
|
Chris@101
|
4190 Fp continuation;
|
Chris@101
|
4191 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4192
|
Chris@101
|
4193 public:
|
Chris@101
|
4194 shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4195 : parent(f),
|
Chris@101
|
4196 continuation(boost::move(c)),
|
Chris@101
|
4197 centinel(parent.future_) {
|
Chris@101
|
4198 }
|
Chris@101
|
4199
|
Chris@101
|
4200 void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) {
|
Chris@101
|
4201 this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that);
|
Chris@101
|
4202 }
|
Chris@101
|
4203
|
Chris@101
|
4204 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
4205 shared_future_async_continuation_shared_state* that = dynamic_cast<shared_future_async_continuation_shared_state*>(that_.get());
|
Chris@101
|
4206 try {
|
Chris@101
|
4207 that->mark_finished_with_result(that->continuation(that->parent));
|
Chris@101
|
4208 } catch(...) {
|
Chris@101
|
4209 that->mark_exceptional_finish();
|
Chris@16
|
4210 }
|
Chris@101
|
4211 }
|
Chris@101
|
4212
|
Chris@101
|
4213 ~shared_future_async_continuation_shared_state() {}
|
Chris@101
|
4214 };
|
Chris@101
|
4215
|
Chris@101
|
4216 template<typename F, typename Fp>
|
Chris@101
|
4217 struct shared_future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void>
|
Chris@101
|
4218 {
|
Chris@101
|
4219 F parent;
|
Chris@101
|
4220 Fp continuation;
|
Chris@101
|
4221 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4222
|
Chris@101
|
4223 public:
|
Chris@101
|
4224 shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4225 : parent(f),
|
Chris@101
|
4226 continuation(boost::move(c)),
|
Chris@101
|
4227 centinel(parent.future_) {
|
Chris@101
|
4228 }
|
Chris@101
|
4229
|
Chris@101
|
4230 void launch_continuation(boost::unique_lock<boost::mutex>&, shared_ptr<shared_state_base> that) {
|
Chris@101
|
4231 this->thr_ = thread(&shared_future_async_continuation_shared_state::run, that);
|
Chris@101
|
4232 }
|
Chris@101
|
4233
|
Chris@101
|
4234 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
4235 shared_future_async_continuation_shared_state* that = dynamic_cast<shared_future_async_continuation_shared_state*>(that_.get());
|
Chris@101
|
4236 try {
|
Chris@101
|
4237 that->continuation(that->parent);
|
Chris@101
|
4238 that->mark_finished_with_result();
|
Chris@101
|
4239 } catch(...) {
|
Chris@101
|
4240 that->mark_exceptional_finish();
|
Chris@16
|
4241 }
|
Chris@101
|
4242 }
|
Chris@101
|
4243
|
Chris@101
|
4244 ~shared_future_async_continuation_shared_state() {}
|
Chris@101
|
4245 };
|
Chris@101
|
4246
|
Chris@101
|
4247 /////////////////////////
|
Chris@101
|
4248 /// shared_future_executor_continuation_shared_state
|
Chris@101
|
4249 /////////////////////////
|
Chris@101
|
4250 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
4251
|
Chris@101
|
4252 template<typename Ex, typename F, typename Rp, typename Fp>
|
Chris@101
|
4253 struct shared_future_executor_continuation_shared_state: shared_state<Rp>
|
Chris@101
|
4254 {
|
Chris@101
|
4255 Ex* ex;
|
Chris@101
|
4256 F parent;
|
Chris@101
|
4257 Fp continuation;
|
Chris@101
|
4258 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4259
|
Chris@101
|
4260 public:
|
Chris@101
|
4261 shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4262 : ex(&ex), parent(f),
|
Chris@101
|
4263 continuation(boost::move(c)),
|
Chris@101
|
4264 centinel(parent.future_) {
|
Chris@101
|
4265 this->set_executor();
|
Chris@101
|
4266 }
|
Chris@101
|
4267
|
Chris@101
|
4268 void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that) {
|
Chris@101
|
4269 relocker relock(lck);
|
Chris@101
|
4270 run_it<shared_future_executor_continuation_shared_state> fct(that);
|
Chris@101
|
4271 ex->submit(fct);
|
Chris@101
|
4272 }
|
Chris@101
|
4273
|
Chris@101
|
4274 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
4275 shared_future_executor_continuation_shared_state* that = dynamic_cast<shared_future_executor_continuation_shared_state*>(that_.get());
|
Chris@101
|
4276 try {
|
Chris@101
|
4277 that->mark_finished_with_result(that->continuation(that->parent));
|
Chris@101
|
4278 } catch(...) {
|
Chris@101
|
4279 that->mark_exceptional_finish();
|
Chris@101
|
4280 }
|
Chris@101
|
4281 }
|
Chris@101
|
4282
|
Chris@101
|
4283 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
|
Chris@16
|
4284 {
|
Chris@101
|
4285 this->wait(lk, false);
|
Chris@101
|
4286 }
|
Chris@101
|
4287
|
Chris@101
|
4288 ~shared_future_executor_continuation_shared_state() {}
|
Chris@101
|
4289 };
|
Chris@101
|
4290
|
Chris@101
|
4291 template<typename Ex, typename F, typename Fp>
|
Chris@101
|
4292 struct shared_future_executor_continuation_shared_state<Ex, F, void, Fp>: public shared_state<void>
|
Chris@101
|
4293 {
|
Chris@101
|
4294 Ex* ex;
|
Chris@101
|
4295 F parent;
|
Chris@101
|
4296 Fp continuation;
|
Chris@101
|
4297 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4298
|
Chris@101
|
4299 public:
|
Chris@101
|
4300 shared_future_executor_continuation_shared_state(Ex& ex, F f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4301 : ex(&ex), parent(f),
|
Chris@101
|
4302 continuation(boost::move(c)),
|
Chris@101
|
4303 centinel(parent.future_) {
|
Chris@101
|
4304 }
|
Chris@101
|
4305
|
Chris@101
|
4306 void launch_continuation(boost::unique_lock<boost::mutex>& lck, shared_ptr<shared_state_base> that) {
|
Chris@101
|
4307 relocker relock(lck);
|
Chris@101
|
4308 run_it<shared_future_executor_continuation_shared_state> fct(that);
|
Chris@101
|
4309 ex->submit(fct);
|
Chris@101
|
4310 }
|
Chris@101
|
4311
|
Chris@101
|
4312 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
4313 shared_future_executor_continuation_shared_state* that = dynamic_cast<shared_future_executor_continuation_shared_state*>(that_.get());
|
Chris@101
|
4314 try {
|
Chris@101
|
4315 that->continuation(that->parent);
|
Chris@101
|
4316 that->mark_finished_with_result();
|
Chris@101
|
4317 } catch(...) {
|
Chris@101
|
4318 that->mark_exceptional_finish();
|
Chris@16
|
4319 }
|
Chris@101
|
4320 }
|
Chris@101
|
4321
|
Chris@101
|
4322 virtual void block_if_needed(boost::unique_lock<boost::mutex>&lk)
|
Chris@101
|
4323 {
|
Chris@101
|
4324 this->wait(lk, false);
|
Chris@101
|
4325 }
|
Chris@101
|
4326
|
Chris@101
|
4327 ~shared_future_executor_continuation_shared_state() {}
|
Chris@101
|
4328 };
|
Chris@101
|
4329 #endif
|
Chris@101
|
4330 //////////////////////////
|
Chris@101
|
4331 /// future_deferred_continuation_shared_state
|
Chris@101
|
4332 //////////////////////////
|
Chris@101
|
4333 template<typename F, typename Rp, typename Fp>
|
Chris@101
|
4334 struct future_deferred_continuation_shared_state: shared_state<Rp>
|
Chris@101
|
4335 {
|
Chris@101
|
4336 F parent;
|
Chris@101
|
4337 Fp continuation;
|
Chris@101
|
4338 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4339
|
Chris@101
|
4340 public:
|
Chris@101
|
4341 future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4342 : parent(boost::move(f)),
|
Chris@101
|
4343 continuation(boost::move(c)),
|
Chris@101
|
4344 centinel(parent.future_) {
|
Chris@101
|
4345 this->set_deferred();
|
Chris@101
|
4346 }
|
Chris@101
|
4347
|
Chris@101
|
4348 virtual void launch_continuation(boost::unique_lock<boost::mutex>&lk, shared_ptr<shared_state_base> ) {
|
Chris@101
|
4349 if (this->is_deferred_) {
|
Chris@101
|
4350 this->is_deferred_=false;
|
Chris@101
|
4351 this->execute(lk);
|
Chris@16
|
4352 }
|
Chris@101
|
4353 }
|
Chris@101
|
4354
|
Chris@101
|
4355 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@101
|
4356 try {
|
Chris@101
|
4357 Fp local_fuct=boost::move(continuation);
|
Chris@101
|
4358 F ftmp = boost::move(parent);
|
Chris@101
|
4359 relocker relock(lck);
|
Chris@101
|
4360 Rp res = local_fuct(boost::move(ftmp));
|
Chris@101
|
4361 relock.lock();
|
Chris@101
|
4362 this->mark_finished_with_result_internal(boost::move(res), lck);
|
Chris@101
|
4363 } catch (...) {
|
Chris@101
|
4364 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@101
|
4365 }
|
Chris@101
|
4366 }
|
Chris@101
|
4367 };
|
Chris@101
|
4368
|
Chris@101
|
4369 template<typename F, typename Fp>
|
Chris@101
|
4370 struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void>
|
Chris@101
|
4371 {
|
Chris@101
|
4372 F parent;
|
Chris@101
|
4373 Fp continuation;
|
Chris@101
|
4374 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4375
|
Chris@101
|
4376 public:
|
Chris@101
|
4377 future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4378 : parent(boost::move(f)),
|
Chris@101
|
4379 continuation(boost::move(c)),
|
Chris@101
|
4380 centinel(parent.future_) {
|
Chris@101
|
4381 this->set_deferred();
|
Chris@101
|
4382 }
|
Chris@101
|
4383
|
Chris@101
|
4384 ~future_deferred_continuation_shared_state() {
|
Chris@101
|
4385 }
|
Chris@101
|
4386 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) {
|
Chris@101
|
4387 if (this->is_deferred_) {
|
Chris@101
|
4388 this->is_deferred_=false;
|
Chris@101
|
4389 this->execute(lk);
|
Chris@101
|
4390 }
|
Chris@101
|
4391 }
|
Chris@101
|
4392
|
Chris@101
|
4393 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@101
|
4394 try {
|
Chris@101
|
4395 Fp local_fuct=boost::move(continuation);
|
Chris@101
|
4396 F ftmp = boost::move(parent);
|
Chris@101
|
4397 relocker relock(lck);
|
Chris@101
|
4398 local_fuct(boost::move(ftmp));
|
Chris@101
|
4399 relock.lock();
|
Chris@101
|
4400 this->mark_finished_with_result_internal(lck);
|
Chris@101
|
4401 } catch (...) {
|
Chris@101
|
4402 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@101
|
4403 }
|
Chris@101
|
4404 }
|
Chris@101
|
4405 };
|
Chris@101
|
4406
|
Chris@101
|
4407 //////////////////////////
|
Chris@101
|
4408 /// shared_future_deferred_continuation_shared_state
|
Chris@101
|
4409 //////////////////////////
|
Chris@101
|
4410 template<typename F, typename Rp, typename Fp>
|
Chris@101
|
4411 struct shared_future_deferred_continuation_shared_state: shared_state<Rp>
|
Chris@101
|
4412 {
|
Chris@101
|
4413 F parent;
|
Chris@101
|
4414 Fp continuation;
|
Chris@101
|
4415 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4416
|
Chris@101
|
4417 public:
|
Chris@101
|
4418 shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4419 : parent(f),
|
Chris@101
|
4420 continuation(boost::move(c)),
|
Chris@101
|
4421 centinel(parent.future_) {
|
Chris@101
|
4422 this->set_deferred();
|
Chris@101
|
4423 }
|
Chris@101
|
4424
|
Chris@101
|
4425 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) {
|
Chris@101
|
4426 if (this->is_deferred_) {
|
Chris@101
|
4427 this->is_deferred_=false;
|
Chris@101
|
4428 this->execute(lk);
|
Chris@101
|
4429 }
|
Chris@101
|
4430 }
|
Chris@101
|
4431
|
Chris@101
|
4432 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@101
|
4433 try {
|
Chris@101
|
4434 Fp local_fuct=boost::move(continuation);
|
Chris@101
|
4435 F ftmp = parent;
|
Chris@101
|
4436 relocker relock(lck);
|
Chris@101
|
4437 Rp res = local_fuct(ftmp);
|
Chris@101
|
4438 relock.lock();
|
Chris@101
|
4439 this->mark_finished_with_result_internal(boost::move(res), lck);
|
Chris@101
|
4440 } catch (...) {
|
Chris@101
|
4441 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@101
|
4442 }
|
Chris@101
|
4443 }
|
Chris@101
|
4444 };
|
Chris@101
|
4445
|
Chris@101
|
4446 template<typename F, typename Fp>
|
Chris@101
|
4447 struct shared_future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void>
|
Chris@101
|
4448 {
|
Chris@101
|
4449 F parent;
|
Chris@101
|
4450 Fp continuation;
|
Chris@101
|
4451 shared_ptr<shared_state_base> centinel;
|
Chris@101
|
4452
|
Chris@101
|
4453 public:
|
Chris@101
|
4454 shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c)
|
Chris@101
|
4455 : parent(f),
|
Chris@101
|
4456 continuation(boost::move(c)),
|
Chris@101
|
4457 centinel(parent.future_) {
|
Chris@101
|
4458 this->set_deferred();
|
Chris@101
|
4459 }
|
Chris@101
|
4460
|
Chris@101
|
4461 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk, shared_ptr<shared_state_base> ) {
|
Chris@101
|
4462 if (this->is_deferred_) {
|
Chris@101
|
4463 this->is_deferred_=false;
|
Chris@101
|
4464 this->execute(lk);
|
Chris@101
|
4465 }
|
Chris@101
|
4466 }
|
Chris@101
|
4467
|
Chris@101
|
4468 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@101
|
4469 try {
|
Chris@101
|
4470 Fp local_fuct=boost::move(continuation);
|
Chris@101
|
4471 F ftmp = parent;
|
Chris@101
|
4472 relocker relock(lck);
|
Chris@101
|
4473 local_fuct(ftmp);
|
Chris@101
|
4474 relock.lock();
|
Chris@101
|
4475 this->mark_finished_with_result_internal(lck);
|
Chris@101
|
4476 } catch (...) {
|
Chris@101
|
4477 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@101
|
4478 }
|
Chris@101
|
4479 }
|
Chris@101
|
4480 };
|
Chris@101
|
4481
|
Chris@101
|
4482 ////////////////////////////////
|
Chris@101
|
4483 // make_future_deferred_continuation_shared_state
|
Chris@101
|
4484 ////////////////////////////////
|
Chris@101
|
4485 template<typename F, typename Rp, typename Fp>
|
Chris@101
|
4486 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
4487 make_future_deferred_continuation_shared_state(
|
Chris@101
|
4488 boost::unique_lock<boost::mutex> &lock,
|
Chris@101
|
4489 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) {
|
Chris@101
|
4490 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> >
|
Chris@101
|
4491 h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
|
Chris@101
|
4492 lock.lock();
|
Chris@101
|
4493 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@101
|
4494 lock.unlock();
|
Chris@101
|
4495 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@101
|
4496 }
|
Chris@101
|
4497
|
Chris@101
|
4498 ////////////////////////////////
|
Chris@101
|
4499 // make_future_async_continuation_shared_state
|
Chris@101
|
4500 ////////////////////////////////
|
Chris@101
|
4501 template<typename F, typename Rp, typename Fp>
|
Chris@101
|
4502 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
4503 make_future_async_continuation_shared_state(
|
Chris@101
|
4504 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
|
Chris@101
|
4505 BOOST_THREAD_FWD_REF(Fp) c) {
|
Chris@101
|
4506 shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> >
|
Chris@101
|
4507 h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
|
Chris@101
|
4508 lock.lock();
|
Chris@101
|
4509 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@101
|
4510 lock.unlock();
|
Chris@101
|
4511
|
Chris@101
|
4512 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@101
|
4513 }
|
Chris@101
|
4514
|
Chris@101
|
4515 ////////////////////////////////
|
Chris@101
|
4516 // make_future_executor_continuation_shared_state
|
Chris@101
|
4517 ////////////////////////////////
|
Chris@101
|
4518 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
4519
|
Chris@101
|
4520 template<typename Ex, typename F, typename Rp, typename Fp>
|
Chris@101
|
4521 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
4522 make_future_executor_continuation_shared_state(Ex& ex,
|
Chris@101
|
4523 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f,
|
Chris@101
|
4524 BOOST_THREAD_FWD_REF(Fp) c) {
|
Chris@101
|
4525 shared_ptr<future_executor_continuation_shared_state<Ex,F,Rp, Fp> >
|
Chris@101
|
4526 h(new future_executor_continuation_shared_state<Ex, F,Rp, Fp>(ex, boost::move(f), boost::forward<Fp>(c)));
|
Chris@101
|
4527 lock.lock();
|
Chris@101
|
4528 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@101
|
4529 lock.unlock();
|
Chris@101
|
4530
|
Chris@101
|
4531 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@101
|
4532 }
|
Chris@16
|
4533 #endif
|
Chris@101
|
4534
|
Chris@101
|
4535 ////////////////////////////////
|
Chris@101
|
4536 // make_shared_future_deferred_continuation_shared_state
|
Chris@101
|
4537 ////////////////////////////////
|
Chris@101
|
4538 template<typename F, typename Rp, typename Fp>
|
Chris@101
|
4539 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
4540 make_shared_future_deferred_continuation_shared_state(
|
Chris@101
|
4541 boost::unique_lock<boost::mutex> &lock,
|
Chris@101
|
4542 F f, BOOST_THREAD_FWD_REF(Fp) c) {
|
Chris@101
|
4543 shared_ptr<shared_future_deferred_continuation_shared_state<F, Rp, Fp> >
|
Chris@101
|
4544 h(new shared_future_deferred_continuation_shared_state<F, Rp, Fp>(f, boost::forward<Fp>(c)));
|
Chris@101
|
4545 lock.lock();
|
Chris@101
|
4546 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@101
|
4547 lock.unlock();
|
Chris@101
|
4548
|
Chris@101
|
4549 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@16
|
4550 }
|
Chris@101
|
4551 ////////////////////////////////
|
Chris@101
|
4552 // make_shared_future_async_continuation_shared_state
|
Chris@101
|
4553 ////////////////////////////////
|
Chris@101
|
4554 template<typename F, typename Rp, typename Fp>
|
Chris@101
|
4555 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
4556 make_shared_future_async_continuation_shared_state(
|
Chris@101
|
4557 boost::unique_lock<boost::mutex> &lock, F f,
|
Chris@101
|
4558 BOOST_THREAD_FWD_REF(Fp) c) {
|
Chris@101
|
4559 shared_ptr<shared_future_async_continuation_shared_state<F,Rp, Fp> >
|
Chris@101
|
4560 h(new shared_future_async_continuation_shared_state<F,Rp, Fp>(f, boost::forward<Fp>(c)));
|
Chris@101
|
4561 lock.lock();
|
Chris@101
|
4562 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@101
|
4563 lock.unlock();
|
Chris@101
|
4564
|
Chris@101
|
4565 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@101
|
4566 }
|
Chris@101
|
4567 ////////////////////////////////
|
Chris@101
|
4568 // make_shared_future_executor_continuation_shared_state
|
Chris@101
|
4569 ////////////////////////////////
|
Chris@101
|
4570 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
4571 template<typename Ex, typename F, typename Rp, typename Fp>
|
Chris@101
|
4572 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
4573 make_shared_future_executor_continuation_shared_state(Ex& ex,
|
Chris@101
|
4574 boost::unique_lock<boost::mutex> &lock, F f,
|
Chris@101
|
4575 BOOST_THREAD_FWD_REF(Fp) c) {
|
Chris@101
|
4576 shared_ptr<shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp> >
|
Chris@101
|
4577 h(new shared_future_executor_continuation_shared_state<Ex, F, Rp, Fp>(ex, f, boost::forward<Fp>(c)));
|
Chris@101
|
4578 lock.lock();
|
Chris@101
|
4579 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@101
|
4580 lock.unlock();
|
Chris@101
|
4581
|
Chris@101
|
4582 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@101
|
4583 }
|
Chris@101
|
4584 #endif
|
Chris@101
|
4585 }
|
Chris@16
|
4586
|
Chris@16
|
4587 ////////////////////////////////
|
Chris@16
|
4588 // template<typename F>
|
Chris@16
|
4589 // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
Chris@16
|
4590 ////////////////////////////////
|
Chris@16
|
4591
|
Chris@16
|
4592 template <typename R>
|
Chris@16
|
4593 template <typename F>
|
Chris@16
|
4594 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
|
Chris@101
|
4595 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
|
Chris@16
|
4596 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
Chris@16
|
4597 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
4598
|
Chris@16
|
4599 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4600 if (underlying_cast<int>(policy) & int(launch::async)) {
|
Chris@101
|
4601 lock.unlock();
|
Chris@101
|
4602 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@101
|
4603 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@101
|
4604 )));
|
Chris@101
|
4605 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
Chris@101
|
4606 this->future_->wait_internal(lock);
|
Chris@101
|
4607 lock.unlock();
|
Chris@101
|
4608 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@101
|
4609 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@101
|
4610 )));
|
Chris@101
|
4611 } else {
|
Chris@101
|
4612 lock.unlock();
|
Chris@16
|
4613 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
4614 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4615 )));
|
Chris@16
|
4616 }
|
Chris@101
|
4617 }
|
Chris@101
|
4618 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
4619 template <typename R>
|
Chris@101
|
4620 template <typename Ex, typename F>
|
Chris@101
|
4621 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
|
Chris@101
|
4622 BOOST_THREAD_FUTURE<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
|
Chris@101
|
4623 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
Chris@101
|
4624 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@101
|
4625
|
Chris@101
|
4626 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4627 lock.unlock();
|
Chris@101
|
4628 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type, F>(ex,
|
Chris@16
|
4629 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4630 )));
|
Chris@16
|
4631 }
|
Chris@101
|
4632 #endif
|
Chris@16
|
4633 template <typename R>
|
Chris@16
|
4634 template <typename F>
|
Chris@16
|
4635 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
|
Chris@101
|
4636 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) {
|
Chris@16
|
4637 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
Chris@16
|
4638 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
4639
|
Chris@16
|
4640 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4641 if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) {
|
Chris@101
|
4642 lock.unlock();
|
Chris@16
|
4643 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
4644 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4645 );
|
Chris@101
|
4646 } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) {
|
Chris@16
|
4647 this->future_->wait_internal(lock);
|
Chris@101
|
4648 lock.unlock();
|
Chris@16
|
4649 return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
4650 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4651 );
|
Chris@101
|
4652 } else {
|
Chris@101
|
4653 lock.unlock();
|
Chris@16
|
4654 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
4655 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4656 );
|
Chris@16
|
4657 }
|
Chris@16
|
4658 }
|
Chris@16
|
4659
|
Chris@101
|
4660 ////////////////////////////////
|
Chris@101
|
4661 // template<typename F>
|
Chris@101
|
4662 // auto future<future<R2>>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
Chris@101
|
4663 ////////////////////////////////
|
Chris@101
|
4664
|
Chris@101
|
4665 template <typename R2>
|
Chris@16
|
4666 template <typename F>
|
Chris@101
|
4667 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
|
Chris@101
|
4668 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) {
|
Chris@101
|
4669 typedef BOOST_THREAD_FUTURE<R2> R;
|
Chris@101
|
4670 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
Chris@16
|
4671 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
4672
|
Chris@16
|
4673 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4674 if (underlying_cast<int>(policy) & int(launch::async)) {
|
Chris@101
|
4675 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@101
|
4676 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@101
|
4677 )));
|
Chris@101
|
4678 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
Chris@101
|
4679 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@101
|
4680 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@101
|
4681 )));
|
Chris@101
|
4682 } else {
|
Chris@101
|
4683 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
4684 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4685 )));
|
Chris@16
|
4686 }
|
Chris@101
|
4687 }
|
Chris@101
|
4688 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
4689 template <typename R2>
|
Chris@101
|
4690 template <typename Ex, typename F>
|
Chris@101
|
4691 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
|
Chris@101
|
4692 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) {
|
Chris@101
|
4693 typedef BOOST_THREAD_FUTURE<R2> R;
|
Chris@101
|
4694 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
Chris@101
|
4695 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@101
|
4696
|
Chris@101
|
4697 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4698 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state<Ex, BOOST_THREAD_FUTURE<R>, future_type, F>(ex,
|
Chris@16
|
4699 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4700 )));
|
Chris@16
|
4701 }
|
Chris@101
|
4702 #endif
|
Chris@101
|
4703 template <typename R2>
|
Chris@16
|
4704 template <typename F>
|
Chris@101
|
4705 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >)>::type>
|
Chris@101
|
4706 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::then(BOOST_THREAD_FWD_REF(F) func) {
|
Chris@101
|
4707 typedef BOOST_THREAD_FUTURE<R2> R;
|
Chris@101
|
4708 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
Chris@16
|
4709 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
4710
|
Chris@16
|
4711 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4712 if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) {
|
Chris@101
|
4713 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
4714 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4715 );
|
Chris@101
|
4716 } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) {
|
Chris@16
|
4717 this->future_->wait_internal(lock);
|
Chris@101
|
4718 return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
4719 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4720 );
|
Chris@101
|
4721 } else {
|
Chris@101
|
4722 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
4723 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4724 );
|
Chris@16
|
4725 }
|
Chris@16
|
4726 }
|
Chris@101
|
4727
|
Chris@101
|
4728 ////////////////////////////////
|
Chris@101
|
4729 // template<typename F>
|
Chris@101
|
4730 // auto shared_future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
Chris@101
|
4731 ////////////////////////////////
|
Chris@101
|
4732
|
Chris@101
|
4733 template <typename R>
|
Chris@101
|
4734 template <typename F>
|
Chris@101
|
4735 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
|
Chris@101
|
4736 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const
|
Chris@16
|
4737 {
|
Chris@101
|
4738 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
|
Chris@101
|
4739 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@101
|
4740
|
Chris@101
|
4741 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4742 if (underlying_cast<int>(policy) & int(launch::async)) {
|
Chris@101
|
4743 lock.unlock();
|
Chris@101
|
4744 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@101
|
4745 lock, *this, boost::forward<F>(func)
|
Chris@101
|
4746 )));
|
Chris@101
|
4747 } else if (underlying_cast<int>(policy) & int(launch::deferred)) {
|
Chris@101
|
4748 this->future_->wait_internal(lock);
|
Chris@101
|
4749 lock.unlock();
|
Chris@101
|
4750 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@101
|
4751 lock, *this, boost::forward<F>(func)
|
Chris@101
|
4752 )));
|
Chris@101
|
4753 } else {
|
Chris@101
|
4754 lock.unlock();
|
Chris@101
|
4755 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@101
|
4756 lock, *this, boost::forward<F>(func)
|
Chris@101
|
4757 )));
|
Chris@101
|
4758 }
|
Chris@16
|
4759 }
|
Chris@101
|
4760 #ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
Chris@101
|
4761 template <typename R>
|
Chris@101
|
4762 template <typename Ex, typename F>
|
Chris@101
|
4763 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
|
Chris@101
|
4764 shared_future<R>::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const
|
Chris@101
|
4765 {
|
Chris@101
|
4766 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
|
Chris@101
|
4767 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@101
|
4768
|
Chris@101
|
4769 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4770 lock.unlock();
|
Chris@101
|
4771 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state<Ex, shared_future<R>, future_type, F>(ex,
|
Chris@101
|
4772 lock, *this, boost::forward<F>(func)
|
Chris@101
|
4773 )));
|
Chris@101
|
4774 }
|
Chris@101
|
4775 #endif
|
Chris@101
|
4776
|
Chris@101
|
4777 template <typename R>
|
Chris@101
|
4778 template <typename F>
|
Chris@101
|
4779 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
|
Chris@101
|
4780 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) const {
|
Chris@101
|
4781 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
|
Chris@101
|
4782
|
Chris@101
|
4783 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@101
|
4784
|
Chris@101
|
4785 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4786 if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) {
|
Chris@101
|
4787 lock.unlock();
|
Chris@101
|
4788 return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@101
|
4789 lock, *this, boost::forward<F>(func));
|
Chris@101
|
4790 } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) {
|
Chris@101
|
4791 this->future_->wait_internal(lock);
|
Chris@101
|
4792 lock.unlock();
|
Chris@101
|
4793 return boost::detail::make_shared_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@101
|
4794 lock, *this, boost::forward<F>(func));
|
Chris@101
|
4795 } else {
|
Chris@101
|
4796 lock.unlock();
|
Chris@101
|
4797 return boost::detail::make_shared_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@101
|
4798 lock, *this, boost::forward<F>(func));
|
Chris@101
|
4799 }
|
Chris@101
|
4800 }
|
Chris@101
|
4801
|
Chris@101
|
4802 namespace detail
|
Chris@101
|
4803 {
|
Chris@101
|
4804 template <typename T>
|
Chris@101
|
4805 struct mfallbacker_to
|
Chris@101
|
4806 {
|
Chris@101
|
4807 T value_;
|
Chris@101
|
4808 typedef T result_type;
|
Chris@101
|
4809 mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
|
Chris@101
|
4810 : value_(boost::move(v))
|
Chris@101
|
4811 {}
|
Chris@101
|
4812
|
Chris@101
|
4813 T operator()(BOOST_THREAD_FUTURE<T> fut) {
|
Chris@101
|
4814 return fut.get_or(boost::move(value_));
|
Chris@101
|
4815 }
|
Chris@101
|
4816 };
|
Chris@101
|
4817 template <typename T>
|
Chris@101
|
4818 struct cfallbacker_to
|
Chris@101
|
4819 {
|
Chris@101
|
4820 T value_;
|
Chris@101
|
4821 typedef T result_type;
|
Chris@101
|
4822 cfallbacker_to(T const& v)
|
Chris@101
|
4823 : value_(v)
|
Chris@101
|
4824 {}
|
Chris@101
|
4825
|
Chris@101
|
4826 T operator()(BOOST_THREAD_FUTURE<T> fut) const {
|
Chris@101
|
4827 return fut.get_or(value_);
|
Chris@101
|
4828
|
Chris@101
|
4829 }
|
Chris@101
|
4830 };
|
Chris@101
|
4831 }
|
Chris@16
|
4832 ////////////////////////////////
|
Chris@16
|
4833 // future<R> future<R>::fallback_to(R&& v);
|
Chris@16
|
4834 ////////////////////////////////
|
Chris@16
|
4835
|
Chris@16
|
4836 template <typename R>
|
Chris@16
|
4837 template <typename R2>
|
Chris@16
|
4838 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
|
Chris@101
|
4839 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) {
|
Chris@16
|
4840 return then(detail::mfallbacker_to<R>(boost::move(v)));
|
Chris@16
|
4841 }
|
Chris@16
|
4842
|
Chris@16
|
4843 template <typename R>
|
Chris@16
|
4844 template <typename R2>
|
Chris@16
|
4845 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
|
Chris@101
|
4846 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) {
|
Chris@16
|
4847 return then(detail::cfallbacker_to<R>(v));
|
Chris@16
|
4848 }
|
Chris@16
|
4849
|
Chris@16
|
4850 #endif
|
Chris@16
|
4851
|
Chris@16
|
4852 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@101
|
4853 namespace detail
|
Chris@101
|
4854 {
|
Chris@101
|
4855 /////////////////////////
|
Chris@101
|
4856 /// future_unwrap_shared_state
|
Chris@101
|
4857 /////////////////////////
|
Chris@101
|
4858
|
Chris@101
|
4859 template<typename F, typename Rp>
|
Chris@101
|
4860 struct future_unwrap_shared_state: shared_state<Rp>
|
Chris@16
|
4861 {
|
Chris@101
|
4862 F parent;
|
Chris@101
|
4863 public:
|
Chris@101
|
4864 explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f)
|
Chris@101
|
4865 : parent(boost::move(f)) {}
|
Chris@101
|
4866
|
Chris@101
|
4867 typename F::value_type parent_value(boost::unique_lock<boost::mutex>& ) {
|
Chris@101
|
4868 typename F::value_type r = parent.get();
|
Chris@101
|
4869 r.set_exceptional_if_invalid();
|
Chris@101
|
4870 return boost::move(r);
|
Chris@101
|
4871 }
|
Chris@101
|
4872
|
Chris@101
|
4873 virtual void wait(boost::unique_lock<boost::mutex>& lk, bool ) { // todo see if rethrow must be used
|
Chris@101
|
4874 parent_value(lk).wait();
|
Chris@101
|
4875 }
|
Chris@101
|
4876 virtual Rp get(boost::unique_lock<boost::mutex>& lk) {
|
Chris@101
|
4877 return parent_value(lk).get();
|
Chris@101
|
4878 }
|
Chris@101
|
4879 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@101
|
4880 typedef shared_ptr<shared_state_base> continuation_ptr_type;
|
Chris@101
|
4881
|
Chris@101
|
4882 virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
4883 {
|
Chris@101
|
4884 boost::unique_lock<boost::mutex> lk(parent.future_->mutex);
|
Chris@101
|
4885 parent.future_->set_continuation_ptr(continuation, lk);
|
Chris@16
|
4886 }
|
Chris@101
|
4887 #endif
|
Chris@101
|
4888 };
|
Chris@101
|
4889
|
Chris@101
|
4890 template <class F, class Rp>
|
Chris@101
|
4891 BOOST_THREAD_FUTURE<Rp>
|
Chris@101
|
4892 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) {
|
Chris@101
|
4893 shared_ptr<future_unwrap_shared_state<F, Rp> >
|
Chris@101
|
4894 h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
|
Chris@101
|
4895 lock.lock();
|
Chris@101
|
4896 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@101
|
4897 lock.unlock();
|
Chris@101
|
4898 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@16
|
4899 }
|
Chris@101
|
4900 }
|
Chris@16
|
4901
|
Chris@16
|
4902 template <typename R>
|
Chris@101
|
4903 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other)
|
Chris@101
|
4904 : base_type(other.unwrap()) {}
|
Chris@16
|
4905
|
Chris@16
|
4906 template <typename R2>
|
Chris@16
|
4907 BOOST_THREAD_FUTURE<R2>
|
Chris@16
|
4908 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
|
Chris@16
|
4909 {
|
Chris@16
|
4910 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
4911 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@101
|
4912 lock.unlock();
|
Chris@16
|
4913 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
|
Chris@16
|
4914 }
|
Chris@16
|
4915 #endif
|
Chris@101
|
4916
|
Chris@101
|
4917 #if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
Chris@101
|
4918 namespace detail
|
Chris@101
|
4919 {
|
Chris@101
|
4920 struct input_iterator_tag {};
|
Chris@101
|
4921 struct vector_tag {};
|
Chris@101
|
4922 struct values_tag {};
|
Chris@101
|
4923 template <typename T>
|
Chris@101
|
4924 struct alias_t { typedef T type; };
|
Chris@101
|
4925
|
Chris@101
|
4926 BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {};
|
Chris@101
|
4927 BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {};
|
Chris@101
|
4928 BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {};
|
Chris@101
|
4929 ////////////////////////////////
|
Chris@101
|
4930 // detail::future_async_when_all_shared_state
|
Chris@101
|
4931 ////////////////////////////////
|
Chris@101
|
4932 template<typename F>
|
Chris@101
|
4933 struct future_when_all_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
|
Chris@101
|
4934 {
|
Chris@101
|
4935 typedef csbl::vector<F> vector_type;
|
Chris@101
|
4936 typedef typename F::value_type value_type;
|
Chris@101
|
4937 vector_type vec_;
|
Chris@101
|
4938
|
Chris@101
|
4939 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
4940 future_when_all_vector_shared_state* that = dynamic_cast<future_when_all_vector_shared_state*>(that_.get());
|
Chris@101
|
4941 try {
|
Chris@101
|
4942 boost::wait_for_all(that->vec_.begin(), that->vec_.end());
|
Chris@101
|
4943 that->mark_finished_with_result(boost::move(that->vec_));
|
Chris@101
|
4944 } catch(...) {
|
Chris@101
|
4945 that->mark_exceptional_finish();
|
Chris@101
|
4946 }
|
Chris@101
|
4947 }
|
Chris@101
|
4948 bool run_deferred() {
|
Chris@101
|
4949
|
Chris@101
|
4950 bool res = false;
|
Chris@101
|
4951 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
|
Chris@101
|
4952 if (! it->run_if_is_deferred())
|
Chris@101
|
4953 {
|
Chris@101
|
4954 res = true;
|
Chris@101
|
4955 }
|
Chris@101
|
4956 }
|
Chris@101
|
4957 return res;
|
Chris@101
|
4958 }
|
Chris@101
|
4959 void init() {
|
Chris@101
|
4960 if (! run_deferred())
|
Chris@101
|
4961 {
|
Chris@101
|
4962 future_when_all_vector_shared_state::run(this->shared_from_this());
|
Chris@101
|
4963 return;
|
Chris@101
|
4964 }
|
Chris@101
|
4965 this->thr_ = thread(&future_when_all_vector_shared_state::run, this->shared_from_this());
|
Chris@101
|
4966 }
|
Chris@101
|
4967
|
Chris@101
|
4968 public:
|
Chris@101
|
4969 template< typename InputIterator>
|
Chris@101
|
4970 future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
|
Chris@101
|
4971 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
|
Chris@101
|
4972 {
|
Chris@101
|
4973 }
|
Chris@101
|
4974
|
Chris@101
|
4975 future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
|
Chris@101
|
4976 : vec_(boost::move(v))
|
Chris@101
|
4977 {
|
Chris@101
|
4978 }
|
Chris@101
|
4979
|
Chris@101
|
4980 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
4981 template< typename T0, typename ...T>
|
Chris@101
|
4982 future_when_all_vector_shared_state(values_tag, BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
|
Chris@101
|
4983 vec_.push_back(boost::forward<T0>(f));
|
Chris@101
|
4984 typename alias_t<char[]>::type{
|
Chris@101
|
4985 ( //first part of magic unpacker
|
Chris@101
|
4986 vec_.push_back(boost::forward<T>(futures)),'0'
|
Chris@101
|
4987 )..., '0'
|
Chris@101
|
4988 }; //second part of magic unpacker
|
Chris@101
|
4989 }
|
Chris@101
|
4990 #endif
|
Chris@101
|
4991
|
Chris@101
|
4992 ~future_when_all_vector_shared_state() {}
|
Chris@101
|
4993 };
|
Chris@101
|
4994
|
Chris@101
|
4995 ////////////////////////////////
|
Chris@101
|
4996 // detail::future_async_when_any_shared_state
|
Chris@101
|
4997 ////////////////////////////////
|
Chris@101
|
4998 template<typename F>
|
Chris@101
|
4999 struct future_when_any_vector_shared_state: future_async_shared_state_base<csbl::vector<F> >
|
Chris@101
|
5000 {
|
Chris@101
|
5001 typedef csbl::vector<F> vector_type;
|
Chris@101
|
5002 typedef typename F::value_type value_type;
|
Chris@101
|
5003 vector_type vec_;
|
Chris@101
|
5004
|
Chris@101
|
5005 static void run(shared_ptr<boost::detail::shared_state_base> that_)
|
Chris@101
|
5006 {
|
Chris@101
|
5007 future_when_any_vector_shared_state* that = dynamic_cast<future_when_any_vector_shared_state*>(that_.get());
|
Chris@101
|
5008 try {
|
Chris@101
|
5009 boost::wait_for_any(that->vec_.begin(), that->vec_.end());
|
Chris@101
|
5010 that->mark_finished_with_result(boost::move(that->vec_));
|
Chris@101
|
5011 } catch(...) {
|
Chris@101
|
5012 that->mark_exceptional_finish();
|
Chris@101
|
5013 }
|
Chris@101
|
5014 }
|
Chris@101
|
5015 bool run_deferred() {
|
Chris@101
|
5016
|
Chris@101
|
5017 for (typename csbl::vector<F>::iterator it = vec_.begin(); it != vec_.end(); ++it) {
|
Chris@101
|
5018 if (it->run_if_is_deferred_or_ready())
|
Chris@101
|
5019 {
|
Chris@101
|
5020 return true;
|
Chris@101
|
5021 }
|
Chris@101
|
5022 }
|
Chris@101
|
5023 return false;
|
Chris@101
|
5024 }
|
Chris@101
|
5025 void init() {
|
Chris@101
|
5026 if (run_deferred())
|
Chris@101
|
5027 {
|
Chris@101
|
5028 future_when_any_vector_shared_state::run(this->shared_from_this());
|
Chris@101
|
5029 return;
|
Chris@101
|
5030 }
|
Chris@101
|
5031
|
Chris@101
|
5032 this->thr_ = thread(&future_when_any_vector_shared_state::run, this->shared_from_this());
|
Chris@101
|
5033 }
|
Chris@101
|
5034
|
Chris@101
|
5035 public:
|
Chris@101
|
5036 template< typename InputIterator>
|
Chris@101
|
5037 future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last)
|
Chris@101
|
5038 : vec_(std::make_move_iterator(first), std::make_move_iterator(last))
|
Chris@101
|
5039 {
|
Chris@101
|
5040 }
|
Chris@101
|
5041
|
Chris@101
|
5042 future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v)
|
Chris@101
|
5043 : vec_(boost::move(v))
|
Chris@101
|
5044 {
|
Chris@101
|
5045 }
|
Chris@101
|
5046
|
Chris@101
|
5047 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
5048 template< typename T0, typename ...T>
|
Chris@101
|
5049 future_when_any_vector_shared_state(values_tag,
|
Chris@101
|
5050 BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures
|
Chris@101
|
5051 ) {
|
Chris@101
|
5052 vec_.push_back(boost::forward<T0>(f));
|
Chris@101
|
5053 typename alias_t<char[]>::type{
|
Chris@101
|
5054 ( //first part of magic unpacker
|
Chris@101
|
5055 vec_.push_back(boost::forward<T>(futures))
|
Chris@101
|
5056 ,'0'
|
Chris@101
|
5057 )...,
|
Chris@101
|
5058 '0'
|
Chris@101
|
5059 }; //second part of magic unpacker
|
Chris@101
|
5060 }
|
Chris@101
|
5061 #endif
|
Chris@101
|
5062
|
Chris@101
|
5063 ~future_when_any_vector_shared_state() {}
|
Chris@101
|
5064 };
|
Chris@101
|
5065
|
Chris@101
|
5066 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
5067 struct wait_for_all_fctr {
|
Chris@101
|
5068 template <class ...T>
|
Chris@101
|
5069 void operator()(T&&... v) {
|
Chris@101
|
5070 boost::wait_for_all(boost::forward<T>(v)...);
|
Chris@101
|
5071 }
|
Chris@101
|
5072 };
|
Chris@101
|
5073
|
Chris@101
|
5074 struct wait_for_any_fctr {
|
Chris@101
|
5075 template <class ...T>
|
Chris@101
|
5076 void operator()(T&&... v) {
|
Chris@101
|
5077 boost::wait_for_any(boost::forward<T>(v)...);
|
Chris@101
|
5078 }
|
Chris@101
|
5079 };
|
Chris@101
|
5080
|
Chris@101
|
5081
|
Chris@101
|
5082 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
|
Chris@101
|
5083 struct accumulate_run_if_is_deferred {
|
Chris@101
|
5084 bool operator ()(Tuple& t)
|
Chris@101
|
5085 {
|
Chris@101
|
5086 return (! csbl::get<i-1>(t).run_if_is_deferred()) || accumulate_run_if_is_deferred<Tuple,i-1>()(t);
|
Chris@101
|
5087 }
|
Chris@101
|
5088 };
|
Chris@101
|
5089 template <class Tuple>
|
Chris@101
|
5090 struct accumulate_run_if_is_deferred<Tuple, 0> {
|
Chris@101
|
5091 bool operator ()(Tuple& )
|
Chris@101
|
5092 {
|
Chris@101
|
5093 return false;
|
Chris@101
|
5094 }
|
Chris@101
|
5095 };
|
Chris@101
|
5096
|
Chris@101
|
5097
|
Chris@101
|
5098 template< typename Tuple, typename T0, typename ...T>
|
Chris@101
|
5099 struct future_when_all_tuple_shared_state: future_async_shared_state_base<Tuple>
|
Chris@101
|
5100 {
|
Chris@101
|
5101 Tuple tup_;
|
Chris@101
|
5102 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
|
Chris@101
|
5103
|
Chris@101
|
5104 static void run(shared_ptr<boost::detail::shared_state_base> that_) {
|
Chris@101
|
5105 future_when_all_tuple_shared_state* that = dynamic_cast<future_when_all_tuple_shared_state*>(that_.get());
|
Chris@101
|
5106 try {
|
Chris@101
|
5107 // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor());
|
Chris@101
|
5108 that->wait_for_all(Index());
|
Chris@101
|
5109
|
Chris@101
|
5110 that->mark_finished_with_result(boost::move(that->tup_));
|
Chris@101
|
5111 } catch(...) {
|
Chris@101
|
5112 that->mark_exceptional_finish();
|
Chris@101
|
5113 }
|
Chris@101
|
5114 }
|
Chris@101
|
5115
|
Chris@101
|
5116 template <size_t ...Indices>
|
Chris@101
|
5117 void wait_for_all(tuple_indices<Indices...>) {
|
Chris@101
|
5118 #if defined BOOST_THREAD_PROVIDES_INVOKE
|
Chris@101
|
5119 return invoke<void>(wait_for_all_fctr(), csbl::get<Indices>(tup_)...);
|
Chris@101
|
5120 #else
|
Chris@101
|
5121 return wait_for_all_fctr()(csbl::get<Indices>(tup_)...);
|
Chris@101
|
5122 #endif
|
Chris@101
|
5123 }
|
Chris@101
|
5124
|
Chris@101
|
5125 bool run_deferred() {
|
Chris@101
|
5126
|
Chris@101
|
5127 return accumulate_run_if_is_deferred<Tuple>()(tup_);
|
Chris@101
|
5128 }
|
Chris@101
|
5129 void init() {
|
Chris@101
|
5130 if (! run_deferred())
|
Chris@101
|
5131 {
|
Chris@101
|
5132 future_when_all_tuple_shared_state::run(this->shared_from_this());
|
Chris@101
|
5133 return;
|
Chris@101
|
5134 }
|
Chris@101
|
5135
|
Chris@101
|
5136 this->thr_ = thread(&future_when_all_tuple_shared_state::run, this->shared_from_this());
|
Chris@101
|
5137 }
|
Chris@101
|
5138 public:
|
Chris@101
|
5139 template< typename F, typename ...Fs>
|
Chris@101
|
5140 future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) :
|
Chris@101
|
5141 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
|
Chris@101
|
5142 {
|
Chris@101
|
5143 }
|
Chris@101
|
5144
|
Chris@101
|
5145 ~future_when_all_tuple_shared_state() {}
|
Chris@101
|
5146
|
Chris@101
|
5147 };
|
Chris@101
|
5148
|
Chris@101
|
5149
|
Chris@101
|
5150 template <class Tuple, std::size_t i=csbl::tuple_size<Tuple>::value>
|
Chris@101
|
5151 struct apply_any_run_if_is_deferred_or_ready {
|
Chris@101
|
5152 bool operator ()(Tuple& t)
|
Chris@101
|
5153 {
|
Chris@101
|
5154 if (csbl::get<i-1>(t).run_if_is_deferred_or_ready()) return true;
|
Chris@101
|
5155 return apply_any_run_if_is_deferred_or_ready<Tuple,i-1>()(t);
|
Chris@101
|
5156 }
|
Chris@101
|
5157 };
|
Chris@101
|
5158 template <class Tuple>
|
Chris@101
|
5159 struct apply_any_run_if_is_deferred_or_ready<Tuple, 0> {
|
Chris@101
|
5160 bool operator ()(Tuple& )
|
Chris@101
|
5161 {
|
Chris@101
|
5162 return false;
|
Chris@101
|
5163 }
|
Chris@101
|
5164 };
|
Chris@101
|
5165
|
Chris@101
|
5166 template< typename Tuple, typename T0, typename ...T >
|
Chris@101
|
5167 struct future_when_any_tuple_shared_state: future_async_shared_state_base<Tuple>
|
Chris@101
|
5168 {
|
Chris@101
|
5169 Tuple tup_;
|
Chris@101
|
5170 typedef typename make_tuple_indices<1+sizeof...(T)>::type Index;
|
Chris@101
|
5171
|
Chris@101
|
5172 static void run(shared_ptr<boost::detail::shared_state_base> that_)
|
Chris@101
|
5173 {
|
Chris@101
|
5174 future_when_any_tuple_shared_state* that = dynamic_cast<future_when_any_tuple_shared_state*>(that_.get());
|
Chris@101
|
5175 try {
|
Chris@101
|
5176 // TODO make use of apply(that->tup_, wait_for_any_fctr);
|
Chris@101
|
5177 that->wait_for_any(Index());
|
Chris@101
|
5178
|
Chris@101
|
5179 that->mark_finished_with_result(boost::move(that->tup_));
|
Chris@101
|
5180 } catch(...) {
|
Chris@101
|
5181 that->mark_exceptional_finish();
|
Chris@101
|
5182 }
|
Chris@101
|
5183 }
|
Chris@101
|
5184 template <size_t ...Indices>
|
Chris@101
|
5185 void wait_for_any(tuple_indices<Indices...>) {
|
Chris@101
|
5186 #if defined BOOST_THREAD_PROVIDES_INVOKE
|
Chris@101
|
5187 return invoke<void>(wait_for_any_fctr(), csbl::get<Indices>(tup_)...);
|
Chris@101
|
5188 #else
|
Chris@101
|
5189 return wait_for_any_fctr()(csbl::get<Indices>(tup_)...);
|
Chris@101
|
5190 #endif
|
Chris@101
|
5191 }
|
Chris@101
|
5192 bool run_deferred() {
|
Chris@101
|
5193 return apply_any_run_if_is_deferred_or_ready<Tuple>()(tup_);
|
Chris@101
|
5194 }
|
Chris@101
|
5195 void init() {
|
Chris@101
|
5196 if (run_deferred())
|
Chris@101
|
5197 {
|
Chris@101
|
5198 future_when_any_tuple_shared_state::run(this->shared_from_this());
|
Chris@101
|
5199 return;
|
Chris@101
|
5200 }
|
Chris@101
|
5201
|
Chris@101
|
5202 this->thr_ = thread(&future_when_any_tuple_shared_state::run, this->shared_from_this());
|
Chris@101
|
5203 }
|
Chris@101
|
5204
|
Chris@101
|
5205 public:
|
Chris@101
|
5206 template< typename F, typename ...Fs>
|
Chris@101
|
5207 future_when_any_tuple_shared_state(values_tag,
|
Chris@101
|
5208 BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures
|
Chris@101
|
5209 ) :
|
Chris@101
|
5210 tup_(boost::csbl::make_tuple(boost::forward<F>(f), boost::forward<Fs>(futures)...))
|
Chris@101
|
5211 {
|
Chris@101
|
5212 }
|
Chris@101
|
5213
|
Chris@101
|
5214 ~future_when_any_tuple_shared_state() {}
|
Chris@101
|
5215 };
|
Chris@101
|
5216 #endif
|
Chris@101
|
5217
|
Chris@101
|
5218 }
|
Chris@101
|
5219
|
Chris@101
|
5220 template< typename InputIterator>
|
Chris@101
|
5221 typename boost::disable_if<is_future_type<InputIterator>,
|
Chris@101
|
5222 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
|
Chris@101
|
5223 >::type
|
Chris@101
|
5224 when_all(InputIterator first, InputIterator last) {
|
Chris@101
|
5225 typedef typename InputIterator::value_type value_type;
|
Chris@101
|
5226 typedef csbl::vector<value_type> container_type;
|
Chris@101
|
5227 typedef detail::future_when_all_vector_shared_state<value_type> factory_type;
|
Chris@101
|
5228
|
Chris@101
|
5229 if (first==last) return make_ready_future(container_type());
|
Chris@101
|
5230 shared_ptr<factory_type >
|
Chris@101
|
5231 h(new factory_type(detail::input_iterator_tag_value, first,last));
|
Chris@101
|
5232 h->init();
|
Chris@101
|
5233 return BOOST_THREAD_FUTURE<container_type>(h);
|
Chris@101
|
5234 }
|
Chris@101
|
5235
|
Chris@101
|
5236 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all() {
|
Chris@101
|
5237 return make_ready_future(csbl::tuple<>());
|
Chris@101
|
5238 }
|
Chris@101
|
5239
|
Chris@101
|
5240 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
5241 template< typename T0, typename ...T>
|
Chris@101
|
5242 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
|
Chris@101
|
5243 when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
|
Chris@101
|
5244 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
|
Chris@101
|
5245 typedef detail::future_when_all_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
|
Chris@101
|
5246
|
Chris@101
|
5247 shared_ptr<factory_type>
|
Chris@101
|
5248 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
|
Chris@101
|
5249 h->init();
|
Chris@101
|
5250 return BOOST_THREAD_FUTURE<container_type>(h);
|
Chris@101
|
5251 }
|
Chris@101
|
5252 #endif
|
Chris@101
|
5253
|
Chris@101
|
5254 template< typename InputIterator>
|
Chris@101
|
5255 typename boost::disable_if<is_future_type<InputIterator>,
|
Chris@101
|
5256 BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> >
|
Chris@101
|
5257 >::type
|
Chris@101
|
5258 when_any(InputIterator first, InputIterator last) {
|
Chris@101
|
5259 typedef typename InputIterator::value_type value_type;
|
Chris@101
|
5260 typedef csbl::vector<value_type> container_type;
|
Chris@101
|
5261 typedef detail::future_when_any_vector_shared_state<value_type> factory_type;
|
Chris@101
|
5262
|
Chris@101
|
5263 if (first==last) return make_ready_future(container_type());
|
Chris@101
|
5264 shared_ptr<factory_type >
|
Chris@101
|
5265 h(new factory_type(detail::input_iterator_tag_value, first,last));
|
Chris@101
|
5266 h->init();
|
Chris@101
|
5267 return BOOST_THREAD_FUTURE<container_type>(h);
|
Chris@101
|
5268 }
|
Chris@101
|
5269
|
Chris@101
|
5270 inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any() {
|
Chris@101
|
5271 return make_ready_future(csbl::tuple<>());
|
Chris@101
|
5272 }
|
Chris@101
|
5273
|
Chris@101
|
5274 #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
Chris@101
|
5275 template< typename T0, typename ...T>
|
Chris@101
|
5276 BOOST_THREAD_FUTURE<csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> >
|
Chris@101
|
5277 when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) {
|
Chris@101
|
5278 typedef csbl::tuple<typename decay<T0>::type, typename decay<T>::type...> container_type;
|
Chris@101
|
5279 typedef detail::future_when_any_tuple_shared_state<container_type, typename decay<T0>::type, typename decay<T>::type...> factory_type;
|
Chris@101
|
5280
|
Chris@101
|
5281 shared_ptr<factory_type>
|
Chris@101
|
5282 h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...));
|
Chris@101
|
5283 h->init();
|
Chris@101
|
5284 return BOOST_THREAD_FUTURE<container_type>(h);
|
Chris@101
|
5285 }
|
Chris@101
|
5286 #endif
|
Chris@101
|
5287 #endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
|
Chris@16
|
5288 }
|
Chris@16
|
5289
|
Chris@16
|
5290 #endif // BOOST_NO_EXCEPTION
|
Chris@16
|
5291 #endif // header
|