33class task_future_base {
34 auto wait_predicate() {
35 return [
this]{
return state != task_state::pending; };
38 task_state get_state() {
39 std::lock_guard<std::mutex> lock(mutex);
43 std::exception_ptr get_exception() {
44 std::lock_guard<std::mutex> lock(mutex);
48 void set_exception(std::exception_ptr exception) {
50 std::lock_guard<std::mutex> lock(mutex);
51 state = task_state::failed;
52 this->exception = exception;
54 condition_variable.notify_all();
58 std::unique_lock<std::mutex> lock(mutex);
59 condition_variable.wait(lock, wait_predicate());
62 template<
class Rep,
class Period>
63 bool wait_for(
const std::chrono::duration<Rep, Period>& timeout_duration) {
64 std::unique_lock<std::mutex> lock(mutex);
65 return condition_variable.wait_for(lock, timeout_duration, wait_predicate());
68 template<
class Clock,
class Duration>
69 bool wait_until(
const std::chrono::time_point<Clock, Duration>& timeout_time) {
70 std::unique_lock<std::mutex> lock(mutex);
71 return condition_variable.wait_until(lock, timeout_time, wait_predicate());
76 std::condition_variable condition_variable;
77 std::exception_ptr exception;
87 : state(task_state::failed)
88 , exception(exception)
92 task_future_base(
const task_future_base&) =
delete;
93 task_future_base& operator=(
const task_future_base&) =
delete;
98class task_future :
public task_future_base,
public std::enable_shared_from_this<task_future<T>> {
100 using value_type = T;
102 template<
typename... Args>
110 , value(std::move(value))
115 if (state == task_state::ready) {
120 static std::shared_ptr<task_future> create_pending() {
123 static std::shared_ptr<task_future> create_ready(T&& value) {
126 static std::shared_ptr<task_future> create_failed(std::exception_ptr exception) {
130 static std::shared_ptr<task_future> create(F&& work) {
133 return create_ready(std::move(value));
135 DISPATCH_QUEUE_CATCH(...) {
136 return create_failed(std::current_exception());
142 auto continuation_future = task_future<function_result<F>>::create_pending();
143 std::unique_lock<std::mutex> lock(mutex);
144 if (state == task_state::pending) {
145 continuations.push_back([=]() {
146 continuation_future->do_work(f);
151 continuation_future->do_work(f);
153 return continuation_future;
159 std::rethrow_exception(exception);
164 template<
typename F,
typename... Args>
165 void do_work(F&& work, Args&&... args) {
167 auto value = work(std::forward<Args>(args)...);
168 set_value(std::move(value));
170 DISPATCH_QUEUE_CATCH(...) {
171 set_exception(std::current_exception());
174 auto continuations = std::move(this->continuations);
175 for (
auto&& continuation : continuations) {
181 auto wrap(F&& work) {
182 auto shared_this = this->shared_from_this();
183 return [shared_this, work]{
184 shared_this->do_work(work);
188 void set_value(T&& value) {
190 std::lock_guard<std::mutex> lock(mutex);
191 state = task_state::ready;
192 this->value = std::move(value);
194 condition_variable.notify_all();
198 std::vector<std::function<void()>> continuations;
207class task_future<void> :
public task_future_base,
public std::enable_shared_from_this<task_future<void>> {
209 using value_type = void;
211 template<
typename... Args>
217 static std::shared_ptr<task_future> create_pending() {
220 static std::shared_ptr<task_future> create_ready() {
223 static std::shared_ptr<task_future> create_failed(std::exception_ptr exception) {
227 static std::shared_ptr<task_future> create(F&& work) {
230 return create_ready();
232 DISPATCH_QUEUE_CATCH(...) {
233 return create_failed(std::current_exception());
239 auto continuation_future = task_future<function_result<F>>::create_pending();
240 std::unique_lock<std::mutex> lock(mutex);
241 if (state == task_state::pending) {
242 continuations.push_back([=]() {
243 continuation_future->do_work(f);
248 continuation_future->do_work(f);
250 return continuation_future;
256 std::rethrow_exception(exception);
260 template<
typename F,
typename... Args>
261 void do_work(F&& work, Args&&... args) {
263 work(std::forward<Args>(args)...);
266 DISPATCH_QUEUE_CATCH(...) {
267 set_exception(std::current_exception());
270 auto continuations = std::move(this->continuations);
271 for (
auto&& continuation : continuations) {
277 auto wrap(F&& work) {
278 auto shared_this = this->shared_from_this();
279 return [shared_this, work]{
280 shared_this->do_work(work);
286 std::lock_guard<std::mutex> lock(mutex);
287 state = task_state::ready;
289 condition_variable.notify_all();
293 std::vector<std::function<void()>> continuations;