Skip to content

Commit 5cba660

Browse files
committed
Remove task_future::create(task_state)
This avoids the possibility of creating futures with invalid state (e.g.: with task_state::exception but with an empty exception_ptr)
1 parent f81c5d1 commit 5cba660

4 files changed

Lines changed: 28 additions & 15 deletions

File tree

include/dispatch_queue.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,12 @@ class dispatch_queue {
207207
task<Ret> dispatch_internal(bool run_on_main_loop, F&& f, Args&&... args) {
208208
auto work = std::bind(std::move(f), std::forward<Args>(args)...);
209209
if (worker_pool) {
210-
auto future = detail::task_future<Ret>::create(task_state::pending);
210+
auto future = detail::task_future<Ret>::create_pending();
211211
worker_pool->enqueue_task({ future->wrap(work) }, run_on_main_loop);
212212
return task<Ret>(future);
213213
}
214214
else if (run_on_main_loop) {
215-
auto future = detail::task_future<Ret>::create(task_state::pending);
215+
auto future = detail::task_future<Ret>::create_pending();
216216
task_queue.push({ future->wrap(work) }, run_on_main_loop);
217217
return task<Ret>(future);
218218
}

include/promise.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class promise {
2424
}
2525

2626
private:
27-
std::shared_ptr<detail::task_future<T>> future = detail::task_future<T>::create();
27+
std::shared_ptr<detail::task_future<T>> future = detail::task_future<T>::create_pending();
2828
};
2929

3030

@@ -42,7 +42,7 @@ class promise<void> {
4242
}
4343

4444
private:
45-
std::shared_ptr<detail::task_future<void>> future = detail::task_future<void>::create();
45+
std::shared_ptr<detail::task_future<void>> future = detail::task_future<void>::create_pending();
4646
};
4747

4848
} // end namespace detail

include/task.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class task {
3838
template<typename F>
3939
requires (detail::is_instance_of<T, task>::value)
4040
auto then(F&& f) const {
41-
auto nested_future = detail::task_future<detail::function_result<F, T>>::create();
41+
auto nested_future = detail::task_future<detail::function_result<F, T>>::create_pending();
4242
task value_this = *this;
4343
future->then([=]() {
4444
value_this.get().then([=](auto t) {

include/task_future.hpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -116,22 +116,29 @@ class task_future : public task_future_base, public std::enable_shared_from_this
116116
}
117117
}
118118

119-
static std::shared_ptr<task_future> create(task_state state = task_state::pending) {
120-
return std::make_shared<task_future>(private_construct{}, state);
119+
static std::shared_ptr<task_future> create_pending() {
120+
return std::make_shared<task_future>(private_construct{}, task_state::pending);
121+
}
122+
static std::shared_ptr<task_future> create_ready(T&& value) {
123+
return std::make_shared<task_future>(private_construct{}, std::move(value));
124+
}
125+
static std::shared_ptr<task_future> create_exception(std::exception_ptr exception) {
126+
return std::make_shared<task_future>(private_construct{}, exception);
121127
}
122128
template<typename F>
123129
static std::shared_ptr<task_future> create(F&& work) {
124130
DISPATCH_QUEUE_TRY {
125-
return std::make_shared<task_future>(private_construct{}, std::move(work()));
131+
auto value = work();
132+
return create_ready(std::move(value));
126133
}
127134
DISPATCH_QUEUE_CATCH(...) {
128-
return std::make_shared<task_future>(private_construct{}, std::current_exception());
135+
return create_exception(std::current_exception());
129136
}
130137
}
131138

132139
template<typename F>
133140
auto then(F&& f) {
134-
auto continuation_future = task_future<function_result<F>>::create();
141+
auto continuation_future = task_future<function_result<F>>::create_pending();
135142
std::unique_lock<std::mutex> lock(mutex);
136143
if (state == task_state::pending) {
137144
continuations.push_back([=]() {
@@ -206,23 +213,29 @@ class task_future<void> : public task_future_base, public std::enable_shared_fro
206213
{
207214
}
208215

209-
static std::shared_ptr<task_future> create(task_state state = task_state::pending) {
210-
return std::make_shared<task_future>(private_construct{}, state);
216+
static std::shared_ptr<task_future> create_pending() {
217+
return std::make_shared<task_future>(private_construct{}, task_state::pending);
218+
}
219+
static std::shared_ptr<task_future> create_ready() {
220+
return std::make_shared<task_future>(private_construct{}, task_state::ready);
221+
}
222+
static std::shared_ptr<task_future> create_exception(std::exception_ptr exception) {
223+
return std::make_shared<task_future>(private_construct{}, exception);
211224
}
212225
template<typename F>
213226
static std::shared_ptr<task_future> create(F&& work) {
214227
DISPATCH_QUEUE_TRY {
215228
work();
216-
return std::make_shared<task_future>(private_construct{}, task_state::ready);
229+
return create_ready();
217230
}
218231
DISPATCH_QUEUE_CATCH(...) {
219-
return std::make_shared<task_future>(private_construct{}, std::current_exception());
232+
return create_exception(std::current_exception());
220233
}
221234
}
222235

223236
template<typename F>
224237
auto then(F&& f) {
225-
auto continuation_future = task_future<function_result<F>>::create();
238+
auto continuation_future = task_future<function_result<F>>::create_pending();
226239
std::unique_lock<std::mutex> lock(mutex);
227240
if (state == task_state::pending) {
228241
continuations.push_back([=]() {

0 commit comments

Comments
 (0)