Chris@16
|
1 // (C) Copyright 2008-10 Anthony Williams
|
Chris@16
|
2 // (C) Copyright 2011-2013 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@16
|
18 //#include <boost/thread/detail/log.hpp>
|
Chris@16
|
19 #include <boost/detail/scoped_enum_emulation.hpp>
|
Chris@16
|
20 #include <stdexcept>
|
Chris@16
|
21 #include <boost/thread/detail/move.hpp>
|
Chris@16
|
22 #include <boost/thread/detail/async_func.hpp>
|
Chris@16
|
23 #include <boost/thread/thread_time.hpp>
|
Chris@16
|
24 #include <boost/thread/mutex.hpp>
|
Chris@16
|
25 #include <boost/thread/condition_variable.hpp>
|
Chris@16
|
26 #include <boost/thread/lock_algorithms.hpp>
|
Chris@16
|
27 #include <boost/thread/lock_types.hpp>
|
Chris@16
|
28 #include <boost/exception_ptr.hpp>
|
Chris@16
|
29 #include <boost/shared_ptr.hpp>
|
Chris@16
|
30 #include <boost/scoped_ptr.hpp>
|
Chris@16
|
31 #include <boost/type_traits/is_fundamental.hpp>
|
Chris@16
|
32 #include <boost/thread/detail/is_convertible.hpp>
|
Chris@16
|
33 #include <boost/type_traits/remove_reference.hpp>
|
Chris@16
|
34 #include <boost/type_traits/remove_cv.hpp>
|
Chris@16
|
35 #include <boost/type_traits/is_void.hpp>
|
Chris@16
|
36 #include <boost/mpl/if.hpp>
|
Chris@16
|
37 #include <boost/config.hpp>
|
Chris@16
|
38 #include <boost/throw_exception.hpp>
|
Chris@16
|
39 #include <algorithm>
|
Chris@16
|
40 #include <boost/function.hpp>
|
Chris@16
|
41 #include <boost/bind.hpp>
|
Chris@16
|
42 #include <boost/ref.hpp>
|
Chris@16
|
43 #include <boost/scoped_array.hpp>
|
Chris@16
|
44 #include <boost/enable_shared_from_this.hpp>
|
Chris@16
|
45 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
46 #include <list>
|
Chris@16
|
47 #include <boost/next_prior.hpp>
|
Chris@16
|
48 #include <vector>
|
Chris@16
|
49
|
Chris@16
|
50 #include <boost/thread/future_error_code.hpp>
|
Chris@16
|
51 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
52 #include <boost/chrono/system_clocks.hpp>
|
Chris@16
|
53 #endif
|
Chris@16
|
54
|
Chris@16
|
55 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
56 #include <boost/thread/detail/memory.hpp>
|
Chris@16
|
57 #endif
|
Chris@16
|
58
|
Chris@16
|
59 #include <boost/utility/result_of.hpp>
|
Chris@16
|
60 #include <boost/thread/thread_only.hpp>
|
Chris@16
|
61
|
Chris@16
|
62 #if defined BOOST_THREAD_PROVIDES_FUTURE
|
Chris@16
|
63 #define BOOST_THREAD_FUTURE future
|
Chris@16
|
64 #else
|
Chris@16
|
65 #define BOOST_THREAD_FUTURE unique_future
|
Chris@16
|
66 #endif
|
Chris@16
|
67
|
Chris@16
|
68 namespace boost
|
Chris@16
|
69 {
|
Chris@16
|
70
|
Chris@16
|
71 //enum class launch
|
Chris@16
|
72 BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
|
Chris@16
|
73 {
|
Chris@16
|
74 none = 0,
|
Chris@16
|
75 async = 1,
|
Chris@16
|
76 deferred = 2,
|
Chris@16
|
77 any = async | deferred
|
Chris@16
|
78 }
|
Chris@16
|
79 BOOST_SCOPED_ENUM_DECLARE_END(launch)
|
Chris@16
|
80
|
Chris@16
|
81 //enum class future_status
|
Chris@16
|
82 BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
|
Chris@16
|
83 {
|
Chris@16
|
84 ready,
|
Chris@16
|
85 timeout,
|
Chris@16
|
86 deferred
|
Chris@16
|
87 }
|
Chris@16
|
88 BOOST_SCOPED_ENUM_DECLARE_END(future_status)
|
Chris@16
|
89
|
Chris@16
|
90 class BOOST_SYMBOL_VISIBLE future_error
|
Chris@16
|
91 : public std::logic_error
|
Chris@16
|
92 {
|
Chris@16
|
93 system::error_code ec_;
|
Chris@16
|
94 public:
|
Chris@16
|
95 future_error(system::error_code ec)
|
Chris@16
|
96 : logic_error(ec.message()),
|
Chris@16
|
97 ec_(ec)
|
Chris@16
|
98 {
|
Chris@16
|
99 }
|
Chris@16
|
100
|
Chris@16
|
101 const system::error_code& code() const BOOST_NOEXCEPT
|
Chris@16
|
102 {
|
Chris@16
|
103 return ec_;
|
Chris@16
|
104 }
|
Chris@16
|
105 };
|
Chris@16
|
106
|
Chris@16
|
107 class BOOST_SYMBOL_VISIBLE future_uninitialized:
|
Chris@16
|
108 public future_error
|
Chris@16
|
109 {
|
Chris@16
|
110 public:
|
Chris@16
|
111 future_uninitialized() :
|
Chris@16
|
112 future_error(system::make_error_code(future_errc::no_state))
|
Chris@16
|
113 {}
|
Chris@16
|
114 };
|
Chris@16
|
115 class BOOST_SYMBOL_VISIBLE broken_promise:
|
Chris@16
|
116 public future_error
|
Chris@16
|
117 {
|
Chris@16
|
118 public:
|
Chris@16
|
119 broken_promise():
|
Chris@16
|
120 future_error(system::make_error_code(future_errc::broken_promise))
|
Chris@16
|
121 {}
|
Chris@16
|
122 };
|
Chris@16
|
123 class BOOST_SYMBOL_VISIBLE future_already_retrieved:
|
Chris@16
|
124 public future_error
|
Chris@16
|
125 {
|
Chris@16
|
126 public:
|
Chris@16
|
127 future_already_retrieved():
|
Chris@16
|
128 future_error(system::make_error_code(future_errc::future_already_retrieved))
|
Chris@16
|
129 {}
|
Chris@16
|
130 };
|
Chris@16
|
131 class BOOST_SYMBOL_VISIBLE promise_already_satisfied:
|
Chris@16
|
132 public future_error
|
Chris@16
|
133 {
|
Chris@16
|
134 public:
|
Chris@16
|
135 promise_already_satisfied():
|
Chris@16
|
136 future_error(system::make_error_code(future_errc::promise_already_satisfied))
|
Chris@16
|
137 {}
|
Chris@16
|
138 };
|
Chris@16
|
139
|
Chris@16
|
140 class BOOST_SYMBOL_VISIBLE task_already_started:
|
Chris@16
|
141 public future_error
|
Chris@16
|
142 {
|
Chris@16
|
143 public:
|
Chris@16
|
144 task_already_started():
|
Chris@16
|
145 future_error(system::make_error_code(future_errc::promise_already_satisfied))
|
Chris@16
|
146 {}
|
Chris@16
|
147 };
|
Chris@16
|
148
|
Chris@16
|
149 class BOOST_SYMBOL_VISIBLE task_moved:
|
Chris@16
|
150 public future_error
|
Chris@16
|
151 {
|
Chris@16
|
152 public:
|
Chris@16
|
153 task_moved():
|
Chris@16
|
154 future_error(system::make_error_code(future_errc::no_state))
|
Chris@16
|
155 {}
|
Chris@16
|
156 };
|
Chris@16
|
157
|
Chris@16
|
158 class promise_moved:
|
Chris@16
|
159 public future_error
|
Chris@16
|
160 {
|
Chris@16
|
161 public:
|
Chris@16
|
162 promise_moved():
|
Chris@16
|
163 future_error(system::make_error_code(future_errc::no_state))
|
Chris@16
|
164 {}
|
Chris@16
|
165 };
|
Chris@16
|
166
|
Chris@16
|
167 namespace future_state
|
Chris@16
|
168 {
|
Chris@16
|
169 enum state { uninitialized, waiting, ready, moved, deferred };
|
Chris@16
|
170 }
|
Chris@16
|
171
|
Chris@16
|
172 namespace detail
|
Chris@16
|
173 {
|
Chris@16
|
174 struct relocker
|
Chris@16
|
175 {
|
Chris@16
|
176 boost::unique_lock<boost::mutex>& lock_;
|
Chris@16
|
177 bool unlocked_;
|
Chris@16
|
178
|
Chris@16
|
179 relocker(boost::unique_lock<boost::mutex>& lk):
|
Chris@16
|
180 lock_(lk)
|
Chris@16
|
181 {
|
Chris@16
|
182 lock_.unlock();
|
Chris@16
|
183 unlocked_=true;
|
Chris@16
|
184 }
|
Chris@16
|
185 ~relocker()
|
Chris@16
|
186 {
|
Chris@16
|
187 if (unlocked_) {
|
Chris@16
|
188 lock_.lock();
|
Chris@16
|
189 }
|
Chris@16
|
190 }
|
Chris@16
|
191 void lock() {
|
Chris@16
|
192 if (unlocked_) {
|
Chris@16
|
193 lock_.lock();
|
Chris@16
|
194 unlocked_=false;
|
Chris@16
|
195 }
|
Chris@16
|
196 }
|
Chris@16
|
197 private:
|
Chris@16
|
198 relocker& operator=(relocker const&);
|
Chris@16
|
199 };
|
Chris@16
|
200
|
Chris@16
|
201 struct shared_state_base : enable_shared_from_this<shared_state_base>
|
Chris@16
|
202 {
|
Chris@16
|
203 typedef std::list<boost::condition_variable_any*> waiter_list;
|
Chris@16
|
204 // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
|
Chris@16
|
205 typedef shared_ptr<shared_state_base> continuation_ptr_type;
|
Chris@16
|
206
|
Chris@16
|
207 boost::exception_ptr exception;
|
Chris@16
|
208 bool done;
|
Chris@16
|
209 bool is_deferred_;
|
Chris@16
|
210 launch policy_;
|
Chris@16
|
211 bool is_constructed;
|
Chris@16
|
212 mutable boost::mutex mutex;
|
Chris@16
|
213 boost::condition_variable waiters;
|
Chris@16
|
214 waiter_list external_waiters;
|
Chris@16
|
215 boost::function<void()> callback;
|
Chris@16
|
216 // This declaration should be only included conditionally if interruptions are allowed, but is included to maintain the same layout.
|
Chris@16
|
217 bool thread_was_interrupted;
|
Chris@16
|
218 // This declaration should be only included conditionally, but is included to maintain the same layout.
|
Chris@16
|
219 continuation_ptr_type continuation_ptr;
|
Chris@16
|
220
|
Chris@16
|
221 // This declaration should be only included conditionally, but is included to maintain the same layout.
|
Chris@16
|
222 virtual void launch_continuation(boost::unique_lock<boost::mutex>&)
|
Chris@16
|
223 {
|
Chris@16
|
224 }
|
Chris@16
|
225
|
Chris@16
|
226 shared_state_base():
|
Chris@16
|
227 done(false),
|
Chris@16
|
228 is_deferred_(false),
|
Chris@16
|
229 policy_(launch::none),
|
Chris@16
|
230 is_constructed(false),
|
Chris@16
|
231 thread_was_interrupted(false),
|
Chris@16
|
232 continuation_ptr()
|
Chris@16
|
233 {}
|
Chris@16
|
234 virtual ~shared_state_base()
|
Chris@16
|
235 {}
|
Chris@16
|
236
|
Chris@16
|
237 void set_deferred()
|
Chris@16
|
238 {
|
Chris@16
|
239 is_deferred_ = true;
|
Chris@16
|
240 policy_ = launch::deferred;
|
Chris@16
|
241 }
|
Chris@16
|
242 void set_async()
|
Chris@16
|
243 {
|
Chris@16
|
244 is_deferred_ = false;
|
Chris@16
|
245 policy_ = launch::async;
|
Chris@16
|
246 }
|
Chris@16
|
247
|
Chris@16
|
248 waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
|
Chris@16
|
249 {
|
Chris@16
|
250 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
251 do_callback(lock);
|
Chris@16
|
252 return external_waiters.insert(external_waiters.end(),&cv);
|
Chris@16
|
253 }
|
Chris@16
|
254
|
Chris@16
|
255 void remove_external_waiter(waiter_list::iterator it)
|
Chris@16
|
256 {
|
Chris@16
|
257 boost::lock_guard<boost::mutex> lock(mutex);
|
Chris@16
|
258 external_waiters.erase(it);
|
Chris@16
|
259 }
|
Chris@16
|
260
|
Chris@16
|
261 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
262 void do_continuation(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
263 {
|
Chris@16
|
264 if (continuation_ptr) {
|
Chris@16
|
265 continuation_ptr->launch_continuation(lock);
|
Chris@16
|
266 if (! lock.owns_lock())
|
Chris@16
|
267 lock.lock();
|
Chris@16
|
268 continuation_ptr.reset();
|
Chris@16
|
269 }
|
Chris@16
|
270 }
|
Chris@16
|
271 #else
|
Chris@16
|
272 void do_continuation(boost::unique_lock<boost::mutex>&)
|
Chris@16
|
273 {
|
Chris@16
|
274 }
|
Chris@16
|
275 #endif
|
Chris@16
|
276 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
277 void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
278 {
|
Chris@16
|
279 continuation_ptr= continuation;
|
Chris@16
|
280 if (done) {
|
Chris@16
|
281 do_continuation(lock);
|
Chris@16
|
282 }
|
Chris@16
|
283 }
|
Chris@16
|
284 #endif
|
Chris@16
|
285 void mark_finished_internal(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
286 {
|
Chris@16
|
287 done=true;
|
Chris@16
|
288 waiters.notify_all();
|
Chris@16
|
289 for(waiter_list::const_iterator it=external_waiters.begin(),
|
Chris@16
|
290 end=external_waiters.end();it!=end;++it)
|
Chris@16
|
291 {
|
Chris@16
|
292 (*it)->notify_all();
|
Chris@16
|
293 }
|
Chris@16
|
294 do_continuation(lock);
|
Chris@16
|
295 }
|
Chris@16
|
296 void make_ready()
|
Chris@16
|
297 {
|
Chris@16
|
298 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
299 mark_finished_internal(lock);
|
Chris@16
|
300 }
|
Chris@16
|
301
|
Chris@16
|
302 void do_callback(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
303 {
|
Chris@16
|
304 if(callback && !done)
|
Chris@16
|
305 {
|
Chris@16
|
306 boost::function<void()> local_callback=callback;
|
Chris@16
|
307 relocker relock(lock);
|
Chris@16
|
308 local_callback();
|
Chris@16
|
309 }
|
Chris@16
|
310 }
|
Chris@16
|
311
|
Chris@16
|
312 void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true)
|
Chris@16
|
313 {
|
Chris@16
|
314 do_callback(lk);
|
Chris@16
|
315 //if (!done) // fixme why this doesn't work?
|
Chris@16
|
316 {
|
Chris@16
|
317 if (is_deferred_)
|
Chris@16
|
318 {
|
Chris@16
|
319 is_deferred_=false;
|
Chris@16
|
320 execute(lk);
|
Chris@16
|
321 //lk.unlock();
|
Chris@16
|
322 }
|
Chris@16
|
323 else
|
Chris@16
|
324 {
|
Chris@16
|
325 while(!done)
|
Chris@16
|
326 {
|
Chris@16
|
327 waiters.wait(lk);
|
Chris@16
|
328 }
|
Chris@16
|
329 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
330 if(rethrow && thread_was_interrupted)
|
Chris@16
|
331 {
|
Chris@16
|
332 throw boost::thread_interrupted();
|
Chris@16
|
333 }
|
Chris@16
|
334 #endif
|
Chris@16
|
335 if(rethrow && exception)
|
Chris@16
|
336 {
|
Chris@16
|
337 boost::rethrow_exception(exception);
|
Chris@16
|
338 }
|
Chris@16
|
339 }
|
Chris@16
|
340 }
|
Chris@16
|
341 }
|
Chris@16
|
342
|
Chris@16
|
343 virtual void wait(bool rethrow=true)
|
Chris@16
|
344 {
|
Chris@16
|
345 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
346 wait_internal(lock, rethrow);
|
Chris@16
|
347 }
|
Chris@16
|
348
|
Chris@16
|
349 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
350 bool timed_wait_until(boost::system_time const& target_time)
|
Chris@16
|
351 {
|
Chris@16
|
352 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
353 if (is_deferred_)
|
Chris@16
|
354 return false;
|
Chris@16
|
355
|
Chris@16
|
356 do_callback(lock);
|
Chris@16
|
357 while(!done)
|
Chris@16
|
358 {
|
Chris@16
|
359 bool const success=waiters.timed_wait(lock,target_time);
|
Chris@16
|
360 if(!success && !done)
|
Chris@16
|
361 {
|
Chris@16
|
362 return false;
|
Chris@16
|
363 }
|
Chris@16
|
364 }
|
Chris@16
|
365 return true;
|
Chris@16
|
366 }
|
Chris@16
|
367 #endif
|
Chris@16
|
368 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
369
|
Chris@16
|
370 template <class Clock, class Duration>
|
Chris@16
|
371 future_status
|
Chris@16
|
372 wait_until(const chrono::time_point<Clock, Duration>& abs_time)
|
Chris@16
|
373 {
|
Chris@16
|
374 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
375 if (is_deferred_)
|
Chris@16
|
376 return future_status::deferred;
|
Chris@16
|
377 do_callback(lock);
|
Chris@16
|
378 while(!done)
|
Chris@16
|
379 {
|
Chris@16
|
380 cv_status const st=waiters.wait_until(lock,abs_time);
|
Chris@16
|
381 if(st==cv_status::timeout && !done)
|
Chris@16
|
382 {
|
Chris@16
|
383 return future_status::timeout;
|
Chris@16
|
384 }
|
Chris@16
|
385 }
|
Chris@16
|
386 return future_status::ready;
|
Chris@16
|
387 }
|
Chris@16
|
388 #endif
|
Chris@16
|
389 void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
390 {
|
Chris@16
|
391 exception=e;
|
Chris@16
|
392 mark_finished_internal(lock);
|
Chris@16
|
393 }
|
Chris@16
|
394
|
Chris@16
|
395 void mark_exceptional_finish()
|
Chris@16
|
396 {
|
Chris@16
|
397 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
398 mark_exceptional_finish_internal(boost::current_exception(), lock);
|
Chris@16
|
399 }
|
Chris@16
|
400
|
Chris@16
|
401 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
402 void mark_interrupted_finish()
|
Chris@16
|
403 {
|
Chris@16
|
404 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
405 thread_was_interrupted=true;
|
Chris@16
|
406 mark_finished_internal(lock);
|
Chris@16
|
407 }
|
Chris@16
|
408
|
Chris@16
|
409 void set_interrupted_at_thread_exit()
|
Chris@16
|
410 {
|
Chris@16
|
411 unique_lock<boost::mutex> lk(mutex);
|
Chris@16
|
412 thread_was_interrupted=true;
|
Chris@16
|
413 if (has_value(lk))
|
Chris@16
|
414 {
|
Chris@16
|
415 throw_exception(promise_already_satisfied());
|
Chris@16
|
416 }
|
Chris@16
|
417 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
418 }
|
Chris@16
|
419 #endif
|
Chris@16
|
420
|
Chris@16
|
421 void set_exception_at_thread_exit(exception_ptr e)
|
Chris@16
|
422 {
|
Chris@16
|
423 unique_lock<boost::mutex> lk(mutex);
|
Chris@16
|
424 if (has_value(lk))
|
Chris@16
|
425 {
|
Chris@16
|
426 throw_exception(promise_already_satisfied());
|
Chris@16
|
427 }
|
Chris@16
|
428 exception=e;
|
Chris@16
|
429 this->is_constructed = true;
|
Chris@16
|
430 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
431
|
Chris@16
|
432 }
|
Chris@16
|
433
|
Chris@16
|
434 bool has_value() const
|
Chris@16
|
435 {
|
Chris@16
|
436 boost::lock_guard<boost::mutex> lock(mutex);
|
Chris@16
|
437 return done && !(exception
|
Chris@16
|
438 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
439 || thread_was_interrupted
|
Chris@16
|
440 #endif
|
Chris@16
|
441 );
|
Chris@16
|
442 }
|
Chris@16
|
443
|
Chris@16
|
444 bool has_value(unique_lock<boost::mutex>& ) const
|
Chris@16
|
445 {
|
Chris@16
|
446 return done && !(exception
|
Chris@16
|
447 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
448 || thread_was_interrupted
|
Chris@16
|
449 #endif
|
Chris@16
|
450 );
|
Chris@16
|
451 }
|
Chris@16
|
452
|
Chris@16
|
453 bool has_exception() const
|
Chris@16
|
454 {
|
Chris@16
|
455 boost::lock_guard<boost::mutex> lock(mutex);
|
Chris@16
|
456 return done && (exception
|
Chris@16
|
457 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
458 || thread_was_interrupted
|
Chris@16
|
459 #endif
|
Chris@16
|
460 );
|
Chris@16
|
461 }
|
Chris@16
|
462
|
Chris@16
|
463 bool has_exception(unique_lock<boost::mutex>&) const
|
Chris@16
|
464 {
|
Chris@16
|
465 return done && (exception
|
Chris@16
|
466 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
467 || thread_was_interrupted
|
Chris@16
|
468 #endif
|
Chris@16
|
469 );
|
Chris@16
|
470 }
|
Chris@16
|
471
|
Chris@16
|
472 bool is_deferred(boost::lock_guard<boost::mutex>&) const {
|
Chris@16
|
473 return is_deferred_;
|
Chris@16
|
474 }
|
Chris@16
|
475
|
Chris@16
|
476 launch launch_policy(boost::unique_lock<boost::mutex>&) const
|
Chris@16
|
477 {
|
Chris@16
|
478 return policy_;
|
Chris@16
|
479 }
|
Chris@16
|
480
|
Chris@16
|
481 future_state::state get_state() const
|
Chris@16
|
482 {
|
Chris@16
|
483 boost::lock_guard<boost::mutex> guard(mutex);
|
Chris@16
|
484 if(!done)
|
Chris@16
|
485 {
|
Chris@16
|
486 return future_state::waiting;
|
Chris@16
|
487 }
|
Chris@16
|
488 else
|
Chris@16
|
489 {
|
Chris@16
|
490 return future_state::ready;
|
Chris@16
|
491 }
|
Chris@16
|
492 }
|
Chris@16
|
493
|
Chris@16
|
494 exception_ptr get_exception_ptr()
|
Chris@16
|
495 {
|
Chris@16
|
496 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
497 return get_exception_ptr(lock);
|
Chris@16
|
498 }
|
Chris@16
|
499 exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
500 {
|
Chris@16
|
501 wait_internal(lock, false);
|
Chris@16
|
502 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
503 if(thread_was_interrupted)
|
Chris@16
|
504 {
|
Chris@16
|
505 return copy_exception(boost::thread_interrupted());
|
Chris@16
|
506 }
|
Chris@16
|
507 #endif
|
Chris@16
|
508 return exception;
|
Chris@16
|
509 }
|
Chris@16
|
510
|
Chris@16
|
511 template<typename F,typename U>
|
Chris@16
|
512 void set_wait_callback(F f,U* u)
|
Chris@16
|
513 {
|
Chris@16
|
514 boost::lock_guard<boost::mutex> lock(mutex);
|
Chris@16
|
515 callback=boost::bind(f,boost::ref(*u));
|
Chris@16
|
516 }
|
Chris@16
|
517
|
Chris@16
|
518 virtual void execute(boost::unique_lock<boost::mutex>&) {}
|
Chris@16
|
519
|
Chris@16
|
520 private:
|
Chris@16
|
521 shared_state_base(shared_state_base const&);
|
Chris@16
|
522 shared_state_base& operator=(shared_state_base const&);
|
Chris@16
|
523 };
|
Chris@16
|
524
|
Chris@16
|
525 template<typename T>
|
Chris@16
|
526 struct future_traits
|
Chris@16
|
527 {
|
Chris@16
|
528 typedef boost::scoped_ptr<T> storage_type;
|
Chris@16
|
529 struct dummy;
|
Chris@16
|
530 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
531 typedef T const& source_reference_type;
|
Chris@16
|
532 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
|
Chris@16
|
533 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
|
Chris@16
|
534 //typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type;
|
Chris@16
|
535 typedef T move_dest_type;
|
Chris@16
|
536 #elif defined BOOST_THREAD_USES_MOVE
|
Chris@16
|
537 typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,T&>::type source_reference_type;
|
Chris@16
|
538 //typedef typename boost::mpl::if_c<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type;
|
Chris@16
|
539 //typedef typename boost::mpl::if_c<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
|
Chris@16
|
540 typedef BOOST_THREAD_RV_REF(T) rvalue_source_type;
|
Chris@16
|
541 typedef T move_dest_type;
|
Chris@16
|
542 #else
|
Chris@16
|
543 typedef T& source_reference_type;
|
Chris@16
|
544 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type;
|
Chris@16
|
545 typedef typename boost::mpl::if_<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type;
|
Chris@16
|
546 #endif
|
Chris@16
|
547
|
Chris@16
|
548
|
Chris@16
|
549 typedef const T& shared_future_get_result_type;
|
Chris@16
|
550
|
Chris@16
|
551 static void init(storage_type& storage,source_reference_type t)
|
Chris@16
|
552 {
|
Chris@16
|
553 storage.reset(new T(t));
|
Chris@16
|
554 }
|
Chris@16
|
555
|
Chris@16
|
556 static void init(storage_type& storage,rvalue_source_type t)
|
Chris@16
|
557 {
|
Chris@16
|
558 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
559 storage.reset(new T(boost::forward<T>(t)));
|
Chris@16
|
560 #else
|
Chris@16
|
561 storage.reset(new T(static_cast<rvalue_source_type>(t)));
|
Chris@16
|
562 #endif
|
Chris@16
|
563 }
|
Chris@16
|
564
|
Chris@16
|
565 static void cleanup(storage_type& storage)
|
Chris@16
|
566 {
|
Chris@16
|
567 storage.reset();
|
Chris@16
|
568 }
|
Chris@16
|
569 };
|
Chris@16
|
570
|
Chris@16
|
571 template<typename T>
|
Chris@16
|
572 struct future_traits<T&>
|
Chris@16
|
573 {
|
Chris@16
|
574 typedef T* storage_type;
|
Chris@16
|
575 typedef T& source_reference_type;
|
Chris@16
|
576 //struct rvalue_source_type
|
Chris@16
|
577 //{};
|
Chris@16
|
578 typedef T& move_dest_type;
|
Chris@16
|
579 typedef T& shared_future_get_result_type;
|
Chris@16
|
580
|
Chris@16
|
581 static void init(storage_type& storage,T& t)
|
Chris@16
|
582 {
|
Chris@16
|
583 storage=&t;
|
Chris@16
|
584 }
|
Chris@16
|
585
|
Chris@16
|
586 static void cleanup(storage_type& storage)
|
Chris@16
|
587 {
|
Chris@16
|
588 storage=0;
|
Chris@16
|
589 }
|
Chris@16
|
590 };
|
Chris@16
|
591
|
Chris@16
|
592 template<>
|
Chris@16
|
593 struct future_traits<void>
|
Chris@16
|
594 {
|
Chris@16
|
595 typedef bool storage_type;
|
Chris@16
|
596 typedef void move_dest_type;
|
Chris@16
|
597 typedef void shared_future_get_result_type;
|
Chris@16
|
598
|
Chris@16
|
599 static void init(storage_type& storage)
|
Chris@16
|
600 {
|
Chris@16
|
601 storage=true;
|
Chris@16
|
602 }
|
Chris@16
|
603
|
Chris@16
|
604 static void cleanup(storage_type& storage)
|
Chris@16
|
605 {
|
Chris@16
|
606 storage=false;
|
Chris@16
|
607 }
|
Chris@16
|
608
|
Chris@16
|
609 };
|
Chris@16
|
610
|
Chris@16
|
611 // Used to create stand-alone futures
|
Chris@16
|
612 template<typename T>
|
Chris@16
|
613 struct shared_state:
|
Chris@16
|
614 detail::shared_state_base
|
Chris@16
|
615 {
|
Chris@16
|
616 typedef typename future_traits<T>::storage_type storage_type;
|
Chris@16
|
617 typedef typename future_traits<T>::source_reference_type source_reference_type;
|
Chris@16
|
618 typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
|
Chris@16
|
619 typedef typename future_traits<T>::move_dest_type move_dest_type;
|
Chris@16
|
620 typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type;
|
Chris@16
|
621
|
Chris@16
|
622 storage_type result;
|
Chris@16
|
623
|
Chris@16
|
624 shared_state():
|
Chris@16
|
625 result(0)
|
Chris@16
|
626 {}
|
Chris@16
|
627
|
Chris@16
|
628 ~shared_state()
|
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 future_traits<T>::init(result,result_);
|
Chris@16
|
634 this->mark_finished_internal(lock);
|
Chris@16
|
635 }
|
Chris@16
|
636
|
Chris@16
|
637 void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
638 {
|
Chris@16
|
639 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
640 future_traits<T>::init(result,boost::forward<T>(result_));
|
Chris@16
|
641 #else
|
Chris@16
|
642 future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
|
Chris@16
|
643 #endif
|
Chris@16
|
644 this->mark_finished_internal(lock);
|
Chris@16
|
645 }
|
Chris@16
|
646
|
Chris@16
|
647 void mark_finished_with_result(source_reference_type result_)
|
Chris@16
|
648 {
|
Chris@16
|
649 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
650 this->mark_finished_with_result_internal(result_, lock);
|
Chris@16
|
651 }
|
Chris@16
|
652
|
Chris@16
|
653 void mark_finished_with_result(rvalue_source_type result_)
|
Chris@16
|
654 {
|
Chris@16
|
655 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
656
|
Chris@16
|
657 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
658 mark_finished_with_result_internal(boost::forward<T>(result_), lock);
|
Chris@16
|
659 #else
|
Chris@16
|
660 mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
|
Chris@16
|
661 #endif
|
Chris@16
|
662 }
|
Chris@16
|
663
|
Chris@16
|
664 virtual move_dest_type get()
|
Chris@16
|
665 {
|
Chris@16
|
666 wait();
|
Chris@16
|
667 return boost::move(*result);
|
Chris@16
|
668 }
|
Chris@16
|
669
|
Chris@16
|
670 virtual shared_future_get_result_type get_sh()
|
Chris@16
|
671 {
|
Chris@16
|
672 wait();
|
Chris@16
|
673 return *result;
|
Chris@16
|
674 }
|
Chris@16
|
675
|
Chris@16
|
676 //void set_value_at_thread_exit(const T & result_)
|
Chris@16
|
677 void set_value_at_thread_exit(source_reference_type result_)
|
Chris@16
|
678 {
|
Chris@16
|
679 unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
680 if (this->has_value(lk))
|
Chris@16
|
681 {
|
Chris@16
|
682 throw_exception(promise_already_satisfied());
|
Chris@16
|
683 }
|
Chris@16
|
684 //future_traits<T>::init(result,result_);
|
Chris@16
|
685 result.reset(new T(result_));
|
Chris@16
|
686
|
Chris@16
|
687 this->is_constructed = true;
|
Chris@16
|
688 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
689 }
|
Chris@16
|
690 //void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_)
|
Chris@16
|
691 void set_value_at_thread_exit(rvalue_source_type result_)
|
Chris@16
|
692 {
|
Chris@16
|
693 unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
694 if (this->has_value(lk))
|
Chris@16
|
695 throw_exception(promise_already_satisfied());
|
Chris@16
|
696 result.reset(new T(boost::move(result_)));
|
Chris@16
|
697 //future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
|
Chris@16
|
698 this->is_constructed = true;
|
Chris@16
|
699 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
700 }
|
Chris@16
|
701
|
Chris@16
|
702
|
Chris@16
|
703 private:
|
Chris@16
|
704 shared_state(shared_state const&);
|
Chris@16
|
705 shared_state& operator=(shared_state const&);
|
Chris@16
|
706 };
|
Chris@16
|
707
|
Chris@16
|
708 template<typename T>
|
Chris@16
|
709 struct shared_state<T&>:
|
Chris@16
|
710 detail::shared_state_base
|
Chris@16
|
711 {
|
Chris@16
|
712 typedef typename future_traits<T&>::storage_type storage_type;
|
Chris@16
|
713 typedef typename future_traits<T&>::source_reference_type source_reference_type;
|
Chris@16
|
714 typedef typename future_traits<T&>::move_dest_type move_dest_type;
|
Chris@16
|
715 typedef typename future_traits<T&>::shared_future_get_result_type shared_future_get_result_type;
|
Chris@16
|
716
|
Chris@16
|
717 T* result;
|
Chris@16
|
718
|
Chris@16
|
719 shared_state():
|
Chris@16
|
720 result(0)
|
Chris@16
|
721 {}
|
Chris@16
|
722
|
Chris@16
|
723 ~shared_state()
|
Chris@16
|
724 {
|
Chris@16
|
725 }
|
Chris@16
|
726
|
Chris@16
|
727 void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
728 {
|
Chris@16
|
729 //future_traits<T>::init(result,result_);
|
Chris@16
|
730 result= &result_;
|
Chris@16
|
731 mark_finished_internal(lock);
|
Chris@16
|
732 }
|
Chris@16
|
733
|
Chris@16
|
734 void mark_finished_with_result(source_reference_type result_)
|
Chris@16
|
735 {
|
Chris@16
|
736 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
737 mark_finished_with_result_internal(result_, lock);
|
Chris@16
|
738 }
|
Chris@16
|
739
|
Chris@16
|
740 virtual T& get()
|
Chris@16
|
741 {
|
Chris@16
|
742 wait();
|
Chris@16
|
743 return *result;
|
Chris@16
|
744 }
|
Chris@16
|
745
|
Chris@16
|
746 virtual T& get_sh()
|
Chris@16
|
747 {
|
Chris@16
|
748 wait();
|
Chris@16
|
749 return *result;
|
Chris@16
|
750 }
|
Chris@16
|
751
|
Chris@16
|
752 void set_value_at_thread_exit(T& result_)
|
Chris@16
|
753 {
|
Chris@16
|
754 unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
755 if (this->has_value(lk))
|
Chris@16
|
756 throw_exception(promise_already_satisfied());
|
Chris@16
|
757 //future_traits<T>::init(result,result_);
|
Chris@16
|
758 result= &result_;
|
Chris@16
|
759 this->is_constructed = true;
|
Chris@16
|
760 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
761 }
|
Chris@16
|
762
|
Chris@16
|
763 private:
|
Chris@16
|
764 shared_state(shared_state const&);
|
Chris@16
|
765 shared_state& operator=(shared_state const&);
|
Chris@16
|
766 };
|
Chris@16
|
767
|
Chris@16
|
768 template<>
|
Chris@16
|
769 struct shared_state<void>:
|
Chris@16
|
770 detail::shared_state_base
|
Chris@16
|
771 {
|
Chris@16
|
772 typedef void shared_future_get_result_type;
|
Chris@16
|
773
|
Chris@16
|
774 shared_state()
|
Chris@16
|
775 {}
|
Chris@16
|
776
|
Chris@16
|
777 void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
778 {
|
Chris@16
|
779 mark_finished_internal(lock);
|
Chris@16
|
780 }
|
Chris@16
|
781
|
Chris@16
|
782 void mark_finished_with_result()
|
Chris@16
|
783 {
|
Chris@16
|
784 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
785 mark_finished_with_result_internal(lock);
|
Chris@16
|
786 }
|
Chris@16
|
787
|
Chris@16
|
788 virtual void get()
|
Chris@16
|
789 {
|
Chris@16
|
790 this->wait();
|
Chris@16
|
791 }
|
Chris@16
|
792
|
Chris@16
|
793 virtual void get_sh()
|
Chris@16
|
794 {
|
Chris@16
|
795 wait();
|
Chris@16
|
796 }
|
Chris@16
|
797
|
Chris@16
|
798 void set_value_at_thread_exit()
|
Chris@16
|
799 {
|
Chris@16
|
800 unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
801 if (this->has_value(lk))
|
Chris@16
|
802 {
|
Chris@16
|
803 throw_exception(promise_already_satisfied());
|
Chris@16
|
804 }
|
Chris@16
|
805 this->is_constructed = true;
|
Chris@16
|
806 detail::make_ready_at_thread_exit(shared_from_this());
|
Chris@16
|
807 }
|
Chris@16
|
808 private:
|
Chris@16
|
809 shared_state(shared_state const&);
|
Chris@16
|
810 shared_state& operator=(shared_state const&);
|
Chris@16
|
811 };
|
Chris@16
|
812
|
Chris@16
|
813 /////////////////////////
|
Chris@16
|
814 /// future_async_shared_state_base
|
Chris@16
|
815 /////////////////////////
|
Chris@16
|
816 template<typename Rp>
|
Chris@16
|
817 struct future_async_shared_state_base: shared_state<Rp>
|
Chris@16
|
818 {
|
Chris@16
|
819 typedef shared_state<Rp> base_type;
|
Chris@16
|
820 protected:
|
Chris@16
|
821 boost::thread thr_;
|
Chris@16
|
822 void join()
|
Chris@16
|
823 {
|
Chris@16
|
824 if (thr_.joinable()) thr_.join();
|
Chris@16
|
825 }
|
Chris@16
|
826 public:
|
Chris@16
|
827 future_async_shared_state_base()
|
Chris@16
|
828 {
|
Chris@16
|
829 this->set_async();
|
Chris@16
|
830 }
|
Chris@16
|
831 explicit future_async_shared_state_base(BOOST_THREAD_RV_REF(boost::thread) th) :
|
Chris@16
|
832 thr_(boost::move(th))
|
Chris@16
|
833 {
|
Chris@16
|
834 this->set_async();
|
Chris@16
|
835 }
|
Chris@16
|
836
|
Chris@16
|
837 ~future_async_shared_state_base()
|
Chris@16
|
838 {
|
Chris@16
|
839 join();
|
Chris@16
|
840 }
|
Chris@16
|
841
|
Chris@16
|
842 virtual void wait(bool rethrow)
|
Chris@16
|
843 {
|
Chris@16
|
844 join();
|
Chris@16
|
845 this->base_type::wait(rethrow);
|
Chris@16
|
846 }
|
Chris@16
|
847 };
|
Chris@16
|
848
|
Chris@16
|
849 /////////////////////////
|
Chris@16
|
850 /// future_async_shared_state
|
Chris@16
|
851 /////////////////////////
|
Chris@16
|
852 template<typename Rp, typename Fp>
|
Chris@16
|
853 struct future_async_shared_state: future_async_shared_state_base<Rp>
|
Chris@16
|
854 {
|
Chris@16
|
855 typedef future_async_shared_state_base<Rp> base_type;
|
Chris@16
|
856
|
Chris@16
|
857 public:
|
Chris@16
|
858 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) :
|
Chris@16
|
859 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f)))
|
Chris@16
|
860 {
|
Chris@16
|
861 }
|
Chris@16
|
862
|
Chris@16
|
863 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
864 {
|
Chris@16
|
865 try
|
Chris@16
|
866 {
|
Chris@16
|
867 that->mark_finished_with_result(f());
|
Chris@16
|
868 }
|
Chris@16
|
869 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
870 catch(thread_interrupted& )
|
Chris@16
|
871 {
|
Chris@16
|
872 that->mark_interrupted_finish();
|
Chris@16
|
873 }
|
Chris@16
|
874 #endif
|
Chris@16
|
875 catch(...)
|
Chris@16
|
876 {
|
Chris@16
|
877 that->mark_exceptional_finish();
|
Chris@16
|
878 }
|
Chris@16
|
879 }
|
Chris@16
|
880 };
|
Chris@16
|
881
|
Chris@16
|
882 template<typename Fp>
|
Chris@16
|
883 struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void>
|
Chris@16
|
884 {
|
Chris@16
|
885 typedef future_async_shared_state_base<void> base_type;
|
Chris@16
|
886
|
Chris@16
|
887 public:
|
Chris@16
|
888 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) :
|
Chris@16
|
889 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f)))
|
Chris@16
|
890 {
|
Chris@16
|
891 }
|
Chris@16
|
892
|
Chris@16
|
893 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
894 {
|
Chris@16
|
895 try
|
Chris@16
|
896 {
|
Chris@16
|
897 f();
|
Chris@16
|
898 that->mark_finished_with_result();
|
Chris@16
|
899 }
|
Chris@16
|
900 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
901 catch(thread_interrupted& )
|
Chris@16
|
902 {
|
Chris@16
|
903 that->mark_interrupted_finish();
|
Chris@16
|
904 }
|
Chris@16
|
905 #endif
|
Chris@16
|
906 catch(...)
|
Chris@16
|
907 {
|
Chris@16
|
908 that->mark_exceptional_finish();
|
Chris@16
|
909 }
|
Chris@16
|
910 }
|
Chris@16
|
911 };
|
Chris@16
|
912
|
Chris@16
|
913 template<typename Rp, typename Fp>
|
Chris@16
|
914 struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&>
|
Chris@16
|
915 {
|
Chris@16
|
916 typedef future_async_shared_state_base<Rp&> base_type;
|
Chris@16
|
917
|
Chris@16
|
918 public:
|
Chris@16
|
919 explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) :
|
Chris@16
|
920 base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f)))
|
Chris@16
|
921 {
|
Chris@16
|
922 }
|
Chris@16
|
923
|
Chris@16
|
924 static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
925 {
|
Chris@16
|
926 try
|
Chris@16
|
927 {
|
Chris@16
|
928 that->mark_finished_with_result(f());
|
Chris@16
|
929 }
|
Chris@16
|
930 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
931 catch(thread_interrupted& )
|
Chris@16
|
932 {
|
Chris@16
|
933 that->mark_interrupted_finish();
|
Chris@16
|
934 }
|
Chris@16
|
935 #endif
|
Chris@16
|
936 catch(...)
|
Chris@16
|
937 {
|
Chris@16
|
938 that->mark_exceptional_finish();
|
Chris@16
|
939 }
|
Chris@16
|
940 }
|
Chris@16
|
941 };
|
Chris@16
|
942
|
Chris@16
|
943 //////////////////////////
|
Chris@16
|
944 /// future_deferred_shared_state
|
Chris@16
|
945 //////////////////////////
|
Chris@16
|
946 template<typename Rp, typename Fp>
|
Chris@16
|
947 struct future_deferred_shared_state: shared_state<Rp>
|
Chris@16
|
948 {
|
Chris@16
|
949 typedef shared_state<Rp> base_type;
|
Chris@16
|
950 Fp func_;
|
Chris@16
|
951
|
Chris@16
|
952 public:
|
Chris@16
|
953 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
954 : func_(boost::forward<Fp>(f))
|
Chris@16
|
955 {
|
Chris@16
|
956 this->set_deferred();
|
Chris@16
|
957 }
|
Chris@16
|
958
|
Chris@16
|
959 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@16
|
960 try
|
Chris@16
|
961 {
|
Chris@16
|
962 Fp local_fuct=boost::move(func_);
|
Chris@16
|
963 relocker relock(lck);
|
Chris@16
|
964 Rp res = local_fuct();
|
Chris@16
|
965 relock.lock();
|
Chris@16
|
966 this->mark_finished_with_result_internal(boost::move(res), lck);
|
Chris@16
|
967 }
|
Chris@16
|
968 catch (...)
|
Chris@16
|
969 {
|
Chris@16
|
970 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@16
|
971 }
|
Chris@16
|
972 }
|
Chris@16
|
973 };
|
Chris@16
|
974 template<typename Rp, typename Fp>
|
Chris@16
|
975 struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&>
|
Chris@16
|
976 {
|
Chris@16
|
977 typedef shared_state<Rp&> base_type;
|
Chris@16
|
978 Fp func_;
|
Chris@16
|
979
|
Chris@16
|
980 public:
|
Chris@16
|
981 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
982 : func_(boost::forward<Fp>(f))
|
Chris@16
|
983 {
|
Chris@16
|
984 this->set_deferred();
|
Chris@16
|
985 }
|
Chris@16
|
986
|
Chris@16
|
987 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@16
|
988 try
|
Chris@16
|
989 {
|
Chris@16
|
990 this->mark_finished_with_result_internal(func_(), lck);
|
Chris@16
|
991 }
|
Chris@16
|
992 catch (...)
|
Chris@16
|
993 {
|
Chris@16
|
994 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@16
|
995 }
|
Chris@16
|
996 }
|
Chris@16
|
997 };
|
Chris@16
|
998
|
Chris@16
|
999 template<typename Fp>
|
Chris@16
|
1000 struct future_deferred_shared_state<void,Fp>: shared_state<void>
|
Chris@16
|
1001 {
|
Chris@16
|
1002 typedef shared_state<void> base_type;
|
Chris@16
|
1003 Fp func_;
|
Chris@16
|
1004
|
Chris@16
|
1005 public:
|
Chris@16
|
1006 explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
1007 : func_(boost::forward<Fp>(f))
|
Chris@16
|
1008 {
|
Chris@16
|
1009 this->set_deferred();
|
Chris@16
|
1010 }
|
Chris@16
|
1011
|
Chris@16
|
1012 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@16
|
1013 try
|
Chris@16
|
1014 {
|
Chris@16
|
1015 Fp local_fuct=boost::move(func_);
|
Chris@16
|
1016 relocker relock(lck);
|
Chris@16
|
1017 local_fuct();
|
Chris@16
|
1018 relock.lock();
|
Chris@16
|
1019 this->mark_finished_with_result_internal(lck);
|
Chris@16
|
1020 }
|
Chris@16
|
1021 catch (...)
|
Chris@16
|
1022 {
|
Chris@16
|
1023 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@16
|
1024 }
|
Chris@16
|
1025 }
|
Chris@16
|
1026 };
|
Chris@16
|
1027
|
Chris@16
|
1028 // template<typename T, typename Allocator>
|
Chris@16
|
1029 // struct shared_state_alloc: public shared_state<T>
|
Chris@16
|
1030 // {
|
Chris@16
|
1031 // typedef shared_state<T> base;
|
Chris@16
|
1032 // Allocator alloc_;
|
Chris@16
|
1033 //
|
Chris@16
|
1034 // public:
|
Chris@16
|
1035 // explicit shared_state_alloc(const Allocator& a)
|
Chris@16
|
1036 // : alloc_(a) {}
|
Chris@16
|
1037 //
|
Chris@16
|
1038 // };
|
Chris@16
|
1039 class future_waiter
|
Chris@16
|
1040 {
|
Chris@16
|
1041 struct registered_waiter;
|
Chris@16
|
1042 typedef std::vector<int>::size_type count_type;
|
Chris@16
|
1043
|
Chris@16
|
1044 struct registered_waiter
|
Chris@16
|
1045 {
|
Chris@16
|
1046 boost::shared_ptr<detail::shared_state_base> future_;
|
Chris@16
|
1047 detail::shared_state_base::waiter_list::iterator wait_iterator;
|
Chris@16
|
1048 count_type index;
|
Chris@16
|
1049
|
Chris@16
|
1050 registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future,
|
Chris@16
|
1051 detail::shared_state_base::waiter_list::iterator wait_iterator_,
|
Chris@16
|
1052 count_type index_):
|
Chris@16
|
1053 future_(a_future),wait_iterator(wait_iterator_),index(index_)
|
Chris@16
|
1054 {}
|
Chris@16
|
1055 };
|
Chris@16
|
1056
|
Chris@16
|
1057 struct all_futures_lock
|
Chris@16
|
1058 {
|
Chris@16
|
1059 #ifdef _MANAGED
|
Chris@16
|
1060 typedef std::ptrdiff_t count_type_portable;
|
Chris@16
|
1061 #else
|
Chris@16
|
1062 typedef count_type count_type_portable;
|
Chris@16
|
1063 #endif
|
Chris@16
|
1064 count_type_portable count;
|
Chris@16
|
1065 boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
|
Chris@16
|
1066
|
Chris@16
|
1067 all_futures_lock(std::vector<registered_waiter>& futures):
|
Chris@16
|
1068 count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
|
Chris@16
|
1069 {
|
Chris@16
|
1070 for(count_type_portable i=0;i<count;++i)
|
Chris@16
|
1071 {
|
Chris@16
|
1072 #if defined __DECCXX || defined __SUNPRO_CC || defined __hpux
|
Chris@16
|
1073 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move();
|
Chris@16
|
1074 #else
|
Chris@16
|
1075 locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex);
|
Chris@16
|
1076 #endif
|
Chris@16
|
1077 }
|
Chris@16
|
1078 }
|
Chris@16
|
1079
|
Chris@16
|
1080 void lock()
|
Chris@16
|
1081 {
|
Chris@16
|
1082 boost::lock(locks.get(),locks.get()+count);
|
Chris@16
|
1083 }
|
Chris@16
|
1084
|
Chris@16
|
1085 void unlock()
|
Chris@16
|
1086 {
|
Chris@16
|
1087 for(count_type_portable i=0;i<count;++i)
|
Chris@16
|
1088 {
|
Chris@16
|
1089 locks[i].unlock();
|
Chris@16
|
1090 }
|
Chris@16
|
1091 }
|
Chris@16
|
1092 };
|
Chris@16
|
1093
|
Chris@16
|
1094 boost::condition_variable_any cv;
|
Chris@16
|
1095 std::vector<registered_waiter> futures;
|
Chris@16
|
1096 count_type future_count;
|
Chris@16
|
1097
|
Chris@16
|
1098 public:
|
Chris@16
|
1099 future_waiter():
|
Chris@16
|
1100 future_count(0)
|
Chris@16
|
1101 {}
|
Chris@16
|
1102
|
Chris@16
|
1103 template<typename F>
|
Chris@16
|
1104 void add(F& f)
|
Chris@16
|
1105 {
|
Chris@16
|
1106 if(f.future_)
|
Chris@16
|
1107 {
|
Chris@16
|
1108 futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count));
|
Chris@16
|
1109 }
|
Chris@16
|
1110 ++future_count;
|
Chris@16
|
1111 }
|
Chris@16
|
1112
|
Chris@16
|
1113 count_type wait()
|
Chris@16
|
1114 {
|
Chris@16
|
1115 all_futures_lock lk(futures);
|
Chris@16
|
1116 for(;;)
|
Chris@16
|
1117 {
|
Chris@16
|
1118 for(count_type i=0;i<futures.size();++i)
|
Chris@16
|
1119 {
|
Chris@16
|
1120 if(futures[i].future_->done)
|
Chris@16
|
1121 {
|
Chris@16
|
1122 return futures[i].index;
|
Chris@16
|
1123 }
|
Chris@16
|
1124 }
|
Chris@16
|
1125 cv.wait(lk);
|
Chris@16
|
1126 }
|
Chris@16
|
1127 }
|
Chris@16
|
1128
|
Chris@16
|
1129 ~future_waiter()
|
Chris@16
|
1130 {
|
Chris@16
|
1131 for(count_type i=0;i<futures.size();++i)
|
Chris@16
|
1132 {
|
Chris@16
|
1133 futures[i].future_->remove_external_waiter(futures[i].wait_iterator);
|
Chris@16
|
1134 }
|
Chris@16
|
1135 }
|
Chris@16
|
1136
|
Chris@16
|
1137 };
|
Chris@16
|
1138
|
Chris@16
|
1139 }
|
Chris@16
|
1140
|
Chris@16
|
1141 template <typename R>
|
Chris@16
|
1142 class BOOST_THREAD_FUTURE;
|
Chris@16
|
1143
|
Chris@16
|
1144 template <typename R>
|
Chris@16
|
1145 class shared_future;
|
Chris@16
|
1146
|
Chris@16
|
1147 template<typename T>
|
Chris@16
|
1148 struct is_future_type
|
Chris@16
|
1149 {
|
Chris@16
|
1150 BOOST_STATIC_CONSTANT(bool, value=false);
|
Chris@16
|
1151 typedef void type;
|
Chris@16
|
1152 };
|
Chris@16
|
1153
|
Chris@16
|
1154 template<typename T>
|
Chris@16
|
1155 struct is_future_type<BOOST_THREAD_FUTURE<T> >
|
Chris@16
|
1156 {
|
Chris@16
|
1157 BOOST_STATIC_CONSTANT(bool, value=true);
|
Chris@16
|
1158 typedef T type;
|
Chris@16
|
1159 };
|
Chris@16
|
1160
|
Chris@16
|
1161 template<typename T>
|
Chris@16
|
1162 struct is_future_type<shared_future<T> >
|
Chris@16
|
1163 {
|
Chris@16
|
1164 BOOST_STATIC_CONSTANT(bool, value=true);
|
Chris@16
|
1165 typedef T type;
|
Chris@16
|
1166 };
|
Chris@16
|
1167
|
Chris@16
|
1168 template<typename Iterator>
|
Chris@16
|
1169 typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
|
Chris@16
|
1170 {
|
Chris@16
|
1171 for(Iterator current=begin;current!=end;++current)
|
Chris@16
|
1172 {
|
Chris@16
|
1173 current->wait();
|
Chris@16
|
1174 }
|
Chris@16
|
1175 }
|
Chris@16
|
1176
|
Chris@16
|
1177 template<typename F1,typename F2>
|
Chris@16
|
1178 typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2)
|
Chris@16
|
1179 {
|
Chris@16
|
1180 f1.wait();
|
Chris@16
|
1181 f2.wait();
|
Chris@16
|
1182 }
|
Chris@16
|
1183
|
Chris@16
|
1184 template<typename F1,typename F2,typename F3>
|
Chris@16
|
1185 void wait_for_all(F1& f1,F2& f2,F3& f3)
|
Chris@16
|
1186 {
|
Chris@16
|
1187 f1.wait();
|
Chris@16
|
1188 f2.wait();
|
Chris@16
|
1189 f3.wait();
|
Chris@16
|
1190 }
|
Chris@16
|
1191
|
Chris@16
|
1192 template<typename F1,typename F2,typename F3,typename F4>
|
Chris@16
|
1193 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
|
Chris@16
|
1194 {
|
Chris@16
|
1195 f1.wait();
|
Chris@16
|
1196 f2.wait();
|
Chris@16
|
1197 f3.wait();
|
Chris@16
|
1198 f4.wait();
|
Chris@16
|
1199 }
|
Chris@16
|
1200
|
Chris@16
|
1201 template<typename F1,typename F2,typename F3,typename F4,typename F5>
|
Chris@16
|
1202 void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
|
Chris@16
|
1203 {
|
Chris@16
|
1204 f1.wait();
|
Chris@16
|
1205 f2.wait();
|
Chris@16
|
1206 f3.wait();
|
Chris@16
|
1207 f4.wait();
|
Chris@16
|
1208 f5.wait();
|
Chris@16
|
1209 }
|
Chris@16
|
1210
|
Chris@16
|
1211 template<typename Iterator>
|
Chris@16
|
1212 typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end)
|
Chris@16
|
1213 {
|
Chris@16
|
1214 if(begin==end)
|
Chris@16
|
1215 return end;
|
Chris@16
|
1216
|
Chris@16
|
1217 detail::future_waiter waiter;
|
Chris@16
|
1218 for(Iterator current=begin;current!=end;++current)
|
Chris@16
|
1219 {
|
Chris@16
|
1220 waiter.add(*current);
|
Chris@16
|
1221 }
|
Chris@16
|
1222 return boost::next(begin,waiter.wait());
|
Chris@16
|
1223 }
|
Chris@16
|
1224
|
Chris@16
|
1225 template<typename F1,typename F2>
|
Chris@16
|
1226 typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2)
|
Chris@16
|
1227 {
|
Chris@16
|
1228 detail::future_waiter waiter;
|
Chris@16
|
1229 waiter.add(f1);
|
Chris@16
|
1230 waiter.add(f2);
|
Chris@16
|
1231 return waiter.wait();
|
Chris@16
|
1232 }
|
Chris@16
|
1233
|
Chris@16
|
1234 template<typename F1,typename F2,typename F3>
|
Chris@16
|
1235 unsigned wait_for_any(F1& f1,F2& f2,F3& f3)
|
Chris@16
|
1236 {
|
Chris@16
|
1237 detail::future_waiter waiter;
|
Chris@16
|
1238 waiter.add(f1);
|
Chris@16
|
1239 waiter.add(f2);
|
Chris@16
|
1240 waiter.add(f3);
|
Chris@16
|
1241 return waiter.wait();
|
Chris@16
|
1242 }
|
Chris@16
|
1243
|
Chris@16
|
1244 template<typename F1,typename F2,typename F3,typename F4>
|
Chris@16
|
1245 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4)
|
Chris@16
|
1246 {
|
Chris@16
|
1247 detail::future_waiter waiter;
|
Chris@16
|
1248 waiter.add(f1);
|
Chris@16
|
1249 waiter.add(f2);
|
Chris@16
|
1250 waiter.add(f3);
|
Chris@16
|
1251 waiter.add(f4);
|
Chris@16
|
1252 return waiter.wait();
|
Chris@16
|
1253 }
|
Chris@16
|
1254
|
Chris@16
|
1255 template<typename F1,typename F2,typename F3,typename F4,typename F5>
|
Chris@16
|
1256 unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
|
Chris@16
|
1257 {
|
Chris@16
|
1258 detail::future_waiter waiter;
|
Chris@16
|
1259 waiter.add(f1);
|
Chris@16
|
1260 waiter.add(f2);
|
Chris@16
|
1261 waiter.add(f3);
|
Chris@16
|
1262 waiter.add(f4);
|
Chris@16
|
1263 waiter.add(f5);
|
Chris@16
|
1264 return waiter.wait();
|
Chris@16
|
1265 }
|
Chris@16
|
1266
|
Chris@16
|
1267 template <typename R>
|
Chris@16
|
1268 class promise;
|
Chris@16
|
1269
|
Chris@16
|
1270 template <typename R>
|
Chris@16
|
1271 class packaged_task;
|
Chris@16
|
1272
|
Chris@16
|
1273 namespace detail
|
Chris@16
|
1274 {
|
Chris@16
|
1275 /// Common implementation for all the futures independently of the return type
|
Chris@16
|
1276 class base_future
|
Chris@16
|
1277 {
|
Chris@16
|
1278 //BOOST_THREAD_MOVABLE(base_future)
|
Chris@16
|
1279
|
Chris@16
|
1280 };
|
Chris@16
|
1281 /// Common implementation for future and shared_future.
|
Chris@16
|
1282 template <typename R>
|
Chris@16
|
1283 class basic_future : public base_future
|
Chris@16
|
1284 {
|
Chris@16
|
1285 protected:
|
Chris@16
|
1286 public:
|
Chris@16
|
1287
|
Chris@16
|
1288 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
|
Chris@16
|
1289
|
Chris@16
|
1290 future_ptr future_;
|
Chris@16
|
1291
|
Chris@16
|
1292 basic_future(future_ptr a_future):
|
Chris@16
|
1293 future_(a_future)
|
Chris@16
|
1294 {
|
Chris@16
|
1295 }
|
Chris@16
|
1296 // Copy construction from a shared_future
|
Chris@16
|
1297 explicit basic_future(const shared_future<R>&) BOOST_NOEXCEPT;
|
Chris@16
|
1298
|
Chris@16
|
1299 public:
|
Chris@16
|
1300 typedef future_state::state state;
|
Chris@16
|
1301
|
Chris@16
|
1302 BOOST_THREAD_MOVABLE(basic_future)
|
Chris@16
|
1303 basic_future(): future_() {}
|
Chris@16
|
1304 ~basic_future() {}
|
Chris@16
|
1305
|
Chris@16
|
1306 basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT:
|
Chris@16
|
1307 future_(BOOST_THREAD_RV(other).future_)
|
Chris@16
|
1308 {
|
Chris@16
|
1309 BOOST_THREAD_RV(other).future_.reset();
|
Chris@16
|
1310 }
|
Chris@16
|
1311 basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT
|
Chris@16
|
1312 {
|
Chris@16
|
1313 future_=BOOST_THREAD_RV(other).future_;
|
Chris@16
|
1314 BOOST_THREAD_RV(other).future_.reset();
|
Chris@16
|
1315 return *this;
|
Chris@16
|
1316 }
|
Chris@16
|
1317 void swap(basic_future& that) BOOST_NOEXCEPT
|
Chris@16
|
1318 {
|
Chris@16
|
1319 future_.swap(that.future_);
|
Chris@16
|
1320 }
|
Chris@16
|
1321 // functions to check state, and wait for ready
|
Chris@16
|
1322 state get_state() const
|
Chris@16
|
1323 {
|
Chris@16
|
1324 if(!future_)
|
Chris@16
|
1325 {
|
Chris@16
|
1326 return future_state::uninitialized;
|
Chris@16
|
1327 }
|
Chris@16
|
1328 return future_->get_state();
|
Chris@16
|
1329 }
|
Chris@16
|
1330
|
Chris@16
|
1331 bool is_ready() const
|
Chris@16
|
1332 {
|
Chris@16
|
1333 return get_state()==future_state::ready;
|
Chris@16
|
1334 }
|
Chris@16
|
1335
|
Chris@16
|
1336 bool has_exception() const
|
Chris@16
|
1337 {
|
Chris@16
|
1338 return future_ && future_->has_exception();
|
Chris@16
|
1339 }
|
Chris@16
|
1340
|
Chris@16
|
1341 bool has_value() const
|
Chris@16
|
1342 {
|
Chris@16
|
1343 return future_ && future_->has_value();
|
Chris@16
|
1344 }
|
Chris@16
|
1345
|
Chris@16
|
1346 launch launch_policy(boost::unique_lock<boost::mutex>& lk) const
|
Chris@16
|
1347 {
|
Chris@16
|
1348 if ( future_ ) return future_->launch_policy(lk);
|
Chris@16
|
1349 else return launch(launch::none);
|
Chris@16
|
1350 }
|
Chris@16
|
1351
|
Chris@16
|
1352 exception_ptr get_exception_ptr()
|
Chris@16
|
1353 {
|
Chris@16
|
1354 return future_
|
Chris@16
|
1355 ? future_->get_exception_ptr()
|
Chris@16
|
1356 : exception_ptr();
|
Chris@16
|
1357 }
|
Chris@16
|
1358
|
Chris@16
|
1359 bool valid() const BOOST_NOEXCEPT
|
Chris@16
|
1360 {
|
Chris@16
|
1361 return future_ != 0;
|
Chris@16
|
1362 }
|
Chris@16
|
1363
|
Chris@16
|
1364
|
Chris@16
|
1365 void wait() const
|
Chris@16
|
1366 {
|
Chris@16
|
1367 if(!future_)
|
Chris@16
|
1368 {
|
Chris@16
|
1369 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1370 }
|
Chris@16
|
1371 future_->wait(false);
|
Chris@16
|
1372 }
|
Chris@16
|
1373
|
Chris@16
|
1374 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
1375 template<typename Duration>
|
Chris@16
|
1376 bool timed_wait(Duration const& rel_time) const
|
Chris@16
|
1377 {
|
Chris@16
|
1378 return timed_wait_until(boost::get_system_time()+rel_time);
|
Chris@16
|
1379 }
|
Chris@16
|
1380
|
Chris@16
|
1381 bool timed_wait_until(boost::system_time const& abs_time) const
|
Chris@16
|
1382 {
|
Chris@16
|
1383 if(!future_)
|
Chris@16
|
1384 {
|
Chris@16
|
1385 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1386 }
|
Chris@16
|
1387 return future_->timed_wait_until(abs_time);
|
Chris@16
|
1388 }
|
Chris@16
|
1389 #endif
|
Chris@16
|
1390 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
1391 template <class Rep, class Period>
|
Chris@16
|
1392 future_status
|
Chris@16
|
1393 wait_for(const chrono::duration<Rep, Period>& rel_time) const
|
Chris@16
|
1394 {
|
Chris@16
|
1395 return wait_until(chrono::steady_clock::now() + rel_time);
|
Chris@16
|
1396
|
Chris@16
|
1397 }
|
Chris@16
|
1398 template <class Clock, class Duration>
|
Chris@16
|
1399 future_status
|
Chris@16
|
1400 wait_until(const chrono::time_point<Clock, Duration>& abs_time) const
|
Chris@16
|
1401 {
|
Chris@16
|
1402 if(!future_)
|
Chris@16
|
1403 {
|
Chris@16
|
1404 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1405 }
|
Chris@16
|
1406 return future_->wait_until(abs_time);
|
Chris@16
|
1407 }
|
Chris@16
|
1408 #endif
|
Chris@16
|
1409
|
Chris@16
|
1410 };
|
Chris@16
|
1411
|
Chris@16
|
1412 } // detail
|
Chris@16
|
1413 BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@16
|
1414
|
Chris@16
|
1415 namespace detail
|
Chris@16
|
1416 {
|
Chris@16
|
1417 #if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005
|
Chris@16
|
1418 template <class Rp, class Fp>
|
Chris@16
|
1419 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1420 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1421
|
Chris@16
|
1422 template <class Rp, class Fp>
|
Chris@16
|
1423 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1424 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1425 #endif // #if (!defined _MSC_VER || _MSC_VER >= 1400)
|
Chris@16
|
1426 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1427 template<typename F, typename Rp, typename Fp>
|
Chris@16
|
1428 struct future_deferred_continuation_shared_state;
|
Chris@16
|
1429 template<typename F, typename Rp, typename Fp>
|
Chris@16
|
1430 struct future_async_continuation_shared_state;
|
Chris@16
|
1431
|
Chris@16
|
1432 template <class F, class Rp, class Fp>
|
Chris@16
|
1433 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1434 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
|
1435
|
Chris@16
|
1436 template <class F, class Rp, class Fp>
|
Chris@16
|
1437 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1438 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
|
1439 #endif
|
Chris@16
|
1440 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1441 template<typename F, typename Rp>
|
Chris@16
|
1442 struct future_unwrap_shared_state;
|
Chris@16
|
1443 template <class F, class Rp>
|
Chris@16
|
1444 inline BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1445 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
|
Chris@16
|
1446 #endif
|
Chris@16
|
1447 }
|
Chris@16
|
1448
|
Chris@16
|
1449 template <typename R>
|
Chris@16
|
1450 class BOOST_THREAD_FUTURE : public detail::basic_future<R>
|
Chris@16
|
1451 {
|
Chris@16
|
1452 private:
|
Chris@16
|
1453 typedef detail::basic_future<R> base_type;
|
Chris@16
|
1454 typedef typename base_type::future_ptr future_ptr;
|
Chris@16
|
1455
|
Chris@16
|
1456 friend class shared_future<R>;
|
Chris@16
|
1457 friend class promise<R>;
|
Chris@16
|
1458 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1459 template <typename, typename, typename>
|
Chris@16
|
1460 friend struct detail::future_async_continuation_shared_state;
|
Chris@16
|
1461 template <typename, typename, typename>
|
Chris@16
|
1462 friend struct detail::future_deferred_continuation_shared_state;
|
Chris@16
|
1463
|
Chris@16
|
1464 template <class F, class Rp, class Fp>
|
Chris@16
|
1465 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1466 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
|
1467
|
Chris@16
|
1468 template <class F, class Rp, class Fp>
|
Chris@16
|
1469 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1470 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
|
1471 #endif
|
Chris@16
|
1472 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1473 template<typename F, typename Rp>
|
Chris@16
|
1474 friend struct detail::future_unwrap_shared_state;
|
Chris@16
|
1475 template <class F, class Rp>
|
Chris@16
|
1476 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1477 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
|
Chris@16
|
1478 #endif
|
Chris@16
|
1479 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
1480 template <class> friend class packaged_task; // todo check if this works in windows
|
Chris@16
|
1481 #else
|
Chris@16
|
1482 friend class packaged_task<R>;
|
Chris@16
|
1483 #endif
|
Chris@16
|
1484 friend class detail::future_waiter;
|
Chris@16
|
1485
|
Chris@16
|
1486 template <class Rp, class Fp>
|
Chris@16
|
1487 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1488 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1489
|
Chris@16
|
1490 template <class Rp, class Fp>
|
Chris@16
|
1491 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1492 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1493
|
Chris@16
|
1494
|
Chris@16
|
1495 typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
|
Chris@16
|
1496
|
Chris@16
|
1497 BOOST_THREAD_FUTURE(future_ptr a_future):
|
Chris@16
|
1498 base_type(a_future)
|
Chris@16
|
1499 {
|
Chris@16
|
1500 }
|
Chris@16
|
1501
|
Chris@16
|
1502 public:
|
Chris@16
|
1503 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
|
Chris@16
|
1504 typedef future_state::state state;
|
Chris@16
|
1505 typedef R value_type; // EXTENSION
|
Chris@16
|
1506
|
Chris@16
|
1507 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
|
Chris@16
|
1508
|
Chris@16
|
1509 ~BOOST_THREAD_FUTURE() {}
|
Chris@16
|
1510
|
Chris@16
|
1511 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
|
Chris@16
|
1512 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
Chris@16
|
1513 {
|
Chris@16
|
1514 }
|
Chris@16
|
1515 inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION
|
Chris@16
|
1516
|
Chris@16
|
1517 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
|
Chris@16
|
1518 {
|
Chris@16
|
1519 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
|
Chris@16
|
1520 return *this;
|
Chris@16
|
1521 }
|
Chris@16
|
1522
|
Chris@16
|
1523 shared_future<R> share()
|
Chris@16
|
1524 {
|
Chris@16
|
1525 return shared_future<R>(::boost::move(*this));
|
Chris@16
|
1526 }
|
Chris@16
|
1527
|
Chris@16
|
1528 void swap(BOOST_THREAD_FUTURE& other)
|
Chris@16
|
1529 {
|
Chris@16
|
1530 static_cast<base_type*>(this)->swap(other);
|
Chris@16
|
1531 }
|
Chris@16
|
1532
|
Chris@16
|
1533 // todo this function must be private and friendship provided to the internal users.
|
Chris@16
|
1534 void set_async()
|
Chris@16
|
1535 {
|
Chris@16
|
1536 this->future_->set_async();
|
Chris@16
|
1537 }
|
Chris@16
|
1538 // todo this function must be private and friendship provided to the internal users.
|
Chris@16
|
1539 void set_deferred()
|
Chris@16
|
1540 {
|
Chris@16
|
1541 this->future_->set_deferred();
|
Chris@16
|
1542 }
|
Chris@16
|
1543
|
Chris@16
|
1544 // retrieving the value
|
Chris@16
|
1545 move_dest_type get()
|
Chris@16
|
1546 {
|
Chris@16
|
1547 if(!this->future_)
|
Chris@16
|
1548 {
|
Chris@16
|
1549 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1550 }
|
Chris@16
|
1551 future_ptr fut_=this->future_;
|
Chris@16
|
1552 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@16
|
1553 this->future_.reset();
|
Chris@16
|
1554 #endif
|
Chris@16
|
1555 return fut_->get();
|
Chris@16
|
1556 }
|
Chris@16
|
1557
|
Chris@16
|
1558 template <typename R2>
|
Chris@16
|
1559 typename boost::disable_if< is_void<R2>, move_dest_type>::type
|
Chris@16
|
1560 get_or(BOOST_THREAD_RV_REF(R2) v)
|
Chris@16
|
1561 {
|
Chris@16
|
1562 if(!this->future_)
|
Chris@16
|
1563 {
|
Chris@16
|
1564 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1565 }
|
Chris@16
|
1566 this->future_->wait(false);
|
Chris@16
|
1567 future_ptr fut_=this->future_;
|
Chris@16
|
1568 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@16
|
1569 this->future_.reset();
|
Chris@16
|
1570 #endif
|
Chris@16
|
1571 if (fut_->has_value()) {
|
Chris@16
|
1572 return fut_->get();
|
Chris@16
|
1573 }
|
Chris@16
|
1574 else {
|
Chris@16
|
1575 return boost::move(v);
|
Chris@16
|
1576 }
|
Chris@16
|
1577 }
|
Chris@16
|
1578
|
Chris@16
|
1579 template <typename R2>
|
Chris@16
|
1580 typename boost::disable_if< is_void<R2>, move_dest_type>::type
|
Chris@16
|
1581 get_or(R2 const& v) // EXTENSION
|
Chris@16
|
1582 {
|
Chris@16
|
1583 if(!this->future_)
|
Chris@16
|
1584 {
|
Chris@16
|
1585 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1586 }
|
Chris@16
|
1587 this->future_->wait(false);
|
Chris@16
|
1588 future_ptr fut_=this->future_;
|
Chris@16
|
1589 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@16
|
1590 this->future_.reset();
|
Chris@16
|
1591 #endif
|
Chris@16
|
1592 if (fut_->has_value()) {
|
Chris@16
|
1593 return fut_->get();
|
Chris@16
|
1594 }
|
Chris@16
|
1595 else {
|
Chris@16
|
1596 return v;
|
Chris@16
|
1597 }
|
Chris@16
|
1598 }
|
Chris@16
|
1599
|
Chris@16
|
1600
|
Chris@16
|
1601 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1602
|
Chris@16
|
1603 // template<typename F>
|
Chris@16
|
1604 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
Chris@16
|
1605
|
Chris@16
|
1606 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
1607 // template<typename RF>
|
Chris@16
|
1608 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
|
Chris@16
|
1609 // template<typename RF>
|
Chris@16
|
1610 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&));
|
Chris@16
|
1611 //#endif
|
Chris@16
|
1612 template<typename F>
|
Chris@16
|
1613 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@16
|
1614 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@16
|
1615 template<typename F>
|
Chris@16
|
1616 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@16
|
1617 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@16
|
1618
|
Chris@16
|
1619 template <typename R2>
|
Chris@16
|
1620 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
|
Chris@16
|
1621 fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION
|
Chris@16
|
1622 template <typename R2>
|
Chris@16
|
1623 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
|
Chris@16
|
1624 fallback_to(R2 const& v); // EXTENSION
|
Chris@16
|
1625
|
Chris@16
|
1626 #endif
|
Chris@16
|
1627
|
Chris@16
|
1628 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1629 // inline
|
Chris@16
|
1630 // typename boost::enable_if<
|
Chris@16
|
1631 // is_future_type<value_type>,
|
Chris@16
|
1632 // value_type
|
Chris@16
|
1633 // //BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type>
|
Chris@16
|
1634 // >::type
|
Chris@16
|
1635 // unwrap();
|
Chris@16
|
1636 //#endif
|
Chris@16
|
1637
|
Chris@16
|
1638 };
|
Chris@16
|
1639
|
Chris@16
|
1640 BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@16
|
1641
|
Chris@16
|
1642 template <typename R2>
|
Chris@16
|
1643 class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> >
|
Chris@16
|
1644 {
|
Chris@16
|
1645 typedef BOOST_THREAD_FUTURE<R2> R;
|
Chris@16
|
1646
|
Chris@16
|
1647 private:
|
Chris@16
|
1648 typedef detail::basic_future<R> base_type;
|
Chris@16
|
1649 typedef typename base_type::future_ptr future_ptr;
|
Chris@16
|
1650
|
Chris@16
|
1651 friend class shared_future<R>;
|
Chris@16
|
1652 friend class promise<R>;
|
Chris@16
|
1653 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1654 template <typename, typename, typename>
|
Chris@16
|
1655 friend struct detail::future_async_continuation_shared_state;
|
Chris@16
|
1656 template <typename, typename, typename>
|
Chris@16
|
1657 friend struct detail::future_deferred_continuation_shared_state;
|
Chris@16
|
1658
|
Chris@16
|
1659 template <class F, class Rp, class Fp>
|
Chris@16
|
1660 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1661 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
|
1662
|
Chris@16
|
1663 template <class F, class Rp, class Fp>
|
Chris@16
|
1664 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1665 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
|
1666 #endif
|
Chris@16
|
1667 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1668 template<typename F, typename Rp>
|
Chris@16
|
1669 friend struct detail::future_unwrap_shared_state;
|
Chris@16
|
1670 template <class F, class Rp>
|
Chris@16
|
1671 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1672 detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f);
|
Chris@16
|
1673 #endif
|
Chris@16
|
1674 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
1675 template <class> friend class packaged_task; // todo check if this works in windows
|
Chris@16
|
1676 #else
|
Chris@16
|
1677 friend class packaged_task<R>;
|
Chris@16
|
1678 #endif
|
Chris@16
|
1679 friend class detail::future_waiter;
|
Chris@16
|
1680
|
Chris@16
|
1681 template <class Rp, class Fp>
|
Chris@16
|
1682 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1683 detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1684
|
Chris@16
|
1685 template <class Rp, class Fp>
|
Chris@16
|
1686 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1687 detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f);
|
Chris@16
|
1688
|
Chris@16
|
1689
|
Chris@16
|
1690 typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
|
Chris@16
|
1691
|
Chris@16
|
1692 BOOST_THREAD_FUTURE(future_ptr a_future):
|
Chris@16
|
1693 base_type(a_future)
|
Chris@16
|
1694 {
|
Chris@16
|
1695 }
|
Chris@16
|
1696
|
Chris@16
|
1697 public:
|
Chris@16
|
1698 BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE)
|
Chris@16
|
1699 typedef future_state::state state;
|
Chris@16
|
1700 typedef R value_type; // EXTENSION
|
Chris@16
|
1701
|
Chris@16
|
1702 BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {}
|
Chris@16
|
1703
|
Chris@16
|
1704 ~BOOST_THREAD_FUTURE() {}
|
Chris@16
|
1705
|
Chris@16
|
1706 BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT:
|
Chris@16
|
1707 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
Chris@16
|
1708 {
|
Chris@16
|
1709 }
|
Chris@16
|
1710
|
Chris@16
|
1711 BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT
|
Chris@16
|
1712 {
|
Chris@16
|
1713 this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
|
Chris@16
|
1714 return *this;
|
Chris@16
|
1715 }
|
Chris@16
|
1716
|
Chris@16
|
1717 shared_future<R> share()
|
Chris@16
|
1718 {
|
Chris@16
|
1719 return shared_future<R>(::boost::move(*this));
|
Chris@16
|
1720 }
|
Chris@16
|
1721
|
Chris@16
|
1722 void swap(BOOST_THREAD_FUTURE& other)
|
Chris@16
|
1723 {
|
Chris@16
|
1724 static_cast<base_type*>(this)->swap(other);
|
Chris@16
|
1725 }
|
Chris@16
|
1726
|
Chris@16
|
1727 // todo this function must be private and friendship provided to the internal users.
|
Chris@16
|
1728 void set_async()
|
Chris@16
|
1729 {
|
Chris@16
|
1730 this->future_->set_async();
|
Chris@16
|
1731 }
|
Chris@16
|
1732 // todo this function must be private and friendship provided to the internal users.
|
Chris@16
|
1733 void set_deferred()
|
Chris@16
|
1734 {
|
Chris@16
|
1735 this->future_->set_deferred();
|
Chris@16
|
1736 }
|
Chris@16
|
1737
|
Chris@16
|
1738 // retrieving the value
|
Chris@16
|
1739 move_dest_type get()
|
Chris@16
|
1740 {
|
Chris@16
|
1741 if(!this->future_)
|
Chris@16
|
1742 {
|
Chris@16
|
1743 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1744 }
|
Chris@16
|
1745 future_ptr fut_=this->future_;
|
Chris@16
|
1746 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@16
|
1747 this->future_.reset();
|
Chris@16
|
1748 #endif
|
Chris@16
|
1749 return fut_->get();
|
Chris@16
|
1750 }
|
Chris@16
|
1751 move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION
|
Chris@16
|
1752 {
|
Chris@16
|
1753 if(!this->future_)
|
Chris@16
|
1754 {
|
Chris@16
|
1755 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1756 }
|
Chris@16
|
1757 this->future_->wait(false);
|
Chris@16
|
1758 future_ptr fut_=this->future_;
|
Chris@16
|
1759 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@16
|
1760 this->future_.reset();
|
Chris@16
|
1761 #endif
|
Chris@16
|
1762 if (fut_->has_value()) return fut_->get();
|
Chris@16
|
1763 else return boost::move(v);
|
Chris@16
|
1764 }
|
Chris@16
|
1765
|
Chris@16
|
1766 move_dest_type get_or(R const& v) // EXTENSION
|
Chris@16
|
1767 {
|
Chris@16
|
1768 if(!this->future_)
|
Chris@16
|
1769 {
|
Chris@16
|
1770 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1771 }
|
Chris@16
|
1772 this->future_->wait(false);
|
Chris@16
|
1773 future_ptr fut_=this->future_;
|
Chris@16
|
1774 #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
|
Chris@16
|
1775 this->future_.reset();
|
Chris@16
|
1776 #endif
|
Chris@16
|
1777 if (fut_->has_value()) return fut_->get();
|
Chris@16
|
1778 else return v;
|
Chris@16
|
1779 }
|
Chris@16
|
1780
|
Chris@16
|
1781
|
Chris@16
|
1782 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1783
|
Chris@16
|
1784 // template<typename F>
|
Chris@16
|
1785 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
Chris@16
|
1786
|
Chris@16
|
1787 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
1788 // template<typename RF>
|
Chris@16
|
1789 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&));
|
Chris@16
|
1790 // template<typename RF>
|
Chris@16
|
1791 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&));
|
Chris@16
|
1792 //#endif
|
Chris@16
|
1793 template<typename F>
|
Chris@16
|
1794 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@16
|
1795 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@16
|
1796 template<typename F>
|
Chris@16
|
1797 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type>
|
Chris@16
|
1798 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@16
|
1799 #endif
|
Chris@16
|
1800
|
Chris@16
|
1801 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1802 inline
|
Chris@16
|
1803 BOOST_THREAD_FUTURE<R2>
|
Chris@16
|
1804 unwrap(); // EXTENSION
|
Chris@16
|
1805 #endif
|
Chris@16
|
1806
|
Chris@16
|
1807 };
|
Chris@16
|
1808
|
Chris@16
|
1809 template <typename R>
|
Chris@16
|
1810 class shared_future : public detail::basic_future<R>
|
Chris@16
|
1811 {
|
Chris@16
|
1812
|
Chris@16
|
1813 typedef detail::basic_future<R> base_type;
|
Chris@16
|
1814 typedef typename base_type::future_ptr future_ptr;
|
Chris@16
|
1815
|
Chris@16
|
1816 friend class detail::future_waiter;
|
Chris@16
|
1817 friend class promise<R>;
|
Chris@16
|
1818
|
Chris@16
|
1819 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1820 template <typename, typename, typename>
|
Chris@16
|
1821 friend struct detail::future_async_continuation_shared_state;
|
Chris@16
|
1822 template <typename, typename, typename>
|
Chris@16
|
1823 friend struct detail::future_deferred_continuation_shared_state;
|
Chris@16
|
1824
|
Chris@16
|
1825 template <class F, class Rp, class Fp>
|
Chris@16
|
1826 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1827 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
|
1828
|
Chris@16
|
1829 template <class F, class Rp, class Fp>
|
Chris@16
|
1830 friend BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
1831 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
|
1832 #endif
|
Chris@16
|
1833 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
1834 template <class> friend class packaged_task;// todo check if this works in windows
|
Chris@16
|
1835 #else
|
Chris@16
|
1836 friend class packaged_task<R>;
|
Chris@16
|
1837 #endif
|
Chris@16
|
1838 shared_future(future_ptr a_future):
|
Chris@16
|
1839 base_type(a_future)
|
Chris@16
|
1840 {}
|
Chris@16
|
1841
|
Chris@16
|
1842 public:
|
Chris@16
|
1843 BOOST_THREAD_MOVABLE(shared_future)
|
Chris@16
|
1844 typedef R value_type; // EXTENSION
|
Chris@16
|
1845
|
Chris@16
|
1846 shared_future(shared_future const& other):
|
Chris@16
|
1847 base_type(other)
|
Chris@16
|
1848 {}
|
Chris@16
|
1849
|
Chris@16
|
1850 typedef future_state::state state;
|
Chris@16
|
1851
|
Chris@16
|
1852 BOOST_CONSTEXPR shared_future()
|
Chris@16
|
1853 {}
|
Chris@16
|
1854
|
Chris@16
|
1855 ~shared_future()
|
Chris@16
|
1856 {}
|
Chris@16
|
1857
|
Chris@16
|
1858 shared_future& operator=(shared_future const& other)
|
Chris@16
|
1859 {
|
Chris@16
|
1860 shared_future(other).swap(*this);
|
Chris@16
|
1861 return *this;
|
Chris@16
|
1862 }
|
Chris@16
|
1863 shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT :
|
Chris@16
|
1864 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
Chris@16
|
1865 {
|
Chris@16
|
1866 BOOST_THREAD_RV(other).future_.reset();
|
Chris@16
|
1867 }
|
Chris@16
|
1868 shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT :
|
Chris@16
|
1869 base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))))
|
Chris@16
|
1870 {
|
Chris@16
|
1871 }
|
Chris@16
|
1872
|
Chris@16
|
1873 shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT
|
Chris@16
|
1874 {
|
Chris@16
|
1875 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
|
Chris@16
|
1876 return *this;
|
Chris@16
|
1877 }
|
Chris@16
|
1878 shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT
|
Chris@16
|
1879 {
|
Chris@16
|
1880 base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other))));
|
Chris@16
|
1881 return *this;
|
Chris@16
|
1882 }
|
Chris@16
|
1883
|
Chris@16
|
1884 void swap(shared_future& other) BOOST_NOEXCEPT
|
Chris@16
|
1885 {
|
Chris@16
|
1886 static_cast<base_type*>(this)->swap(other);
|
Chris@16
|
1887 }
|
Chris@16
|
1888
|
Chris@16
|
1889 // retrieving the value
|
Chris@16
|
1890 typename detail::shared_state<R>::shared_future_get_result_type get()
|
Chris@16
|
1891 {
|
Chris@16
|
1892 if(!this->future_)
|
Chris@16
|
1893 {
|
Chris@16
|
1894 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1895 }
|
Chris@16
|
1896
|
Chris@16
|
1897 return this->future_->get_sh();
|
Chris@16
|
1898 }
|
Chris@16
|
1899
|
Chris@16
|
1900 template <typename R2>
|
Chris@16
|
1901 typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type
|
Chris@16
|
1902 get_or(BOOST_THREAD_RV_REF(R2) v) // EXTENSION
|
Chris@16
|
1903 {
|
Chris@16
|
1904 if(!this->future_)
|
Chris@16
|
1905 {
|
Chris@16
|
1906 boost::throw_exception(future_uninitialized());
|
Chris@16
|
1907 }
|
Chris@16
|
1908 future_ptr fut_=this->future_;
|
Chris@16
|
1909 fut_->wait();
|
Chris@16
|
1910 if (fut_->has_value()) return fut_->get_sh();
|
Chris@16
|
1911 else return boost::move(v);
|
Chris@16
|
1912 }
|
Chris@16
|
1913
|
Chris@16
|
1914 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
1915
|
Chris@16
|
1916 // template<typename F>
|
Chris@16
|
1917 // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
Chris@16
|
1918 // template<typename F>
|
Chris@16
|
1919 // auto then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
Chris@16
|
1920
|
Chris@16
|
1921 //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
1922 // template<typename RF>
|
Chris@16
|
1923 // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(shared_future&));
|
Chris@16
|
1924 // template<typename RF>
|
Chris@16
|
1925 // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(shared_future&));
|
Chris@16
|
1926 //#endif
|
Chris@16
|
1927 template<typename F>
|
Chris@16
|
1928 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
|
Chris@16
|
1929 then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@16
|
1930 template<typename F>
|
Chris@16
|
1931 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type>
|
Chris@16
|
1932 then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION
|
Chris@16
|
1933 #endif
|
Chris@16
|
1934 //#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
1935 // inline
|
Chris@16
|
1936 // typename boost::enable_if_c<
|
Chris@16
|
1937 // is_future_type<value_type>::value,
|
Chris@16
|
1938 // BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type>
|
Chris@16
|
1939 // >::type
|
Chris@16
|
1940 // unwrap();
|
Chris@16
|
1941 //#endif
|
Chris@16
|
1942
|
Chris@16
|
1943 };
|
Chris@16
|
1944
|
Chris@16
|
1945 BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@16
|
1946
|
Chris@16
|
1947 namespace detail
|
Chris@16
|
1948 {
|
Chris@16
|
1949 /// Copy construction from a shared_future
|
Chris@16
|
1950 template <typename R>
|
Chris@16
|
1951 inline basic_future<R>::basic_future(const shared_future<R>& other) BOOST_NOEXCEPT
|
Chris@16
|
1952 : future_(other.future_)
|
Chris@16
|
1953 {
|
Chris@16
|
1954 }
|
Chris@16
|
1955 }
|
Chris@16
|
1956
|
Chris@16
|
1957 template <typename R>
|
Chris@16
|
1958 class promise
|
Chris@16
|
1959 {
|
Chris@16
|
1960 typedef boost::shared_ptr<detail::shared_state<R> > future_ptr;
|
Chris@16
|
1961
|
Chris@16
|
1962 future_ptr future_;
|
Chris@16
|
1963 bool future_obtained;
|
Chris@16
|
1964
|
Chris@16
|
1965 void lazy_init()
|
Chris@16
|
1966 {
|
Chris@16
|
1967 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
1968 #include <boost/detail/atomic_undef_macros.hpp>
|
Chris@16
|
1969 if(!atomic_load(&future_))
|
Chris@16
|
1970 {
|
Chris@16
|
1971 future_ptr blank;
|
Chris@16
|
1972 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>));
|
Chris@16
|
1973 }
|
Chris@16
|
1974 #include <boost/detail/atomic_redef_macros.hpp>
|
Chris@16
|
1975 #endif
|
Chris@16
|
1976 }
|
Chris@16
|
1977
|
Chris@16
|
1978 public:
|
Chris@16
|
1979 BOOST_THREAD_MOVABLE_ONLY(promise)
|
Chris@16
|
1980 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
1981 template <class Allocator>
|
Chris@16
|
1982 promise(boost::allocator_arg_t, Allocator a)
|
Chris@16
|
1983 {
|
Chris@16
|
1984 typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2;
|
Chris@16
|
1985 A2 a2(a);
|
Chris@16
|
1986 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
1987
|
Chris@16
|
1988 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) );
|
Chris@16
|
1989 future_obtained = false;
|
Chris@16
|
1990 }
|
Chris@16
|
1991 #endif
|
Chris@16
|
1992 promise():
|
Chris@16
|
1993 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
1994 future_(),
|
Chris@16
|
1995 #else
|
Chris@16
|
1996 future_(new detail::shared_state<R>()),
|
Chris@16
|
1997 #endif
|
Chris@16
|
1998 future_obtained(false)
|
Chris@16
|
1999 {}
|
Chris@16
|
2000
|
Chris@16
|
2001 ~promise()
|
Chris@16
|
2002 {
|
Chris@16
|
2003 if(future_)
|
Chris@16
|
2004 {
|
Chris@16
|
2005 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2006
|
Chris@16
|
2007 if(!future_->done && !future_->is_constructed)
|
Chris@16
|
2008 {
|
Chris@16
|
2009 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
|
Chris@16
|
2010 }
|
Chris@16
|
2011 }
|
Chris@16
|
2012 }
|
Chris@16
|
2013
|
Chris@16
|
2014 // Assignment
|
Chris@16
|
2015 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
|
Chris@16
|
2016 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
|
Chris@16
|
2017 {
|
Chris@16
|
2018 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2019 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2020 }
|
Chris@16
|
2021 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
|
Chris@16
|
2022 {
|
Chris@16
|
2023 future_=BOOST_THREAD_RV(rhs).future_;
|
Chris@16
|
2024 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
|
Chris@16
|
2025 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2026 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2027 return *this;
|
Chris@16
|
2028 }
|
Chris@16
|
2029
|
Chris@16
|
2030 void swap(promise& other)
|
Chris@16
|
2031 {
|
Chris@16
|
2032 future_.swap(other.future_);
|
Chris@16
|
2033 std::swap(future_obtained,other.future_obtained);
|
Chris@16
|
2034 }
|
Chris@16
|
2035
|
Chris@16
|
2036 // Result retrieval
|
Chris@16
|
2037 BOOST_THREAD_FUTURE<R> get_future()
|
Chris@16
|
2038 {
|
Chris@16
|
2039 lazy_init();
|
Chris@16
|
2040 if (future_.get()==0)
|
Chris@16
|
2041 {
|
Chris@16
|
2042 boost::throw_exception(promise_moved());
|
Chris@16
|
2043 }
|
Chris@16
|
2044 if (future_obtained)
|
Chris@16
|
2045 {
|
Chris@16
|
2046 boost::throw_exception(future_already_retrieved());
|
Chris@16
|
2047 }
|
Chris@16
|
2048 future_obtained=true;
|
Chris@16
|
2049 return BOOST_THREAD_FUTURE<R>(future_);
|
Chris@16
|
2050 }
|
Chris@16
|
2051
|
Chris@16
|
2052 void set_value(typename detail::future_traits<R>::source_reference_type r)
|
Chris@16
|
2053 {
|
Chris@16
|
2054 lazy_init();
|
Chris@16
|
2055 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2056 if(future_->done)
|
Chris@16
|
2057 {
|
Chris@16
|
2058 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2059 }
|
Chris@16
|
2060 future_->mark_finished_with_result_internal(r, lock);
|
Chris@16
|
2061 }
|
Chris@16
|
2062
|
Chris@16
|
2063 // void set_value(R && r);
|
Chris@16
|
2064 void set_value(typename detail::future_traits<R>::rvalue_source_type r)
|
Chris@16
|
2065 {
|
Chris@16
|
2066 lazy_init();
|
Chris@16
|
2067 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2068 if(future_->done)
|
Chris@16
|
2069 {
|
Chris@16
|
2070 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2071 }
|
Chris@16
|
2072 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2073 future_->mark_finished_with_result_internal(boost::forward<R>(r), lock);
|
Chris@16
|
2074 #else
|
Chris@16
|
2075 future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r), lock);
|
Chris@16
|
2076 #endif
|
Chris@16
|
2077 }
|
Chris@16
|
2078
|
Chris@16
|
2079 void set_exception(boost::exception_ptr p)
|
Chris@16
|
2080 {
|
Chris@16
|
2081 lazy_init();
|
Chris@16
|
2082 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2083 if(future_->done)
|
Chris@16
|
2084 {
|
Chris@16
|
2085 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2086 }
|
Chris@16
|
2087 future_->mark_exceptional_finish_internal(p, lock);
|
Chris@16
|
2088 }
|
Chris@16
|
2089 template <typename E>
|
Chris@16
|
2090 void set_exception(E ex)
|
Chris@16
|
2091 {
|
Chris@16
|
2092 set_exception(copy_exception(ex));
|
Chris@16
|
2093 }
|
Chris@16
|
2094 // setting the result with deferred notification
|
Chris@16
|
2095 void set_value_at_thread_exit(const R& r)
|
Chris@16
|
2096 {
|
Chris@16
|
2097 if (future_.get()==0)
|
Chris@16
|
2098 {
|
Chris@16
|
2099 boost::throw_exception(promise_moved());
|
Chris@16
|
2100 }
|
Chris@16
|
2101 future_->set_value_at_thread_exit(r);
|
Chris@16
|
2102 }
|
Chris@16
|
2103
|
Chris@16
|
2104 void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
|
Chris@16
|
2105 {
|
Chris@16
|
2106 if (future_.get()==0)
|
Chris@16
|
2107 {
|
Chris@16
|
2108 boost::throw_exception(promise_moved());
|
Chris@16
|
2109 }
|
Chris@16
|
2110 future_->set_value_at_thread_exit(boost::move(r));
|
Chris@16
|
2111 }
|
Chris@16
|
2112 void set_exception_at_thread_exit(exception_ptr e)
|
Chris@16
|
2113 {
|
Chris@16
|
2114 if (future_.get()==0)
|
Chris@16
|
2115 {
|
Chris@16
|
2116 boost::throw_exception(promise_moved());
|
Chris@16
|
2117 }
|
Chris@16
|
2118 future_->set_exception_at_thread_exit(e);
|
Chris@16
|
2119 }
|
Chris@16
|
2120 template <typename E>
|
Chris@16
|
2121 void set_exception_at_thread_exit(E ex)
|
Chris@16
|
2122 {
|
Chris@16
|
2123 set_exception_at_thread_exit(copy_exception(ex));
|
Chris@16
|
2124 }
|
Chris@16
|
2125
|
Chris@16
|
2126 template<typename F>
|
Chris@16
|
2127 void set_wait_callback(F f)
|
Chris@16
|
2128 {
|
Chris@16
|
2129 lazy_init();
|
Chris@16
|
2130 future_->set_wait_callback(f,this);
|
Chris@16
|
2131 }
|
Chris@16
|
2132
|
Chris@16
|
2133 };
|
Chris@16
|
2134
|
Chris@16
|
2135 template <typename R>
|
Chris@16
|
2136 class promise<R&>
|
Chris@16
|
2137 {
|
Chris@16
|
2138 typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr;
|
Chris@16
|
2139
|
Chris@16
|
2140 future_ptr future_;
|
Chris@16
|
2141 bool future_obtained;
|
Chris@16
|
2142
|
Chris@16
|
2143 void lazy_init()
|
Chris@16
|
2144 {
|
Chris@16
|
2145 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
2146 #include <boost/detail/atomic_undef_macros.hpp>
|
Chris@16
|
2147 if(!atomic_load(&future_))
|
Chris@16
|
2148 {
|
Chris@16
|
2149 future_ptr blank;
|
Chris@16
|
2150 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R&>));
|
Chris@16
|
2151 }
|
Chris@16
|
2152 #include <boost/detail/atomic_redef_macros.hpp>
|
Chris@16
|
2153 #endif
|
Chris@16
|
2154 }
|
Chris@16
|
2155
|
Chris@16
|
2156 public:
|
Chris@16
|
2157 BOOST_THREAD_MOVABLE_ONLY(promise)
|
Chris@16
|
2158 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
2159 template <class Allocator>
|
Chris@16
|
2160 promise(boost::allocator_arg_t, Allocator a)
|
Chris@16
|
2161 {
|
Chris@16
|
2162 typedef typename Allocator::template rebind<detail::shared_state<R&> >::other A2;
|
Chris@16
|
2163 A2 a2(a);
|
Chris@16
|
2164 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
2165
|
Chris@16
|
2166 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) );
|
Chris@16
|
2167 future_obtained = false;
|
Chris@16
|
2168 }
|
Chris@16
|
2169 #endif
|
Chris@16
|
2170 promise():
|
Chris@16
|
2171 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
2172 future_(),
|
Chris@16
|
2173 #else
|
Chris@16
|
2174 future_(new detail::shared_state<R&>()),
|
Chris@16
|
2175 #endif
|
Chris@16
|
2176 future_obtained(false)
|
Chris@16
|
2177 {}
|
Chris@16
|
2178
|
Chris@16
|
2179 ~promise()
|
Chris@16
|
2180 {
|
Chris@16
|
2181 if(future_)
|
Chris@16
|
2182 {
|
Chris@16
|
2183 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2184
|
Chris@16
|
2185 if(!future_->done && !future_->is_constructed)
|
Chris@16
|
2186 {
|
Chris@16
|
2187 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
|
Chris@16
|
2188 }
|
Chris@16
|
2189 }
|
Chris@16
|
2190 }
|
Chris@16
|
2191
|
Chris@16
|
2192 // Assignment
|
Chris@16
|
2193 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
|
Chris@16
|
2194 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
|
Chris@16
|
2195 {
|
Chris@16
|
2196 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2197 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2198 }
|
Chris@16
|
2199 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
|
Chris@16
|
2200 {
|
Chris@16
|
2201 future_=BOOST_THREAD_RV(rhs).future_;
|
Chris@16
|
2202 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
|
Chris@16
|
2203 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2204 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2205 return *this;
|
Chris@16
|
2206 }
|
Chris@16
|
2207
|
Chris@16
|
2208 void swap(promise& other)
|
Chris@16
|
2209 {
|
Chris@16
|
2210 future_.swap(other.future_);
|
Chris@16
|
2211 std::swap(future_obtained,other.future_obtained);
|
Chris@16
|
2212 }
|
Chris@16
|
2213
|
Chris@16
|
2214 // Result retrieval
|
Chris@16
|
2215 BOOST_THREAD_FUTURE<R&> get_future()
|
Chris@16
|
2216 {
|
Chris@16
|
2217 lazy_init();
|
Chris@16
|
2218 if (future_.get()==0)
|
Chris@16
|
2219 {
|
Chris@16
|
2220 boost::throw_exception(promise_moved());
|
Chris@16
|
2221 }
|
Chris@16
|
2222 if (future_obtained)
|
Chris@16
|
2223 {
|
Chris@16
|
2224 boost::throw_exception(future_already_retrieved());
|
Chris@16
|
2225 }
|
Chris@16
|
2226 future_obtained=true;
|
Chris@16
|
2227 return BOOST_THREAD_FUTURE<R&>(future_);
|
Chris@16
|
2228 }
|
Chris@16
|
2229
|
Chris@16
|
2230 void set_value(R& r)
|
Chris@16
|
2231 {
|
Chris@16
|
2232 lazy_init();
|
Chris@16
|
2233 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2234 if(future_->done)
|
Chris@16
|
2235 {
|
Chris@16
|
2236 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2237 }
|
Chris@16
|
2238 future_->mark_finished_with_result_internal(r, lock);
|
Chris@16
|
2239 }
|
Chris@16
|
2240
|
Chris@16
|
2241 void set_exception(boost::exception_ptr p)
|
Chris@16
|
2242 {
|
Chris@16
|
2243 lazy_init();
|
Chris@16
|
2244 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2245 if(future_->done)
|
Chris@16
|
2246 {
|
Chris@16
|
2247 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2248 }
|
Chris@16
|
2249 future_->mark_exceptional_finish_internal(p, lock);
|
Chris@16
|
2250 }
|
Chris@16
|
2251 template <typename E>
|
Chris@16
|
2252 void set_exception(E ex)
|
Chris@16
|
2253 {
|
Chris@16
|
2254 set_exception(copy_exception(ex));
|
Chris@16
|
2255 }
|
Chris@16
|
2256
|
Chris@16
|
2257 // setting the result with deferred notification
|
Chris@16
|
2258 void set_value_at_thread_exit(R& r)
|
Chris@16
|
2259 {
|
Chris@16
|
2260 if (future_.get()==0)
|
Chris@16
|
2261 {
|
Chris@16
|
2262 boost::throw_exception(promise_moved());
|
Chris@16
|
2263 }
|
Chris@16
|
2264 future_->set_value_at_thread_exit(r);
|
Chris@16
|
2265 }
|
Chris@16
|
2266
|
Chris@16
|
2267 void set_exception_at_thread_exit(exception_ptr e)
|
Chris@16
|
2268 {
|
Chris@16
|
2269 if (future_.get()==0)
|
Chris@16
|
2270 {
|
Chris@16
|
2271 boost::throw_exception(promise_moved());
|
Chris@16
|
2272 }
|
Chris@16
|
2273 future_->set_exception_at_thread_exit(e);
|
Chris@16
|
2274 }
|
Chris@16
|
2275 template <typename E>
|
Chris@16
|
2276 void set_exception_at_thread_exit(E ex)
|
Chris@16
|
2277 {
|
Chris@16
|
2278 set_exception_at_thread_exit(copy_exception(ex));
|
Chris@16
|
2279 }
|
Chris@16
|
2280
|
Chris@16
|
2281 template<typename F>
|
Chris@16
|
2282 void set_wait_callback(F f)
|
Chris@16
|
2283 {
|
Chris@16
|
2284 lazy_init();
|
Chris@16
|
2285 future_->set_wait_callback(f,this);
|
Chris@16
|
2286 }
|
Chris@16
|
2287
|
Chris@16
|
2288 };
|
Chris@16
|
2289 template <>
|
Chris@16
|
2290 class promise<void>
|
Chris@16
|
2291 {
|
Chris@16
|
2292 typedef boost::shared_ptr<detail::shared_state<void> > future_ptr;
|
Chris@16
|
2293
|
Chris@16
|
2294 future_ptr future_;
|
Chris@16
|
2295 bool future_obtained;
|
Chris@16
|
2296
|
Chris@16
|
2297 void lazy_init()
|
Chris@16
|
2298 {
|
Chris@16
|
2299 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
2300 if(!atomic_load(&future_))
|
Chris@16
|
2301 {
|
Chris@16
|
2302 future_ptr blank;
|
Chris@16
|
2303 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<void>));
|
Chris@16
|
2304 }
|
Chris@16
|
2305 #endif
|
Chris@16
|
2306 }
|
Chris@16
|
2307 public:
|
Chris@16
|
2308 BOOST_THREAD_MOVABLE_ONLY(promise)
|
Chris@16
|
2309
|
Chris@16
|
2310 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
2311 template <class Allocator>
|
Chris@16
|
2312 promise(boost::allocator_arg_t, Allocator a)
|
Chris@16
|
2313 {
|
Chris@16
|
2314 typedef typename Allocator::template rebind<detail::shared_state<void> >::other A2;
|
Chris@16
|
2315 A2 a2(a);
|
Chris@16
|
2316 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
2317
|
Chris@16
|
2318 future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) );
|
Chris@16
|
2319 future_obtained = false;
|
Chris@16
|
2320 }
|
Chris@16
|
2321 #endif
|
Chris@16
|
2322 promise():
|
Chris@16
|
2323 #if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
|
Chris@16
|
2324 future_(),
|
Chris@16
|
2325 #else
|
Chris@16
|
2326 future_(new detail::shared_state<void>),
|
Chris@16
|
2327 #endif
|
Chris@16
|
2328 future_obtained(false)
|
Chris@16
|
2329 {}
|
Chris@16
|
2330
|
Chris@16
|
2331 ~promise()
|
Chris@16
|
2332 {
|
Chris@16
|
2333 if(future_)
|
Chris@16
|
2334 {
|
Chris@16
|
2335 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2336
|
Chris@16
|
2337 if(!future_->done && !future_->is_constructed)
|
Chris@16
|
2338 {
|
Chris@16
|
2339 future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
|
Chris@16
|
2340 }
|
Chris@16
|
2341 }
|
Chris@16
|
2342 }
|
Chris@16
|
2343
|
Chris@16
|
2344 // Assignment
|
Chris@16
|
2345 promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
|
Chris@16
|
2346 future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
|
Chris@16
|
2347 {
|
Chris@16
|
2348 // we need to release the future as shared_ptr doesn't implements move semantics
|
Chris@16
|
2349 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2350 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2351 }
|
Chris@16
|
2352
|
Chris@16
|
2353 promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
|
Chris@16
|
2354 {
|
Chris@16
|
2355 future_=BOOST_THREAD_RV(rhs).future_;
|
Chris@16
|
2356 future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
|
Chris@16
|
2357 BOOST_THREAD_RV(rhs).future_.reset();
|
Chris@16
|
2358 BOOST_THREAD_RV(rhs).future_obtained=false;
|
Chris@16
|
2359 return *this;
|
Chris@16
|
2360 }
|
Chris@16
|
2361
|
Chris@16
|
2362 void swap(promise& other)
|
Chris@16
|
2363 {
|
Chris@16
|
2364 future_.swap(other.future_);
|
Chris@16
|
2365 std::swap(future_obtained,other.future_obtained);
|
Chris@16
|
2366 }
|
Chris@16
|
2367
|
Chris@16
|
2368 // Result retrieval
|
Chris@16
|
2369 BOOST_THREAD_FUTURE<void> get_future()
|
Chris@16
|
2370 {
|
Chris@16
|
2371 lazy_init();
|
Chris@16
|
2372
|
Chris@16
|
2373 if (future_.get()==0)
|
Chris@16
|
2374 {
|
Chris@16
|
2375 boost::throw_exception(promise_moved());
|
Chris@16
|
2376 }
|
Chris@16
|
2377 if(future_obtained)
|
Chris@16
|
2378 {
|
Chris@16
|
2379 boost::throw_exception(future_already_retrieved());
|
Chris@16
|
2380 }
|
Chris@16
|
2381 future_obtained=true;
|
Chris@16
|
2382 return BOOST_THREAD_FUTURE<void>(future_);
|
Chris@16
|
2383 }
|
Chris@16
|
2384
|
Chris@16
|
2385 void set_value()
|
Chris@16
|
2386 {
|
Chris@16
|
2387 lazy_init();
|
Chris@16
|
2388 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2389 if(future_->done)
|
Chris@16
|
2390 {
|
Chris@16
|
2391 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2392 }
|
Chris@16
|
2393 future_->mark_finished_with_result_internal(lock);
|
Chris@16
|
2394 }
|
Chris@16
|
2395
|
Chris@16
|
2396 void set_exception(boost::exception_ptr p)
|
Chris@16
|
2397 {
|
Chris@16
|
2398 lazy_init();
|
Chris@16
|
2399 boost::unique_lock<boost::mutex> lock(future_->mutex);
|
Chris@16
|
2400 if(future_->done)
|
Chris@16
|
2401 {
|
Chris@16
|
2402 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
2403 }
|
Chris@16
|
2404 future_->mark_exceptional_finish_internal(p,lock);
|
Chris@16
|
2405 }
|
Chris@16
|
2406 template <typename E>
|
Chris@16
|
2407 void set_exception(E ex)
|
Chris@16
|
2408 {
|
Chris@16
|
2409 set_exception(copy_exception(ex));
|
Chris@16
|
2410 }
|
Chris@16
|
2411
|
Chris@16
|
2412 // setting the result with deferred notification
|
Chris@16
|
2413 void set_value_at_thread_exit()
|
Chris@16
|
2414 {
|
Chris@16
|
2415 if (future_.get()==0)
|
Chris@16
|
2416 {
|
Chris@16
|
2417 boost::throw_exception(promise_moved());
|
Chris@16
|
2418 }
|
Chris@16
|
2419 future_->set_value_at_thread_exit();
|
Chris@16
|
2420 }
|
Chris@16
|
2421
|
Chris@16
|
2422 void set_exception_at_thread_exit(exception_ptr e)
|
Chris@16
|
2423 {
|
Chris@16
|
2424 if (future_.get()==0)
|
Chris@16
|
2425 {
|
Chris@16
|
2426 boost::throw_exception(promise_moved());
|
Chris@16
|
2427 }
|
Chris@16
|
2428 future_->set_exception_at_thread_exit(e);
|
Chris@16
|
2429 }
|
Chris@16
|
2430 template <typename E>
|
Chris@16
|
2431 void set_exception_at_thread_exit(E ex)
|
Chris@16
|
2432 {
|
Chris@16
|
2433 set_exception_at_thread_exit(copy_exception(ex));
|
Chris@16
|
2434 }
|
Chris@16
|
2435
|
Chris@16
|
2436 template<typename F>
|
Chris@16
|
2437 void set_wait_callback(F f)
|
Chris@16
|
2438 {
|
Chris@16
|
2439 lazy_init();
|
Chris@16
|
2440 future_->set_wait_callback(f,this);
|
Chris@16
|
2441 }
|
Chris@16
|
2442
|
Chris@16
|
2443 };
|
Chris@16
|
2444
|
Chris@16
|
2445 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
2446 namespace container
|
Chris@16
|
2447 {
|
Chris@16
|
2448 template <class R, class Alloc>
|
Chris@16
|
2449 struct uses_allocator<promise<R> , Alloc> : true_type
|
Chris@16
|
2450 {
|
Chris@16
|
2451 };
|
Chris@16
|
2452 }
|
Chris@16
|
2453 #endif
|
Chris@16
|
2454
|
Chris@16
|
2455 BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@16
|
2456
|
Chris@16
|
2457 namespace detail
|
Chris@16
|
2458 {
|
Chris@16
|
2459 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2460 template<typename R>
|
Chris@16
|
2461 struct task_base_shared_state;
|
Chris@16
|
2462 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2463 template<typename R, typename ...ArgTypes>
|
Chris@16
|
2464 struct task_base_shared_state<R(ArgTypes...)>:
|
Chris@16
|
2465 #else
|
Chris@16
|
2466 template<typename R>
|
Chris@16
|
2467 struct task_base_shared_state<R()>:
|
Chris@16
|
2468 #endif
|
Chris@16
|
2469 #else
|
Chris@16
|
2470 template<typename R>
|
Chris@16
|
2471 struct task_base_shared_state:
|
Chris@16
|
2472 #endif
|
Chris@16
|
2473 detail::shared_state<R>
|
Chris@16
|
2474 {
|
Chris@16
|
2475 bool started;
|
Chris@16
|
2476
|
Chris@16
|
2477 task_base_shared_state():
|
Chris@16
|
2478 started(false)
|
Chris@16
|
2479 {}
|
Chris@16
|
2480
|
Chris@16
|
2481 void reset()
|
Chris@16
|
2482 {
|
Chris@16
|
2483 started=false;
|
Chris@16
|
2484 }
|
Chris@16
|
2485 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2486 virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
|
Chris@16
|
2487 void run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2488 #else
|
Chris@16
|
2489 virtual void do_run()=0;
|
Chris@16
|
2490 void run()
|
Chris@16
|
2491 #endif
|
Chris@16
|
2492 {
|
Chris@16
|
2493 {
|
Chris@16
|
2494 boost::lock_guard<boost::mutex> lk(this->mutex);
|
Chris@16
|
2495 if(started)
|
Chris@16
|
2496 {
|
Chris@16
|
2497 boost::throw_exception(task_already_started());
|
Chris@16
|
2498 }
|
Chris@16
|
2499 started=true;
|
Chris@16
|
2500 }
|
Chris@16
|
2501 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2502 do_run(boost::forward<ArgTypes>(args)...);
|
Chris@16
|
2503 #else
|
Chris@16
|
2504 do_run();
|
Chris@16
|
2505 #endif
|
Chris@16
|
2506 }
|
Chris@16
|
2507
|
Chris@16
|
2508 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2509 virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0;
|
Chris@16
|
2510 void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2511 #else
|
Chris@16
|
2512 virtual void do_apply()=0;
|
Chris@16
|
2513 void apply()
|
Chris@16
|
2514 #endif
|
Chris@16
|
2515 {
|
Chris@16
|
2516 {
|
Chris@16
|
2517 boost::lock_guard<boost::mutex> lk(this->mutex);
|
Chris@16
|
2518 if(started)
|
Chris@16
|
2519 {
|
Chris@16
|
2520 boost::throw_exception(task_already_started());
|
Chris@16
|
2521 }
|
Chris@16
|
2522 started=true;
|
Chris@16
|
2523 }
|
Chris@16
|
2524 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2525 do_apply(boost::forward<ArgTypes>(args)...);
|
Chris@16
|
2526 #else
|
Chris@16
|
2527 do_apply();
|
Chris@16
|
2528 #endif
|
Chris@16
|
2529 }
|
Chris@16
|
2530
|
Chris@16
|
2531 void owner_destroyed()
|
Chris@16
|
2532 {
|
Chris@16
|
2533 boost::unique_lock<boost::mutex> lk(this->mutex);
|
Chris@16
|
2534 if(!started)
|
Chris@16
|
2535 {
|
Chris@16
|
2536 started=true;
|
Chris@16
|
2537 this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk);
|
Chris@16
|
2538 }
|
Chris@16
|
2539 }
|
Chris@16
|
2540
|
Chris@16
|
2541 };
|
Chris@16
|
2542
|
Chris@16
|
2543 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2544 template<typename F, typename R>
|
Chris@16
|
2545 struct task_shared_state;
|
Chris@16
|
2546 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2547 template<typename F, typename R, typename ...ArgTypes>
|
Chris@16
|
2548 struct task_shared_state<F, R(ArgTypes...)>:
|
Chris@16
|
2549 task_base_shared_state<R(ArgTypes...)>
|
Chris@16
|
2550 #else
|
Chris@16
|
2551 template<typename F, typename R>
|
Chris@16
|
2552 struct task_shared_state<F, R()>:
|
Chris@16
|
2553 task_base_shared_state<R()>
|
Chris@16
|
2554 #endif
|
Chris@16
|
2555 #else
|
Chris@16
|
2556 template<typename F, typename R>
|
Chris@16
|
2557 struct task_shared_state:
|
Chris@16
|
2558 task_base_shared_state<R>
|
Chris@16
|
2559 #endif
|
Chris@16
|
2560 {
|
Chris@16
|
2561 private:
|
Chris@16
|
2562 task_shared_state(task_shared_state&);
|
Chris@16
|
2563 public:
|
Chris@16
|
2564 F f;
|
Chris@16
|
2565 task_shared_state(F const& f_):
|
Chris@16
|
2566 f(f_)
|
Chris@16
|
2567 {}
|
Chris@16
|
2568 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
|
Chris@16
|
2569 f(boost::move(f_))
|
Chris@16
|
2570 {}
|
Chris@16
|
2571
|
Chris@16
|
2572 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2573 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2574 {
|
Chris@16
|
2575 try
|
Chris@16
|
2576 {
|
Chris@16
|
2577 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
|
Chris@16
|
2578 }
|
Chris@16
|
2579 #else
|
Chris@16
|
2580 void do_apply()
|
Chris@16
|
2581 {
|
Chris@16
|
2582 try
|
Chris@16
|
2583 {
|
Chris@16
|
2584 this->set_value_at_thread_exit(f());
|
Chris@16
|
2585 }
|
Chris@16
|
2586 #endif
|
Chris@16
|
2587 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2588 catch(thread_interrupted& )
|
Chris@16
|
2589 {
|
Chris@16
|
2590 this->set_interrupted_at_thread_exit();
|
Chris@16
|
2591 }
|
Chris@16
|
2592 #endif
|
Chris@16
|
2593 catch(...)
|
Chris@16
|
2594 {
|
Chris@16
|
2595 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2596 }
|
Chris@16
|
2597 }
|
Chris@16
|
2598
|
Chris@16
|
2599 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2600 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2601 {
|
Chris@16
|
2602 try
|
Chris@16
|
2603 {
|
Chris@16
|
2604 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
|
Chris@16
|
2605 }
|
Chris@16
|
2606 #else
|
Chris@16
|
2607 void do_run()
|
Chris@16
|
2608 {
|
Chris@16
|
2609 try
|
Chris@16
|
2610 {
|
Chris@16
|
2611 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
2612 R res((f()));
|
Chris@16
|
2613 this->mark_finished_with_result(boost::move(res));
|
Chris@16
|
2614 #else
|
Chris@16
|
2615 this->mark_finished_with_result(f());
|
Chris@16
|
2616 #endif
|
Chris@16
|
2617 }
|
Chris@16
|
2618 #endif
|
Chris@16
|
2619 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2620 catch(thread_interrupted& )
|
Chris@16
|
2621 {
|
Chris@16
|
2622 this->mark_interrupted_finish();
|
Chris@16
|
2623 }
|
Chris@16
|
2624 #endif
|
Chris@16
|
2625 catch(...)
|
Chris@16
|
2626 {
|
Chris@16
|
2627 this->mark_exceptional_finish();
|
Chris@16
|
2628 }
|
Chris@16
|
2629 }
|
Chris@16
|
2630 };
|
Chris@16
|
2631
|
Chris@16
|
2632 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2633 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2634 template<typename F, typename R, typename ...ArgTypes>
|
Chris@16
|
2635 struct task_shared_state<F, R&(ArgTypes...)>:
|
Chris@16
|
2636 task_base_shared_state<R&(ArgTypes...)>
|
Chris@16
|
2637 #else
|
Chris@16
|
2638 template<typename F, typename R>
|
Chris@16
|
2639 struct task_shared_state<F, R&()>:
|
Chris@16
|
2640 task_base_shared_state<R&()>
|
Chris@16
|
2641 #endif
|
Chris@16
|
2642 #else
|
Chris@16
|
2643 template<typename F, typename R>
|
Chris@16
|
2644 struct task_shared_state<F,R&>:
|
Chris@16
|
2645 task_base_shared_state<R&>
|
Chris@16
|
2646 #endif
|
Chris@16
|
2647 {
|
Chris@16
|
2648 private:
|
Chris@16
|
2649 task_shared_state(task_shared_state&);
|
Chris@16
|
2650 public:
|
Chris@16
|
2651 F f;
|
Chris@16
|
2652 task_shared_state(F const& f_):
|
Chris@16
|
2653 f(f_)
|
Chris@16
|
2654 {}
|
Chris@16
|
2655 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
|
Chris@16
|
2656 f(boost::move(f_))
|
Chris@16
|
2657 {}
|
Chris@16
|
2658
|
Chris@16
|
2659 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2660 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2661 {
|
Chris@16
|
2662 try
|
Chris@16
|
2663 {
|
Chris@16
|
2664 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
|
Chris@16
|
2665 }
|
Chris@16
|
2666 #else
|
Chris@16
|
2667 void do_apply()
|
Chris@16
|
2668 {
|
Chris@16
|
2669 try
|
Chris@16
|
2670 {
|
Chris@16
|
2671 this->set_value_at_thread_exit(f());
|
Chris@16
|
2672 }
|
Chris@16
|
2673 #endif
|
Chris@16
|
2674 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2675 catch(thread_interrupted& )
|
Chris@16
|
2676 {
|
Chris@16
|
2677 this->set_interrupted_at_thread_exit();
|
Chris@16
|
2678 }
|
Chris@16
|
2679 #endif
|
Chris@16
|
2680 catch(...)
|
Chris@16
|
2681 {
|
Chris@16
|
2682 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2683 }
|
Chris@16
|
2684 }
|
Chris@16
|
2685
|
Chris@16
|
2686 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2687 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2688 {
|
Chris@16
|
2689 try
|
Chris@16
|
2690 {
|
Chris@16
|
2691 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
|
Chris@16
|
2692 }
|
Chris@16
|
2693 #else
|
Chris@16
|
2694 void do_run()
|
Chris@16
|
2695 {
|
Chris@16
|
2696 try
|
Chris@16
|
2697 {
|
Chris@16
|
2698 R& res((f()));
|
Chris@16
|
2699 this->mark_finished_with_result(res);
|
Chris@16
|
2700 }
|
Chris@16
|
2701 #endif
|
Chris@16
|
2702 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2703 catch(thread_interrupted& )
|
Chris@16
|
2704 {
|
Chris@16
|
2705 this->mark_interrupted_finish();
|
Chris@16
|
2706 }
|
Chris@16
|
2707 #endif
|
Chris@16
|
2708 catch(...)
|
Chris@16
|
2709 {
|
Chris@16
|
2710 this->mark_exceptional_finish();
|
Chris@16
|
2711 }
|
Chris@16
|
2712 }
|
Chris@16
|
2713 };
|
Chris@16
|
2714
|
Chris@16
|
2715 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
2716
|
Chris@16
|
2717 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2718 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2719 template<typename R, typename ...ArgTypes>
|
Chris@16
|
2720 struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>:
|
Chris@16
|
2721 task_base_shared_state<R(ArgTypes...)>
|
Chris@16
|
2722 #else
|
Chris@16
|
2723 template<typename R>
|
Chris@16
|
2724 struct task_shared_state<R (*)(), R()>:
|
Chris@16
|
2725 task_base_shared_state<R()>
|
Chris@16
|
2726 #endif
|
Chris@16
|
2727 #else
|
Chris@16
|
2728 template<typename R>
|
Chris@16
|
2729 struct task_shared_state<R (*)(), R> :
|
Chris@16
|
2730 task_base_shared_state<R>
|
Chris@16
|
2731 #endif
|
Chris@16
|
2732 {
|
Chris@16
|
2733 private:
|
Chris@16
|
2734 task_shared_state(task_shared_state&);
|
Chris@16
|
2735 public:
|
Chris@16
|
2736 R (*f)();
|
Chris@16
|
2737 task_shared_state(R (*f_)()):
|
Chris@16
|
2738 f(f_)
|
Chris@16
|
2739 {}
|
Chris@16
|
2740
|
Chris@16
|
2741
|
Chris@16
|
2742 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2743 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2744 {
|
Chris@16
|
2745 try
|
Chris@16
|
2746 {
|
Chris@16
|
2747 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
|
Chris@16
|
2748 }
|
Chris@16
|
2749 #else
|
Chris@16
|
2750 void do_apply()
|
Chris@16
|
2751 {
|
Chris@16
|
2752 try
|
Chris@16
|
2753 {
|
Chris@16
|
2754 R r((f()));
|
Chris@16
|
2755 this->set_value_at_thread_exit(boost::move(r));
|
Chris@16
|
2756 }
|
Chris@16
|
2757 #endif
|
Chris@16
|
2758 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2759 catch(thread_interrupted& )
|
Chris@16
|
2760 {
|
Chris@16
|
2761 this->set_interrupted_at_thread_exit();
|
Chris@16
|
2762 }
|
Chris@16
|
2763 #endif
|
Chris@16
|
2764 catch(...)
|
Chris@16
|
2765 {
|
Chris@16
|
2766 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2767 }
|
Chris@16
|
2768 }
|
Chris@16
|
2769
|
Chris@16
|
2770
|
Chris@16
|
2771 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2772 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2773 {
|
Chris@16
|
2774 try
|
Chris@16
|
2775 {
|
Chris@16
|
2776 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
|
Chris@16
|
2777 }
|
Chris@16
|
2778 #else
|
Chris@16
|
2779 void do_run()
|
Chris@16
|
2780 {
|
Chris@16
|
2781 try
|
Chris@16
|
2782 {
|
Chris@16
|
2783 R res((f()));
|
Chris@16
|
2784 this->mark_finished_with_result(boost::move(res));
|
Chris@16
|
2785 }
|
Chris@16
|
2786 #endif
|
Chris@16
|
2787 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2788 catch(thread_interrupted& )
|
Chris@16
|
2789 {
|
Chris@16
|
2790 this->mark_interrupted_finish();
|
Chris@16
|
2791 }
|
Chris@16
|
2792 #endif
|
Chris@16
|
2793 catch(...)
|
Chris@16
|
2794 {
|
Chris@16
|
2795 this->mark_exceptional_finish();
|
Chris@16
|
2796 }
|
Chris@16
|
2797 }
|
Chris@16
|
2798 };
|
Chris@16
|
2799 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2800 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2801 template<typename R, typename ...ArgTypes>
|
Chris@16
|
2802 struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>:
|
Chris@16
|
2803 task_base_shared_state<R&(ArgTypes...)>
|
Chris@16
|
2804 #else
|
Chris@16
|
2805 template<typename R>
|
Chris@16
|
2806 struct task_shared_state<R& (*)(), R&()>:
|
Chris@16
|
2807 task_base_shared_state<R&()>
|
Chris@16
|
2808 #endif
|
Chris@16
|
2809 #else
|
Chris@16
|
2810 template<typename R>
|
Chris@16
|
2811 struct task_shared_state<R& (*)(), R&> :
|
Chris@16
|
2812 task_base_shared_state<R&>
|
Chris@16
|
2813 #endif
|
Chris@16
|
2814 {
|
Chris@16
|
2815 private:
|
Chris@16
|
2816 task_shared_state(task_shared_state&);
|
Chris@16
|
2817 public:
|
Chris@16
|
2818 R& (*f)();
|
Chris@16
|
2819 task_shared_state(R& (*f_)()):
|
Chris@16
|
2820 f(f_)
|
Chris@16
|
2821 {}
|
Chris@16
|
2822
|
Chris@16
|
2823
|
Chris@16
|
2824 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2825 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2826 {
|
Chris@16
|
2827 try
|
Chris@16
|
2828 {
|
Chris@16
|
2829 this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...));
|
Chris@16
|
2830 }
|
Chris@16
|
2831 #else
|
Chris@16
|
2832 void do_apply()
|
Chris@16
|
2833 {
|
Chris@16
|
2834 try
|
Chris@16
|
2835 {
|
Chris@16
|
2836 this->set_value_at_thread_exit(f());
|
Chris@16
|
2837 }
|
Chris@16
|
2838 #endif
|
Chris@16
|
2839 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2840 catch(thread_interrupted& )
|
Chris@16
|
2841 {
|
Chris@16
|
2842 this->set_interrupted_at_thread_exit();
|
Chris@16
|
2843 }
|
Chris@16
|
2844 #endif
|
Chris@16
|
2845 catch(...)
|
Chris@16
|
2846 {
|
Chris@16
|
2847 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2848 }
|
Chris@16
|
2849 }
|
Chris@16
|
2850
|
Chris@16
|
2851
|
Chris@16
|
2852 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2853 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2854 {
|
Chris@16
|
2855 try
|
Chris@16
|
2856 {
|
Chris@16
|
2857 this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...));
|
Chris@16
|
2858 }
|
Chris@16
|
2859 #else
|
Chris@16
|
2860 void do_run()
|
Chris@16
|
2861 {
|
Chris@16
|
2862 try
|
Chris@16
|
2863 {
|
Chris@16
|
2864 this->mark_finished_with_result(f());
|
Chris@16
|
2865 }
|
Chris@16
|
2866 #endif
|
Chris@16
|
2867 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2868 catch(thread_interrupted& )
|
Chris@16
|
2869 {
|
Chris@16
|
2870 this->mark_interrupted_finish();
|
Chris@16
|
2871 }
|
Chris@16
|
2872 #endif
|
Chris@16
|
2873 catch(...)
|
Chris@16
|
2874 {
|
Chris@16
|
2875 this->mark_exceptional_finish();
|
Chris@16
|
2876 }
|
Chris@16
|
2877 }
|
Chris@16
|
2878 };
|
Chris@16
|
2879 #endif
|
Chris@16
|
2880 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2881 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2882 template<typename F, typename ...ArgTypes>
|
Chris@16
|
2883 struct task_shared_state<F, void(ArgTypes...)>:
|
Chris@16
|
2884 task_base_shared_state<void(ArgTypes...)>
|
Chris@16
|
2885 #else
|
Chris@16
|
2886 template<typename F>
|
Chris@16
|
2887 struct task_shared_state<F, void()>:
|
Chris@16
|
2888 task_base_shared_state<void()>
|
Chris@16
|
2889 #endif
|
Chris@16
|
2890 #else
|
Chris@16
|
2891 template<typename F>
|
Chris@16
|
2892 struct task_shared_state<F,void>:
|
Chris@16
|
2893 task_base_shared_state<void>
|
Chris@16
|
2894 #endif
|
Chris@16
|
2895 {
|
Chris@16
|
2896 private:
|
Chris@16
|
2897 task_shared_state(task_shared_state&);
|
Chris@16
|
2898 public:
|
Chris@16
|
2899 F f;
|
Chris@16
|
2900 task_shared_state(F const& f_):
|
Chris@16
|
2901 f(f_)
|
Chris@16
|
2902 {}
|
Chris@16
|
2903 task_shared_state(BOOST_THREAD_RV_REF(F) f_):
|
Chris@16
|
2904 f(boost::move(f_))
|
Chris@16
|
2905 {}
|
Chris@16
|
2906
|
Chris@16
|
2907 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2908 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2909 {
|
Chris@16
|
2910 try
|
Chris@16
|
2911 {
|
Chris@16
|
2912 f(boost::forward<ArgTypes>(args)...);
|
Chris@16
|
2913 #else
|
Chris@16
|
2914 void do_apply()
|
Chris@16
|
2915 {
|
Chris@16
|
2916 try
|
Chris@16
|
2917 {
|
Chris@16
|
2918 f();
|
Chris@16
|
2919 #endif
|
Chris@16
|
2920 this->set_value_at_thread_exit();
|
Chris@16
|
2921 }
|
Chris@16
|
2922 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2923 catch(thread_interrupted& )
|
Chris@16
|
2924 {
|
Chris@16
|
2925 this->set_interrupted_at_thread_exit();
|
Chris@16
|
2926 }
|
Chris@16
|
2927 #endif
|
Chris@16
|
2928 catch(...)
|
Chris@16
|
2929 {
|
Chris@16
|
2930 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
2931 }
|
Chris@16
|
2932 }
|
Chris@16
|
2933
|
Chris@16
|
2934 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2935 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2936 {
|
Chris@16
|
2937 try
|
Chris@16
|
2938 {
|
Chris@16
|
2939 f(boost::forward<ArgTypes>(args)...);
|
Chris@16
|
2940 #else
|
Chris@16
|
2941 void do_run()
|
Chris@16
|
2942 {
|
Chris@16
|
2943 try
|
Chris@16
|
2944 {
|
Chris@16
|
2945 f();
|
Chris@16
|
2946 #endif
|
Chris@16
|
2947 this->mark_finished_with_result();
|
Chris@16
|
2948 }
|
Chris@16
|
2949 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
2950 catch(thread_interrupted& )
|
Chris@16
|
2951 {
|
Chris@16
|
2952 this->mark_interrupted_finish();
|
Chris@16
|
2953 }
|
Chris@16
|
2954 #endif
|
Chris@16
|
2955 catch(...)
|
Chris@16
|
2956 {
|
Chris@16
|
2957 this->mark_exceptional_finish();
|
Chris@16
|
2958 }
|
Chris@16
|
2959 }
|
Chris@16
|
2960 };
|
Chris@16
|
2961
|
Chris@16
|
2962 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
2963 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2964 template<typename ...ArgTypes>
|
Chris@16
|
2965 struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>:
|
Chris@16
|
2966 task_base_shared_state<void(ArgTypes...)>
|
Chris@16
|
2967 #else
|
Chris@16
|
2968 template<>
|
Chris@16
|
2969 struct task_shared_state<void (*)(), void()>:
|
Chris@16
|
2970 task_base_shared_state<void()>
|
Chris@16
|
2971 #endif
|
Chris@16
|
2972 #else
|
Chris@16
|
2973 template<>
|
Chris@16
|
2974 struct task_shared_state<void (*)(),void>:
|
Chris@16
|
2975 task_base_shared_state<void>
|
Chris@16
|
2976 #endif
|
Chris@16
|
2977 {
|
Chris@16
|
2978 private:
|
Chris@16
|
2979 task_shared_state(task_shared_state&);
|
Chris@16
|
2980 public:
|
Chris@16
|
2981 void (*f)();
|
Chris@16
|
2982 task_shared_state(void (*f_)()):
|
Chris@16
|
2983 f(f_)
|
Chris@16
|
2984 {}
|
Chris@16
|
2985
|
Chris@16
|
2986 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
2987 void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
2988 {
|
Chris@16
|
2989 try
|
Chris@16
|
2990 {
|
Chris@16
|
2991 f(boost::forward<ArgTypes>(args)...);
|
Chris@16
|
2992 #else
|
Chris@16
|
2993 void do_apply()
|
Chris@16
|
2994 {
|
Chris@16
|
2995 try
|
Chris@16
|
2996 {
|
Chris@16
|
2997 f();
|
Chris@16
|
2998 #endif
|
Chris@16
|
2999 this->set_value_at_thread_exit();
|
Chris@16
|
3000 }
|
Chris@16
|
3001 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
3002 catch(thread_interrupted& )
|
Chris@16
|
3003 {
|
Chris@16
|
3004 this->set_interrupted_at_thread_exit();
|
Chris@16
|
3005 }
|
Chris@16
|
3006 #endif
|
Chris@16
|
3007 catch(...)
|
Chris@16
|
3008 {
|
Chris@16
|
3009 this->set_exception_at_thread_exit(current_exception());
|
Chris@16
|
3010 }
|
Chris@16
|
3011 }
|
Chris@16
|
3012
|
Chris@16
|
3013 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3014 void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)
|
Chris@16
|
3015 {
|
Chris@16
|
3016 try
|
Chris@16
|
3017 {
|
Chris@16
|
3018 f(boost::forward<ArgTypes>(args)...);
|
Chris@16
|
3019 #else
|
Chris@16
|
3020 void do_run()
|
Chris@16
|
3021 {
|
Chris@16
|
3022 try
|
Chris@16
|
3023 {
|
Chris@16
|
3024 f();
|
Chris@16
|
3025 #endif
|
Chris@16
|
3026 this->mark_finished_with_result();
|
Chris@16
|
3027 }
|
Chris@16
|
3028 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
3029 catch(thread_interrupted& )
|
Chris@16
|
3030 {
|
Chris@16
|
3031 this->mark_interrupted_finish();
|
Chris@16
|
3032 }
|
Chris@16
|
3033 #endif
|
Chris@16
|
3034 catch(...)
|
Chris@16
|
3035 {
|
Chris@16
|
3036 this->mark_exceptional_finish();
|
Chris@16
|
3037 }
|
Chris@16
|
3038 }
|
Chris@16
|
3039 };
|
Chris@16
|
3040 }
|
Chris@16
|
3041
|
Chris@16
|
3042 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3043 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3044 template<typename R, typename ...ArgTypes>
|
Chris@16
|
3045 class packaged_task<R(ArgTypes...)>
|
Chris@16
|
3046 {
|
Chris@16
|
3047 typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr;
|
Chris@16
|
3048 boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task;
|
Chris@16
|
3049 #else
|
Chris@16
|
3050 template<typename R>
|
Chris@16
|
3051 class packaged_task<R()>
|
Chris@16
|
3052 {
|
Chris@16
|
3053 typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr;
|
Chris@16
|
3054 boost::shared_ptr<detail::task_base_shared_state<R()> > task;
|
Chris@16
|
3055 #endif
|
Chris@16
|
3056 #else
|
Chris@16
|
3057 template<typename R>
|
Chris@16
|
3058 class packaged_task
|
Chris@16
|
3059 {
|
Chris@16
|
3060 typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr;
|
Chris@16
|
3061 boost::shared_ptr<detail::task_base_shared_state<R> > task;
|
Chris@16
|
3062 #endif
|
Chris@16
|
3063 bool future_obtained;
|
Chris@16
|
3064 struct dummy;
|
Chris@16
|
3065
|
Chris@16
|
3066 public:
|
Chris@16
|
3067 typedef R result_type;
|
Chris@16
|
3068 BOOST_THREAD_MOVABLE_ONLY(packaged_task)
|
Chris@16
|
3069
|
Chris@16
|
3070 packaged_task():
|
Chris@16
|
3071 future_obtained(false)
|
Chris@16
|
3072 {}
|
Chris@16
|
3073
|
Chris@16
|
3074 // construction and destruction
|
Chris@16
|
3075 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
3076
|
Chris@16
|
3077 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3078 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3079 explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args)
|
Chris@16
|
3080 {
|
Chris@16
|
3081 typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...);
|
Chris@16
|
3082 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3083 task= task_ptr(new task_shared_state_type(f, boost::forward<ArgTypes>(args)...));
|
Chris@16
|
3084 future_obtained=false;
|
Chris@16
|
3085 }
|
Chris@16
|
3086 #else
|
Chris@16
|
3087 explicit packaged_task(R(*f)())
|
Chris@16
|
3088 {
|
Chris@16
|
3089 typedef R(*FR)();
|
Chris@16
|
3090 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
|
Chris@16
|
3091 task= task_ptr(new task_shared_state_type(f));
|
Chris@16
|
3092 future_obtained=false;
|
Chris@16
|
3093 }
|
Chris@16
|
3094 #endif
|
Chris@16
|
3095 #else
|
Chris@16
|
3096 explicit packaged_task(R(*f)())
|
Chris@16
|
3097 {
|
Chris@16
|
3098 typedef R(*FR)();
|
Chris@16
|
3099 typedef detail::task_shared_state<FR,R> task_shared_state_type;
|
Chris@16
|
3100 task= task_ptr(new task_shared_state_type(f));
|
Chris@16
|
3101 future_obtained=false;
|
Chris@16
|
3102 }
|
Chris@16
|
3103 #endif
|
Chris@16
|
3104 #endif
|
Chris@16
|
3105 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3106 template <class F>
|
Chris@16
|
3107 explicit packaged_task(BOOST_THREAD_FWD_REF(F) f
|
Chris@16
|
3108 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
|
Chris@16
|
3109 )
|
Chris@16
|
3110 {
|
Chris@16
|
3111 typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
|
Chris@16
|
3112 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3113 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3114 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3115 #else
|
Chris@16
|
3116 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
|
Chris@16
|
3117 #endif
|
Chris@16
|
3118 #else
|
Chris@16
|
3119 typedef detail::task_shared_state<FR,R> task_shared_state_type;
|
Chris@16
|
3120 #endif
|
Chris@16
|
3121 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
|
Chris@16
|
3122 future_obtained = false;
|
Chris@16
|
3123
|
Chris@16
|
3124 }
|
Chris@16
|
3125
|
Chris@16
|
3126 #else
|
Chris@16
|
3127 template <class F>
|
Chris@16
|
3128 explicit packaged_task(F const& f
|
Chris@16
|
3129 , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0
|
Chris@16
|
3130 )
|
Chris@16
|
3131 {
|
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<F,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3135 #else
|
Chris@16
|
3136 typedef detail::task_shared_state<F,R()> task_shared_state_type;
|
Chris@16
|
3137 #endif
|
Chris@16
|
3138 #else
|
Chris@16
|
3139 typedef detail::task_shared_state<F,R> task_shared_state_type;
|
Chris@16
|
3140 #endif
|
Chris@16
|
3141 task = task_ptr(new task_shared_state_type(f));
|
Chris@16
|
3142 future_obtained=false;
|
Chris@16
|
3143 }
|
Chris@16
|
3144 template <class F>
|
Chris@16
|
3145 explicit packaged_task(BOOST_THREAD_RV_REF(F) f)
|
Chris@16
|
3146 {
|
Chris@16
|
3147 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3148 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3149 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3150 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
|
Chris@16
|
3151 #else
|
Chris@16
|
3152 typedef detail::task_shared_state<F,R()> task_shared_state_type;
|
Chris@16
|
3153 task = task_ptr(new task_shared_state_type(boost::move(f))); // TODO forward
|
Chris@16
|
3154 #endif
|
Chris@16
|
3155 #else
|
Chris@16
|
3156 typedef detail::task_shared_state<F,R> task_shared_state_type;
|
Chris@16
|
3157 task = task_ptr(new task_shared_state_type(boost::forward<F>(f)));
|
Chris@16
|
3158 #endif
|
Chris@16
|
3159 future_obtained=false;
|
Chris@16
|
3160
|
Chris@16
|
3161 }
|
Chris@16
|
3162 #endif
|
Chris@16
|
3163
|
Chris@16
|
3164 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
3165 #if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
3166 template <class Allocator>
|
Chris@16
|
3167 packaged_task(boost::allocator_arg_t, Allocator a, R(*f)())
|
Chris@16
|
3168 {
|
Chris@16
|
3169 typedef R(*FR)();
|
Chris@16
|
3170 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3171 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3172 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3173 #else
|
Chris@16
|
3174 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
|
Chris@16
|
3175 #endif
|
Chris@16
|
3176 #else
|
Chris@16
|
3177 typedef detail::task_shared_state<FR,R> task_shared_state_type;
|
Chris@16
|
3178 #endif
|
Chris@16
|
3179 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
|
Chris@16
|
3180 A2 a2(a);
|
Chris@16
|
3181 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
3182
|
Chris@16
|
3183 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
|
Chris@16
|
3184 future_obtained = false;
|
Chris@16
|
3185 }
|
Chris@16
|
3186 #endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@16
|
3187
|
Chris@16
|
3188 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3189 template <class F, class Allocator>
|
Chris@16
|
3190 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f)
|
Chris@16
|
3191 {
|
Chris@16
|
3192 typedef typename remove_cv<typename remove_reference<F>::type>::type FR;
|
Chris@16
|
3193 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3194 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3195 typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3196 #else
|
Chris@16
|
3197 typedef detail::task_shared_state<FR,R()> task_shared_state_type;
|
Chris@16
|
3198 #endif
|
Chris@16
|
3199 #else
|
Chris@16
|
3200 typedef detail::task_shared_state<FR,R> task_shared_state_type;
|
Chris@16
|
3201 #endif
|
Chris@16
|
3202 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
|
Chris@16
|
3203 A2 a2(a);
|
Chris@16
|
3204 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
3205
|
Chris@16
|
3206 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
|
Chris@16
|
3207 future_obtained = false;
|
Chris@16
|
3208 }
|
Chris@16
|
3209 #else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3210 template <class F, class Allocator>
|
Chris@16
|
3211 packaged_task(boost::allocator_arg_t, Allocator a, const F& f)
|
Chris@16
|
3212 {
|
Chris@16
|
3213 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3214 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3215 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3216 #else
|
Chris@16
|
3217 typedef detail::task_shared_state<F,R()> task_shared_state_type;
|
Chris@16
|
3218 #endif
|
Chris@16
|
3219 #else
|
Chris@16
|
3220 typedef detail::task_shared_state<F,R> task_shared_state_type;
|
Chris@16
|
3221 #endif
|
Chris@16
|
3222 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
|
Chris@16
|
3223 A2 a2(a);
|
Chris@16
|
3224 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
3225
|
Chris@16
|
3226 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) );
|
Chris@16
|
3227 future_obtained = false;
|
Chris@16
|
3228 }
|
Chris@16
|
3229 template <class F, class Allocator>
|
Chris@16
|
3230 packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f)
|
Chris@16
|
3231 {
|
Chris@16
|
3232 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3233 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3234 typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type;
|
Chris@16
|
3235 #else
|
Chris@16
|
3236 typedef detail::task_shared_state<F,R()> task_shared_state_type;
|
Chris@16
|
3237 #endif
|
Chris@16
|
3238 #else
|
Chris@16
|
3239 typedef detail::task_shared_state<F,R> task_shared_state_type;
|
Chris@16
|
3240 #endif
|
Chris@16
|
3241 typedef typename Allocator::template rebind<task_shared_state_type>::other A2;
|
Chris@16
|
3242 A2 a2(a);
|
Chris@16
|
3243 typedef thread_detail::allocator_destructor<A2> D;
|
Chris@16
|
3244
|
Chris@16
|
3245 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3246 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) );
|
Chris@16
|
3247 #else
|
Chris@16
|
3248 task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) ); // TODO forward
|
Chris@16
|
3249 #endif
|
Chris@16
|
3250 future_obtained = false;
|
Chris@16
|
3251 }
|
Chris@16
|
3252
|
Chris@16
|
3253 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3254 #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
3255
|
Chris@16
|
3256 ~packaged_task()
|
Chris@16
|
3257 {
|
Chris@16
|
3258 if(task)
|
Chris@16
|
3259 {
|
Chris@16
|
3260 task->owner_destroyed();
|
Chris@16
|
3261 }
|
Chris@16
|
3262 }
|
Chris@16
|
3263
|
Chris@16
|
3264 // assignment
|
Chris@16
|
3265 packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT :
|
Chris@16
|
3266 future_obtained(BOOST_THREAD_RV(other).future_obtained)
|
Chris@16
|
3267 {
|
Chris@16
|
3268 task.swap(BOOST_THREAD_RV(other).task);
|
Chris@16
|
3269 BOOST_THREAD_RV(other).future_obtained=false;
|
Chris@16
|
3270 }
|
Chris@16
|
3271 packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT
|
Chris@16
|
3272 {
|
Chris@16
|
3273
|
Chris@16
|
3274 // todo use forward
|
Chris@16
|
3275 #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
3276 packaged_task temp(boost::move(other));
|
Chris@16
|
3277 #else
|
Chris@16
|
3278 packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other));
|
Chris@16
|
3279 #endif
|
Chris@16
|
3280 swap(temp);
|
Chris@16
|
3281 return *this;
|
Chris@16
|
3282 }
|
Chris@16
|
3283
|
Chris@16
|
3284 void reset()
|
Chris@16
|
3285 {
|
Chris@16
|
3286 if (!valid())
|
Chris@16
|
3287 throw future_error(system::make_error_code(future_errc::no_state));
|
Chris@16
|
3288 task->reset();
|
Chris@16
|
3289 future_obtained=false;
|
Chris@16
|
3290 }
|
Chris@16
|
3291
|
Chris@16
|
3292 void swap(packaged_task& other) BOOST_NOEXCEPT
|
Chris@16
|
3293 {
|
Chris@16
|
3294 task.swap(other.task);
|
Chris@16
|
3295 std::swap(future_obtained,other.future_obtained);
|
Chris@16
|
3296 }
|
Chris@16
|
3297 bool valid() const BOOST_NOEXCEPT
|
Chris@16
|
3298 {
|
Chris@16
|
3299 return task.get()!=0;
|
Chris@16
|
3300 }
|
Chris@16
|
3301
|
Chris@16
|
3302 // result retrieval
|
Chris@16
|
3303 BOOST_THREAD_FUTURE<R> get_future()
|
Chris@16
|
3304 {
|
Chris@16
|
3305 if(!task)
|
Chris@16
|
3306 {
|
Chris@16
|
3307 boost::throw_exception(task_moved());
|
Chris@16
|
3308 }
|
Chris@16
|
3309 else if(!future_obtained)
|
Chris@16
|
3310 {
|
Chris@16
|
3311 future_obtained=true;
|
Chris@16
|
3312 return BOOST_THREAD_FUTURE<R>(task);
|
Chris@16
|
3313 }
|
Chris@16
|
3314 else
|
Chris@16
|
3315 {
|
Chris@16
|
3316 boost::throw_exception(future_already_retrieved());
|
Chris@16
|
3317 }
|
Chris@16
|
3318 //return BOOST_THREAD_FUTURE<R>();
|
Chris@16
|
3319 }
|
Chris@16
|
3320
|
Chris@16
|
3321 // execution
|
Chris@16
|
3322 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3323 void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args)
|
Chris@16
|
3324 {
|
Chris@16
|
3325 if(!task)
|
Chris@16
|
3326 {
|
Chris@16
|
3327 boost::throw_exception(task_moved());
|
Chris@16
|
3328 }
|
Chris@16
|
3329 task->run(boost::forward<ArgTypes>(args)...);
|
Chris@16
|
3330 }
|
Chris@16
|
3331 void make_ready_at_thread_exit(ArgTypes... args)
|
Chris@16
|
3332 {
|
Chris@16
|
3333 if(!task)
|
Chris@16
|
3334 {
|
Chris@16
|
3335 boost::throw_exception(task_moved());
|
Chris@16
|
3336 }
|
Chris@16
|
3337 if (task->has_value())
|
Chris@16
|
3338 {
|
Chris@16
|
3339 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
3340 }
|
Chris@16
|
3341 task->apply(boost::forward<ArgTypes>(args)...);
|
Chris@16
|
3342 }
|
Chris@16
|
3343 #else
|
Chris@16
|
3344 void operator()()
|
Chris@16
|
3345 {
|
Chris@16
|
3346 if(!task)
|
Chris@16
|
3347 {
|
Chris@16
|
3348 boost::throw_exception(task_moved());
|
Chris@16
|
3349 }
|
Chris@16
|
3350 task->run();
|
Chris@16
|
3351 }
|
Chris@16
|
3352 void make_ready_at_thread_exit()
|
Chris@16
|
3353 {
|
Chris@16
|
3354 if(!task)
|
Chris@16
|
3355 {
|
Chris@16
|
3356 boost::throw_exception(task_moved());
|
Chris@16
|
3357 }
|
Chris@16
|
3358 if (task->has_value())
|
Chris@16
|
3359 boost::throw_exception(promise_already_satisfied());
|
Chris@16
|
3360 task->apply();
|
Chris@16
|
3361 }
|
Chris@16
|
3362 #endif
|
Chris@16
|
3363 template<typename F>
|
Chris@16
|
3364 void set_wait_callback(F f)
|
Chris@16
|
3365 {
|
Chris@16
|
3366 task->set_wait_callback(f,this);
|
Chris@16
|
3367 }
|
Chris@16
|
3368 };
|
Chris@16
|
3369
|
Chris@16
|
3370 #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
|
Chris@16
|
3371 namespace container
|
Chris@16
|
3372 {
|
Chris@16
|
3373 template <class R, class Alloc>
|
Chris@16
|
3374 struct uses_allocator<packaged_task<R>, Alloc>
|
Chris@16
|
3375 : public true_type {};
|
Chris@16
|
3376 }
|
Chris@16
|
3377 #endif
|
Chris@16
|
3378
|
Chris@16
|
3379 BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
|
Chris@16
|
3380
|
Chris@16
|
3381 namespace detail
|
Chris@16
|
3382 {
|
Chris@16
|
3383 ////////////////////////////////
|
Chris@16
|
3384 // make_future_deferred_shared_state
|
Chris@16
|
3385 ////////////////////////////////
|
Chris@16
|
3386 template <class Rp, class Fp>
|
Chris@16
|
3387 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
3388 make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
3389 {
|
Chris@16
|
3390 shared_ptr<future_deferred_shared_state<Rp, Fp> >
|
Chris@16
|
3391 h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
|
Chris@16
|
3392 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@16
|
3393 }
|
Chris@16
|
3394
|
Chris@16
|
3395 ////////////////////////////////
|
Chris@16
|
3396 // make_future_async_shared_state
|
Chris@16
|
3397 ////////////////////////////////
|
Chris@16
|
3398 template <class Rp, class Fp>
|
Chris@16
|
3399 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
3400 make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f)
|
Chris@16
|
3401 {
|
Chris@16
|
3402 shared_ptr<future_async_shared_state<Rp, Fp> >
|
Chris@16
|
3403 h(new future_async_shared_state<Rp, Fp>(boost::forward<Fp>(f)));
|
Chris@16
|
3404 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@16
|
3405 }
|
Chris@16
|
3406
|
Chris@16
|
3407 }
|
Chris@16
|
3408
|
Chris@16
|
3409 ////////////////////////////////
|
Chris@16
|
3410 // template <class F, class... ArgTypes>
|
Chris@16
|
3411 // future<R> async(launch policy, F&&, ArgTypes&&...);
|
Chris@16
|
3412 ////////////////////////////////
|
Chris@16
|
3413
|
Chris@16
|
3414 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@16
|
3415
|
Chris@16
|
3416 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3417 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3418 template <class R, class... ArgTypes>
|
Chris@16
|
3419 BOOST_THREAD_FUTURE<R>
|
Chris@16
|
3420 async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
|
Chris@16
|
3421 {
|
Chris@16
|
3422 typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...);
|
Chris@16
|
3423 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
|
Chris@16
|
3424 typedef typename BF::result_type Rp;
|
Chris@16
|
3425 #else
|
Chris@16
|
3426 template <class R>
|
Chris@16
|
3427 BOOST_THREAD_FUTURE<R>
|
Chris@16
|
3428 async(launch policy, R(*f)())
|
Chris@16
|
3429 {
|
Chris@16
|
3430 typedef packaged_task<R()> packaged_task_type;
|
Chris@16
|
3431 #endif
|
Chris@16
|
3432 #else
|
Chris@16
|
3433 template <class R>
|
Chris@16
|
3434 BOOST_THREAD_FUTURE<R>
|
Chris@16
|
3435 async(launch policy, R(*f)())
|
Chris@16
|
3436 {
|
Chris@16
|
3437 typedef packaged_task<R> packaged_task_type;
|
Chris@16
|
3438 #endif
|
Chris@16
|
3439 if (int(policy) & int(launch::async))
|
Chris@16
|
3440 {
|
Chris@16
|
3441 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3442 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
|
Chris@16
|
3443 BF(
|
Chris@16
|
3444 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@16
|
3445 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@16
|
3446 )
|
Chris@16
|
3447 ));
|
Chris@16
|
3448 #else
|
Chris@16
|
3449 packaged_task_type pt( f );
|
Chris@16
|
3450
|
Chris@16
|
3451 BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future());
|
Chris@16
|
3452 ret.set_async();
|
Chris@16
|
3453 boost::thread( boost::move(pt) ).detach();
|
Chris@16
|
3454 return ::boost::move(ret);
|
Chris@16
|
3455 #endif
|
Chris@16
|
3456 }
|
Chris@16
|
3457 else if (int(policy) & int(launch::deferred))
|
Chris@16
|
3458 {
|
Chris@16
|
3459 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3460 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
|
Chris@16
|
3461 BF(
|
Chris@16
|
3462 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@16
|
3463 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@16
|
3464 )
|
Chris@16
|
3465 ));
|
Chris@16
|
3466 #else
|
Chris@16
|
3467 std::terminate();
|
Chris@16
|
3468 BOOST_THREAD_FUTURE<R> ret;
|
Chris@16
|
3469 return ::boost::move(ret);
|
Chris@16
|
3470
|
Chris@16
|
3471 #endif
|
Chris@16
|
3472 } else {
|
Chris@16
|
3473 std::terminate();
|
Chris@16
|
3474 BOOST_THREAD_FUTURE<R> ret;
|
Chris@16
|
3475 return ::boost::move(ret);
|
Chris@16
|
3476 }
|
Chris@16
|
3477 }
|
Chris@16
|
3478
|
Chris@16
|
3479 #endif
|
Chris@16
|
3480
|
Chris@16
|
3481 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
|
Chris@16
|
3482 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3483
|
Chris@16
|
3484 template <class F, class ...ArgTypes>
|
Chris@16
|
3485 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
|
Chris@16
|
3486 typename decay<ArgTypes>::type...
|
Chris@16
|
3487 )>::type>
|
Chris@16
|
3488 async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
|
Chris@16
|
3489 {
|
Chris@16
|
3490
|
Chris@16
|
3491 typedef typename boost::result_of<typename decay<F>::type(
|
Chris@16
|
3492 typename decay<ArgTypes>::type...
|
Chris@16
|
3493 )>::type R;
|
Chris@16
|
3494
|
Chris@16
|
3495 typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
|
Chris@16
|
3496 typedef typename BF::result_type Rp;
|
Chris@16
|
3497
|
Chris@16
|
3498 #else
|
Chris@16
|
3499 template <class F>
|
Chris@16
|
3500 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
|
Chris@16
|
3501 async(launch policy, BOOST_THREAD_FWD_REF(F) f)
|
Chris@16
|
3502 {
|
Chris@16
|
3503 typedef typename boost::result_of<typename decay<F>::type()>::type R;
|
Chris@16
|
3504 typedef packaged_task<R()> packaged_task_type;
|
Chris@16
|
3505
|
Chris@16
|
3506 #endif
|
Chris@16
|
3507 #else
|
Chris@16
|
3508 template <class F>
|
Chris@16
|
3509 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
|
Chris@16
|
3510 async(launch policy, BOOST_THREAD_FWD_REF(F) f)
|
Chris@16
|
3511 {
|
Chris@16
|
3512 typedef typename boost::result_of<typename decay<F>::type()>::type R;
|
Chris@16
|
3513 typedef packaged_task<R> packaged_task_type;
|
Chris@16
|
3514
|
Chris@16
|
3515 #endif
|
Chris@16
|
3516
|
Chris@16
|
3517 if (int(policy) & int(launch::async))
|
Chris@16
|
3518 {
|
Chris@16
|
3519 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3520 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>(
|
Chris@16
|
3521 BF(
|
Chris@16
|
3522 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@16
|
3523 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@16
|
3524 )
|
Chris@16
|
3525 ));
|
Chris@16
|
3526 #else
|
Chris@16
|
3527 packaged_task_type pt( boost::forward<F>(f) );
|
Chris@16
|
3528
|
Chris@16
|
3529 BOOST_THREAD_FUTURE<R> ret = pt.get_future();
|
Chris@16
|
3530 ret.set_async();
|
Chris@16
|
3531 boost::thread( boost::move(pt) ).detach();
|
Chris@16
|
3532 return ::boost::move(ret);
|
Chris@16
|
3533 #endif
|
Chris@16
|
3534 }
|
Chris@16
|
3535 else if (int(policy) & int(launch::deferred))
|
Chris@16
|
3536 {
|
Chris@16
|
3537 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3538 return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>(
|
Chris@16
|
3539 BF(
|
Chris@16
|
3540 thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@16
|
3541 , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
|
Chris@16
|
3542 )
|
Chris@16
|
3543 ));
|
Chris@16
|
3544 #else
|
Chris@16
|
3545 std::terminate();
|
Chris@16
|
3546 BOOST_THREAD_FUTURE<R> ret;
|
Chris@16
|
3547 return ::boost::move(ret);
|
Chris@16
|
3548 // return boost::detail::make_future_deferred_shared_state<Rp>(
|
Chris@16
|
3549 // BF(
|
Chris@16
|
3550 // thread_detail::decay_copy(boost::forward<F>(f))
|
Chris@16
|
3551 // )
|
Chris@16
|
3552 // );
|
Chris@16
|
3553 #endif
|
Chris@16
|
3554
|
Chris@16
|
3555 } else {
|
Chris@16
|
3556 std::terminate();
|
Chris@16
|
3557 BOOST_THREAD_FUTURE<R> ret;
|
Chris@16
|
3558 return ::boost::move(ret);
|
Chris@16
|
3559 }
|
Chris@16
|
3560 }
|
Chris@16
|
3561
|
Chris@16
|
3562 ////////////////////////////////
|
Chris@16
|
3563 // template <class F, class... ArgTypes>
|
Chris@16
|
3564 // future<R> async(F&&, ArgTypes&&...);
|
Chris@16
|
3565 ////////////////////////////////
|
Chris@16
|
3566
|
Chris@16
|
3567 #if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
|
Chris@16
|
3568
|
Chris@16
|
3569 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3570 template <class R, class... ArgTypes>
|
Chris@16
|
3571 BOOST_THREAD_FUTURE<R>
|
Chris@16
|
3572 async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args)
|
Chris@16
|
3573 {
|
Chris@16
|
3574 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...));
|
Chris@16
|
3575 }
|
Chris@16
|
3576 #else
|
Chris@16
|
3577 template <class R>
|
Chris@16
|
3578 BOOST_THREAD_FUTURE<R>
|
Chris@16
|
3579 async(R(*f)())
|
Chris@16
|
3580 {
|
Chris@16
|
3581 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f));
|
Chris@16
|
3582 }
|
Chris@16
|
3583 #endif
|
Chris@16
|
3584 #endif
|
Chris@16
|
3585
|
Chris@16
|
3586 #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
|
Chris@16
|
3587 template <class F, class ...ArgTypes>
|
Chris@16
|
3588 BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type(
|
Chris@16
|
3589 typename decay<ArgTypes>::type...
|
Chris@16
|
3590 )>::type>
|
Chris@16
|
3591 async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args)
|
Chris@16
|
3592 {
|
Chris@16
|
3593 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...));
|
Chris@16
|
3594 }
|
Chris@16
|
3595 #else
|
Chris@16
|
3596 template <class F>
|
Chris@16
|
3597 BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type>
|
Chris@16
|
3598 async(BOOST_THREAD_RV_REF(F) f)
|
Chris@16
|
3599 {
|
Chris@16
|
3600 return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f)));
|
Chris@16
|
3601 }
|
Chris@16
|
3602 #endif
|
Chris@16
|
3603
|
Chris@16
|
3604
|
Chris@16
|
3605 ////////////////////////////////
|
Chris@16
|
3606 // make_future deprecated
|
Chris@16
|
3607 ////////////////////////////////
|
Chris@16
|
3608 template <typename T>
|
Chris@16
|
3609 BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value)
|
Chris@16
|
3610 {
|
Chris@16
|
3611 typedef typename decay<T>::type future_value_type;
|
Chris@16
|
3612 promise<future_value_type> p;
|
Chris@16
|
3613 p.set_value(boost::forward<future_value_type>(value));
|
Chris@16
|
3614 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3615 }
|
Chris@16
|
3616
|
Chris@16
|
3617 #if defined BOOST_THREAD_USES_MOVE
|
Chris@16
|
3618 inline BOOST_THREAD_FUTURE<void> make_future()
|
Chris@16
|
3619 {
|
Chris@16
|
3620 promise<void> p;
|
Chris@16
|
3621 p.set_value();
|
Chris@16
|
3622 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3623 }
|
Chris@16
|
3624 #endif
|
Chris@16
|
3625
|
Chris@16
|
3626 ////////////////////////////////
|
Chris@16
|
3627 // make_ready_future
|
Chris@16
|
3628 ////////////////////////////////
|
Chris@16
|
3629 template <typename T>
|
Chris@16
|
3630 BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value)
|
Chris@16
|
3631 {
|
Chris@16
|
3632 typedef typename decay<T>::type future_value_type;
|
Chris@16
|
3633 promise<future_value_type> p;
|
Chris@16
|
3634 p.set_value(boost::forward<future_value_type>(value));
|
Chris@16
|
3635 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3636 }
|
Chris@16
|
3637
|
Chris@16
|
3638 #if defined BOOST_THREAD_USES_MOVE
|
Chris@16
|
3639 inline BOOST_THREAD_FUTURE<void> make_ready_future()
|
Chris@16
|
3640 {
|
Chris@16
|
3641 promise<void> p;
|
Chris@16
|
3642 p.set_value();
|
Chris@16
|
3643 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3644 }
|
Chris@16
|
3645 #endif
|
Chris@16
|
3646
|
Chris@16
|
3647 template <typename T>
|
Chris@16
|
3648 BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex)
|
Chris@16
|
3649 {
|
Chris@16
|
3650 promise<T> p;
|
Chris@16
|
3651 p.set_exception(ex);
|
Chris@16
|
3652 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3653 }
|
Chris@16
|
3654 template <typename T, typename E>
|
Chris@16
|
3655 BOOST_THREAD_FUTURE<T> make_ready_future(E ex)
|
Chris@16
|
3656 {
|
Chris@16
|
3657 promise<T> p;
|
Chris@16
|
3658 p.set_exception(boost::copy_exception(ex));
|
Chris@16
|
3659 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3660 }
|
Chris@16
|
3661
|
Chris@16
|
3662 #if 0
|
Chris@16
|
3663 template<typename CLOSURE>
|
Chris@16
|
3664 make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> {
|
Chris@16
|
3665 typedef decltype(closure()) T;
|
Chris@16
|
3666 promise<T> p;
|
Chris@16
|
3667 try
|
Chris@16
|
3668 {
|
Chris@16
|
3669 p.set_value(closure());
|
Chris@16
|
3670 }
|
Chris@16
|
3671 catch(...)
|
Chris@16
|
3672 {
|
Chris@16
|
3673 p.set_exception(std::current_exception());
|
Chris@16
|
3674 }
|
Chris@16
|
3675 return BOOST_THREAD_MAKE_RV_REF(p.get_future());
|
Chris@16
|
3676 }
|
Chris@16
|
3677 #endif
|
Chris@16
|
3678
|
Chris@16
|
3679 ////////////////////////////////
|
Chris@16
|
3680 // make_shared_future deprecated
|
Chris@16
|
3681 ////////////////////////////////
|
Chris@16
|
3682 template <typename T>
|
Chris@16
|
3683 shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value)
|
Chris@16
|
3684 {
|
Chris@16
|
3685 typedef typename decay<T>::type future_type;
|
Chris@16
|
3686 promise<future_type> p;
|
Chris@16
|
3687 p.set_value(boost::forward<T>(value));
|
Chris@16
|
3688 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
|
Chris@16
|
3689 }
|
Chris@16
|
3690
|
Chris@16
|
3691
|
Chris@16
|
3692 inline shared_future<void> make_shared_future()
|
Chris@16
|
3693 {
|
Chris@16
|
3694 promise<void> p;
|
Chris@16
|
3695 return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
|
Chris@16
|
3696
|
Chris@16
|
3697 }
|
Chris@16
|
3698
|
Chris@16
|
3699 // ////////////////////////////////
|
Chris@16
|
3700 // // make_ready_shared_future
|
Chris@16
|
3701 // ////////////////////////////////
|
Chris@16
|
3702 // template <typename T>
|
Chris@16
|
3703 // shared_future<typename decay<T>::type> make_ready_shared_future(BOOST_THREAD_FWD_REF(T) value)
|
Chris@16
|
3704 // {
|
Chris@16
|
3705 // typedef typename decay<T>::type future_type;
|
Chris@16
|
3706 // promise<future_type> p;
|
Chris@16
|
3707 // p.set_value(boost::forward<T>(value));
|
Chris@16
|
3708 // return p.get_future().share();
|
Chris@16
|
3709 // }
|
Chris@16
|
3710 //
|
Chris@16
|
3711 //
|
Chris@16
|
3712 // inline shared_future<void> make_ready_shared_future()
|
Chris@16
|
3713 // {
|
Chris@16
|
3714 // promise<void> p;
|
Chris@16
|
3715 // return BOOST_THREAD_MAKE_RV_REF(p.get_future().share());
|
Chris@16
|
3716 //
|
Chris@16
|
3717 // }
|
Chris@16
|
3718 //
|
Chris@16
|
3719 // ////////////////////////////////
|
Chris@16
|
3720 // // make_exceptional_shared_future
|
Chris@16
|
3721 // ////////////////////////////////
|
Chris@16
|
3722 // template <typename T>
|
Chris@16
|
3723 // shared_future<T> make_exceptional_shared_future(exception_ptr ex)
|
Chris@16
|
3724 // {
|
Chris@16
|
3725 // promise<T> p;
|
Chris@16
|
3726 // p.set_exception(ex);
|
Chris@16
|
3727 // return p.get_future().share();
|
Chris@16
|
3728 // }
|
Chris@16
|
3729
|
Chris@16
|
3730 ////////////////////////////////
|
Chris@16
|
3731 // detail::future_async_continuation_shared_state
|
Chris@16
|
3732 ////////////////////////////////
|
Chris@16
|
3733 #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
Chris@16
|
3734 namespace detail
|
Chris@16
|
3735 {
|
Chris@16
|
3736
|
Chris@16
|
3737 /////////////////////////
|
Chris@16
|
3738 /// future_async_continuation_shared_state
|
Chris@16
|
3739 /////////////////////////
|
Chris@16
|
3740
|
Chris@16
|
3741 template<typename F, typename Rp, typename Fp>
|
Chris@16
|
3742 struct future_async_continuation_shared_state: future_async_shared_state_base<Rp>
|
Chris@16
|
3743 {
|
Chris@16
|
3744 F parent;
|
Chris@16
|
3745 Fp continuation;
|
Chris@16
|
3746
|
Chris@16
|
3747 public:
|
Chris@16
|
3748 future_async_continuation_shared_state(
|
Chris@16
|
3749 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
|
Chris@16
|
3750 ) :
|
Chris@16
|
3751 parent(boost::move(f)),
|
Chris@16
|
3752 continuation(boost::move(c))
|
Chris@16
|
3753 {
|
Chris@16
|
3754 }
|
Chris@16
|
3755
|
Chris@16
|
3756 void launch_continuation(boost::unique_lock<boost::mutex>& lock)
|
Chris@16
|
3757 {
|
Chris@16
|
3758 lock.unlock();
|
Chris@16
|
3759 this->thr_ = thread(&future_async_continuation_shared_state::run, this);
|
Chris@16
|
3760 }
|
Chris@16
|
3761
|
Chris@16
|
3762 static void run(future_async_continuation_shared_state* that)
|
Chris@16
|
3763 {
|
Chris@16
|
3764 try
|
Chris@16
|
3765 {
|
Chris@16
|
3766 that->mark_finished_with_result(that->continuation(boost::move(that->parent)));
|
Chris@16
|
3767 }
|
Chris@16
|
3768 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
3769 catch(thread_interrupted& )
|
Chris@16
|
3770 {
|
Chris@16
|
3771 that->mark_interrupted_finish();
|
Chris@16
|
3772 }
|
Chris@16
|
3773 #endif
|
Chris@16
|
3774 catch(...)
|
Chris@16
|
3775 {
|
Chris@16
|
3776 that->mark_exceptional_finish();
|
Chris@16
|
3777 }
|
Chris@16
|
3778 }
|
Chris@16
|
3779 ~future_async_continuation_shared_state()
|
Chris@16
|
3780 {
|
Chris@16
|
3781 this->join();
|
Chris@16
|
3782 }
|
Chris@16
|
3783 };
|
Chris@16
|
3784
|
Chris@16
|
3785 template<typename F, typename Fp>
|
Chris@16
|
3786 struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void>
|
Chris@16
|
3787 {
|
Chris@16
|
3788 F parent;
|
Chris@16
|
3789 Fp continuation;
|
Chris@16
|
3790
|
Chris@16
|
3791 public:
|
Chris@16
|
3792 future_async_continuation_shared_state(
|
Chris@16
|
3793 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
|
Chris@16
|
3794 ) :
|
Chris@16
|
3795 parent(boost::move(f)),
|
Chris@16
|
3796 continuation(boost::move(c))
|
Chris@16
|
3797 {
|
Chris@16
|
3798 }
|
Chris@16
|
3799
|
Chris@16
|
3800 void launch_continuation(boost::unique_lock<boost::mutex>& lk)
|
Chris@16
|
3801 {
|
Chris@16
|
3802 lk.unlock();
|
Chris@16
|
3803 this->thr_ = thread(&future_async_continuation_shared_state::run, this);
|
Chris@16
|
3804 }
|
Chris@16
|
3805
|
Chris@16
|
3806 static void run(future_async_continuation_shared_state* that)
|
Chris@16
|
3807 {
|
Chris@16
|
3808 try
|
Chris@16
|
3809 {
|
Chris@16
|
3810 that->continuation(boost::move(that->parent));
|
Chris@16
|
3811 that->mark_finished_with_result();
|
Chris@16
|
3812 }
|
Chris@16
|
3813 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
Chris@16
|
3814 catch(thread_interrupted& )
|
Chris@16
|
3815 {
|
Chris@16
|
3816 that->mark_interrupted_finish();
|
Chris@16
|
3817 }
|
Chris@16
|
3818 #endif
|
Chris@16
|
3819 catch(...)
|
Chris@16
|
3820 {
|
Chris@16
|
3821 that->mark_exceptional_finish();
|
Chris@16
|
3822 }
|
Chris@16
|
3823 }
|
Chris@16
|
3824 ~future_async_continuation_shared_state()
|
Chris@16
|
3825 {
|
Chris@16
|
3826 this->join();
|
Chris@16
|
3827 }
|
Chris@16
|
3828 };
|
Chris@16
|
3829
|
Chris@16
|
3830
|
Chris@16
|
3831 //////////////////////////
|
Chris@16
|
3832 /// future_deferred_continuation_shared_state
|
Chris@16
|
3833 //////////////////////////
|
Chris@16
|
3834 template<typename F, typename Rp, typename Fp>
|
Chris@16
|
3835 struct future_deferred_continuation_shared_state: shared_state<Rp>
|
Chris@16
|
3836 {
|
Chris@16
|
3837 F parent;
|
Chris@16
|
3838 Fp continuation;
|
Chris@16
|
3839
|
Chris@16
|
3840 public:
|
Chris@16
|
3841 future_deferred_continuation_shared_state(
|
Chris@16
|
3842 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
|
Chris@16
|
3843 ) :
|
Chris@16
|
3844 parent(boost::move(f)),
|
Chris@16
|
3845 continuation(boost::move(c))
|
Chris@16
|
3846 {
|
Chris@16
|
3847 this->set_deferred();
|
Chris@16
|
3848 }
|
Chris@16
|
3849
|
Chris@16
|
3850 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
|
Chris@16
|
3851 {
|
Chris@16
|
3852 execute(lk);
|
Chris@16
|
3853 }
|
Chris@16
|
3854
|
Chris@16
|
3855 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@16
|
3856 try
|
Chris@16
|
3857 {
|
Chris@16
|
3858 Fp local_fuct=boost::move(continuation);
|
Chris@16
|
3859 F ftmp = boost::move(parent);
|
Chris@16
|
3860 relocker relock(lck);
|
Chris@16
|
3861 Rp res = local_fuct(boost::move(ftmp));
|
Chris@16
|
3862 relock.lock();
|
Chris@16
|
3863 this->mark_finished_with_result_internal(boost::move(res), lck);
|
Chris@16
|
3864 }
|
Chris@16
|
3865 catch (...)
|
Chris@16
|
3866 {
|
Chris@16
|
3867 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@16
|
3868 }
|
Chris@16
|
3869 }
|
Chris@16
|
3870 };
|
Chris@16
|
3871
|
Chris@16
|
3872 template<typename F, typename Fp>
|
Chris@16
|
3873 struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void>
|
Chris@16
|
3874 {
|
Chris@16
|
3875 F parent;
|
Chris@16
|
3876 Fp continuation;
|
Chris@16
|
3877
|
Chris@16
|
3878 public:
|
Chris@16
|
3879 future_deferred_continuation_shared_state(
|
Chris@16
|
3880 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
|
Chris@16
|
3881 ):
|
Chris@16
|
3882 parent(boost::move(f)),
|
Chris@16
|
3883 continuation(boost::move(c))
|
Chris@16
|
3884 {
|
Chris@16
|
3885 this->set_deferred();
|
Chris@16
|
3886 }
|
Chris@16
|
3887
|
Chris@16
|
3888 virtual void launch_continuation(boost::unique_lock<boost::mutex>& lk)
|
Chris@16
|
3889 {
|
Chris@16
|
3890 execute(lk);
|
Chris@16
|
3891 }
|
Chris@16
|
3892 virtual void execute(boost::unique_lock<boost::mutex>& lck) {
|
Chris@16
|
3893 try
|
Chris@16
|
3894 {
|
Chris@16
|
3895 Fp local_fuct=boost::move(continuation);
|
Chris@16
|
3896 F ftmp = boost::move(parent);
|
Chris@16
|
3897 relocker relock(lck);
|
Chris@16
|
3898 local_fuct(boost::move(ftmp));
|
Chris@16
|
3899 relock.lock();
|
Chris@16
|
3900 this->mark_finished_with_result_internal(lck);
|
Chris@16
|
3901 }
|
Chris@16
|
3902 catch (...)
|
Chris@16
|
3903 {
|
Chris@16
|
3904 this->mark_exceptional_finish_internal(current_exception(), lck);
|
Chris@16
|
3905 }
|
Chris@16
|
3906 }
|
Chris@16
|
3907 };
|
Chris@16
|
3908
|
Chris@16
|
3909 ////////////////////////////////
|
Chris@16
|
3910 // make_future_deferred_continuation_shared_state
|
Chris@16
|
3911 ////////////////////////////////
|
Chris@16
|
3912 template<typename F, typename Rp, typename Fp>
|
Chris@16
|
3913 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
3914 make_future_deferred_continuation_shared_state(
|
Chris@16
|
3915 boost::unique_lock<boost::mutex> &lock,
|
Chris@16
|
3916 BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
|
Chris@16
|
3917 )
|
Chris@16
|
3918 {
|
Chris@16
|
3919 shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> >
|
Chris@16
|
3920 h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
|
Chris@16
|
3921 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@16
|
3922 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@16
|
3923 }
|
Chris@16
|
3924
|
Chris@16
|
3925 ////////////////////////////////
|
Chris@16
|
3926 // make_future_async_continuation_shared_state
|
Chris@16
|
3927 ////////////////////////////////
|
Chris@16
|
3928 template<typename F, typename Rp, typename Fp>
|
Chris@16
|
3929 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
3930 make_future_async_continuation_shared_state(
|
Chris@16
|
3931 boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c
|
Chris@16
|
3932 )
|
Chris@16
|
3933 {
|
Chris@16
|
3934 shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> >
|
Chris@16
|
3935 h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c)));
|
Chris@16
|
3936 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@16
|
3937
|
Chris@16
|
3938 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@16
|
3939 }
|
Chris@16
|
3940
|
Chris@16
|
3941 }
|
Chris@16
|
3942
|
Chris@16
|
3943 ////////////////////////////////
|
Chris@16
|
3944 // template<typename F>
|
Chris@16
|
3945 // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
|
Chris@16
|
3946 ////////////////////////////////
|
Chris@16
|
3947
|
Chris@16
|
3948 template <typename R>
|
Chris@16
|
3949 template <typename F>
|
Chris@16
|
3950 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
|
Chris@16
|
3951 BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func)
|
Chris@16
|
3952 {
|
Chris@16
|
3953
|
Chris@16
|
3954 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
Chris@16
|
3955 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
3956
|
Chris@16
|
3957 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@16
|
3958 if (int(policy) & int(launch::async))
|
Chris@16
|
3959 {
|
Chris@16
|
3960 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
3961 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
3962 )));
|
Chris@16
|
3963 }
|
Chris@16
|
3964 else if (int(policy) & int(launch::deferred))
|
Chris@16
|
3965 {
|
Chris@16
|
3966 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
3967 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
3968 )));
|
Chris@16
|
3969 }
|
Chris@16
|
3970 else
|
Chris@16
|
3971 {
|
Chris@16
|
3972 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
3973 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
3974 )));
|
Chris@16
|
3975
|
Chris@16
|
3976 }
|
Chris@16
|
3977
|
Chris@16
|
3978 }
|
Chris@16
|
3979 template <typename R>
|
Chris@16
|
3980 template <typename F>
|
Chris@16
|
3981 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type>
|
Chris@16
|
3982 BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func)
|
Chris@16
|
3983 {
|
Chris@16
|
3984
|
Chris@16
|
3985 typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type;
|
Chris@16
|
3986 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
3987
|
Chris@16
|
3988 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@16
|
3989 if (int(this->launch_policy(lock)) & int(launch::async))
|
Chris@16
|
3990 {
|
Chris@16
|
3991 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
3992 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
3993 );
|
Chris@16
|
3994 }
|
Chris@16
|
3995 else if (int(this->launch_policy(lock)) & int(launch::deferred))
|
Chris@16
|
3996 {
|
Chris@16
|
3997 this->future_->wait_internal(lock);
|
Chris@16
|
3998 return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
3999 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4000 );
|
Chris@16
|
4001 }
|
Chris@16
|
4002 else
|
Chris@16
|
4003 {
|
Chris@16
|
4004 return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>(
|
Chris@16
|
4005 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4006 );
|
Chris@16
|
4007 }
|
Chris@16
|
4008 }
|
Chris@16
|
4009
|
Chris@16
|
4010
|
Chris@16
|
4011 //#if 0 && defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR)
|
Chris@16
|
4012 // template <typename R>
|
Chris@16
|
4013 // template<typename RF>
|
Chris@16
|
4014 // BOOST_THREAD_FUTURE<RF>
|
Chris@16
|
4015 // BOOST_THREAD_FUTURE<R>::then(RF(*func)(BOOST_THREAD_FUTURE<R>&))
|
Chris@16
|
4016 // {
|
Chris@16
|
4017 //
|
Chris@16
|
4018 // typedef RF future_type;
|
Chris@16
|
4019 //
|
Chris@16
|
4020 // if (this->future_)
|
Chris@16
|
4021 // {
|
Chris@16
|
4022 // boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@16
|
4023 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
|
Chris@16
|
4024 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func);
|
Chris@16
|
4025 // if (ptr==0)
|
Chris@16
|
4026 // {
|
Chris@16
|
4027 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
|
Chris@16
|
4028 // }
|
Chris@16
|
4029 // this->future_->set_continuation_ptr(ptr, lock);
|
Chris@16
|
4030 // return ptr->get_future();
|
Chris@16
|
4031 // } else {
|
Chris@16
|
4032 // // fixme what to do when the future has no associated state?
|
Chris@16
|
4033 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
|
Chris@16
|
4034 // }
|
Chris@16
|
4035 //
|
Chris@16
|
4036 // }
|
Chris@16
|
4037 // template <typename R>
|
Chris@16
|
4038 // template<typename RF>
|
Chris@16
|
4039 // BOOST_THREAD_FUTURE<RF>
|
Chris@16
|
4040 // BOOST_THREAD_FUTURE<R>::then(launch policy, RF(*func)(BOOST_THREAD_FUTURE<R>&))
|
Chris@16
|
4041 // {
|
Chris@16
|
4042 //
|
Chris@16
|
4043 // typedef RF future_type;
|
Chris@16
|
4044 //
|
Chris@16
|
4045 // if (this->future_)
|
Chris@16
|
4046 // {
|
Chris@16
|
4047 // boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@16
|
4048 // detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr =
|
Chris@16
|
4049 // new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func, policy);
|
Chris@16
|
4050 // if (ptr==0)
|
Chris@16
|
4051 // {
|
Chris@16
|
4052 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
|
Chris@16
|
4053 // }
|
Chris@16
|
4054 // this->future_->set_continuation_ptr(ptr, lock);
|
Chris@16
|
4055 // return ptr->get_future();
|
Chris@16
|
4056 // } else {
|
Chris@16
|
4057 // // fixme what to do when the future has no associated state?
|
Chris@16
|
4058 // return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>());
|
Chris@16
|
4059 // }
|
Chris@16
|
4060 //
|
Chris@16
|
4061 // }
|
Chris@16
|
4062 //#endif
|
Chris@16
|
4063
|
Chris@16
|
4064 template <typename R>
|
Chris@16
|
4065 template <typename F>
|
Chris@16
|
4066 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
|
Chris@16
|
4067 shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func)
|
Chris@16
|
4068 {
|
Chris@16
|
4069
|
Chris@16
|
4070 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
|
Chris@16
|
4071 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
4072
|
Chris@16
|
4073 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@16
|
4074 if (int(policy) & int(launch::async))
|
Chris@16
|
4075 {
|
Chris@16
|
4076 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@16
|
4077 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4078 )));
|
Chris@16
|
4079 }
|
Chris@16
|
4080 else if (int(policy) & int(launch::deferred))
|
Chris@16
|
4081 {
|
Chris@16
|
4082 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@16
|
4083 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4084 )));
|
Chris@16
|
4085 }
|
Chris@16
|
4086 else
|
Chris@16
|
4087 {
|
Chris@16
|
4088 return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@16
|
4089 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4090 )));
|
Chris@16
|
4091 }
|
Chris@16
|
4092
|
Chris@16
|
4093 }
|
Chris@16
|
4094 template <typename R>
|
Chris@16
|
4095 template <typename F>
|
Chris@16
|
4096 inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type>
|
Chris@16
|
4097 shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func)
|
Chris@16
|
4098 {
|
Chris@16
|
4099
|
Chris@16
|
4100 typedef typename boost::result_of<F(shared_future<R>)>::type future_type;
|
Chris@16
|
4101
|
Chris@16
|
4102 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
4103
|
Chris@16
|
4104 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@16
|
4105 if (int(this->launch_policy(lock)) & int(launch::async))
|
Chris@16
|
4106 {
|
Chris@16
|
4107 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@16
|
4108 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4109 );
|
Chris@16
|
4110 }
|
Chris@16
|
4111 else if (int(this->launch_policy(lock)) & int(launch::deferred))
|
Chris@16
|
4112 {
|
Chris@16
|
4113 this->future_->wait_internal(lock);
|
Chris@16
|
4114 return boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@16
|
4115 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4116 );
|
Chris@16
|
4117 }
|
Chris@16
|
4118 else
|
Chris@16
|
4119 {
|
Chris@16
|
4120 return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>(
|
Chris@16
|
4121 lock, boost::move(*this), boost::forward<F>(func)
|
Chris@16
|
4122 );
|
Chris@16
|
4123 }
|
Chris@16
|
4124 }
|
Chris@16
|
4125 namespace detail
|
Chris@16
|
4126 {
|
Chris@16
|
4127 template <typename T>
|
Chris@16
|
4128 struct mfallbacker_to
|
Chris@16
|
4129 {
|
Chris@16
|
4130 T value_;
|
Chris@16
|
4131 typedef T result_type;
|
Chris@16
|
4132 mfallbacker_to(BOOST_THREAD_RV_REF(T) v)
|
Chris@16
|
4133 : value_(boost::move(v))
|
Chris@16
|
4134 {}
|
Chris@16
|
4135
|
Chris@16
|
4136 T operator()(BOOST_THREAD_FUTURE<T> fut)
|
Chris@16
|
4137 {
|
Chris@16
|
4138 return fut.get_or(boost::move(value_));
|
Chris@16
|
4139
|
Chris@16
|
4140 }
|
Chris@16
|
4141 };
|
Chris@16
|
4142 template <typename T>
|
Chris@16
|
4143 struct cfallbacker_to
|
Chris@16
|
4144 {
|
Chris@16
|
4145 T value_;
|
Chris@16
|
4146 typedef T result_type;
|
Chris@16
|
4147 cfallbacker_to(T const& v)
|
Chris@16
|
4148 : value_(v)
|
Chris@16
|
4149 {}
|
Chris@16
|
4150
|
Chris@16
|
4151 T operator()(BOOST_THREAD_FUTURE<T> fut)
|
Chris@16
|
4152 {
|
Chris@16
|
4153 return fut.get_or(value_);
|
Chris@16
|
4154
|
Chris@16
|
4155 }
|
Chris@16
|
4156 };
|
Chris@16
|
4157 }
|
Chris@16
|
4158 ////////////////////////////////
|
Chris@16
|
4159 // future<R> future<R>::fallback_to(R&& v);
|
Chris@16
|
4160 ////////////////////////////////
|
Chris@16
|
4161
|
Chris@16
|
4162 template <typename R>
|
Chris@16
|
4163 template <typename R2>
|
Chris@16
|
4164 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
|
Chris@16
|
4165 BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v)
|
Chris@16
|
4166 {
|
Chris@16
|
4167 return then(detail::mfallbacker_to<R>(boost::move(v)));
|
Chris@16
|
4168 }
|
Chris@16
|
4169
|
Chris@16
|
4170 template <typename R>
|
Chris@16
|
4171 template <typename R2>
|
Chris@16
|
4172 inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type
|
Chris@16
|
4173 BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v)
|
Chris@16
|
4174 {
|
Chris@16
|
4175 return then(detail::cfallbacker_to<R>(v));
|
Chris@16
|
4176 }
|
Chris@16
|
4177
|
Chris@16
|
4178 #endif
|
Chris@16
|
4179
|
Chris@16
|
4180 #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP
|
Chris@16
|
4181 namespace detail
|
Chris@16
|
4182 {
|
Chris@16
|
4183
|
Chris@16
|
4184 /////////////////////////
|
Chris@16
|
4185 /// future_unwrap_shared_state
|
Chris@16
|
4186 /////////////////////////
|
Chris@16
|
4187
|
Chris@16
|
4188 template<typename F, typename Rp>
|
Chris@16
|
4189 struct future_unwrap_shared_state: shared_state<Rp>
|
Chris@16
|
4190 {
|
Chris@16
|
4191 F parent;
|
Chris@16
|
4192 public:
|
Chris@16
|
4193 explicit future_unwrap_shared_state(
|
Chris@16
|
4194 BOOST_THREAD_RV_REF(F) f
|
Chris@16
|
4195 ) :
|
Chris@16
|
4196 parent(boost::move(f))
|
Chris@16
|
4197 {
|
Chris@16
|
4198 }
|
Chris@16
|
4199 virtual void wait(bool ) // todo see if rethrow must be used
|
Chris@16
|
4200 {
|
Chris@16
|
4201 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
4202 parent.get().wait();
|
Chris@16
|
4203 }
|
Chris@16
|
4204 virtual Rp get()
|
Chris@16
|
4205 {
|
Chris@16
|
4206 boost::unique_lock<boost::mutex> lock(mutex);
|
Chris@16
|
4207 return parent.get().get();
|
Chris@16
|
4208 }
|
Chris@16
|
4209
|
Chris@16
|
4210 };
|
Chris@16
|
4211
|
Chris@16
|
4212 template <class F, class Rp>
|
Chris@16
|
4213 BOOST_THREAD_FUTURE<Rp>
|
Chris@16
|
4214 make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f)
|
Chris@16
|
4215 {
|
Chris@16
|
4216 shared_ptr<future_unwrap_shared_state<F, Rp> >
|
Chris@16
|
4217 h(new future_unwrap_shared_state<F, Rp>(boost::move(f)));
|
Chris@16
|
4218 h->parent.future_->set_continuation_ptr(h, lock);
|
Chris@16
|
4219 return BOOST_THREAD_FUTURE<Rp>(h);
|
Chris@16
|
4220 }
|
Chris@16
|
4221 }
|
Chris@16
|
4222
|
Chris@16
|
4223 template <typename R>
|
Chris@16
|
4224 inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other):
|
Chris@16
|
4225 base_type(other.unwrap())
|
Chris@16
|
4226 {
|
Chris@16
|
4227 }
|
Chris@16
|
4228
|
Chris@16
|
4229 template <typename R2>
|
Chris@16
|
4230 BOOST_THREAD_FUTURE<R2>
|
Chris@16
|
4231 BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap()
|
Chris@16
|
4232 {
|
Chris@16
|
4233 BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized());
|
Chris@16
|
4234 boost::unique_lock<boost::mutex> lock(this->future_->mutex);
|
Chris@16
|
4235 return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this));
|
Chris@16
|
4236 }
|
Chris@16
|
4237 #endif
|
Chris@16
|
4238 }
|
Chris@16
|
4239
|
Chris@16
|
4240 #endif // BOOST_NO_EXCEPTION
|
Chris@16
|
4241 #endif // header
|