diff --git a/cpp/async/handle_base.hpp b/cpp/async/handle_base.hpp index 1e7776ad5f..d7d9eca5a6 100644 --- a/cpp/async/handle_base.hpp +++ b/cpp/async/handle_base.hpp @@ -237,6 +237,9 @@ class handle_base inline void set_value(T&& value) { std::unique_lock lock(data_->lock_); + if (is_cancelled(data_)) { + return; + } ASSERT(!has_result(data_)); data_->result_ = Result(std::forward(value)); on_result_updated(std::move(lock), data_); @@ -247,6 +250,9 @@ class handle_base inline void set_value(T&& value) { std::unique_lock lock(data_->lock_); + if (is_cancelled(data_)) { + return; + } ASSERT(!has_result(data_)); data_->result_ = Result(std::forward(value)); on_result_updated(std::move(lock), data_); @@ -257,6 +263,9 @@ class handle_base requires(std::is_void_v) { std::unique_lock lock(data_->lock_); + if (is_cancelled(data_)) { + return; + } ASSERT(!has_result(data_)); data_->result_->set_fulfilled(); on_result_updated(std::move(lock), data_); @@ -265,6 +274,9 @@ class handle_base inline void set_exception(std::exception_ptr ex) { std::unique_lock lock(data_->lock_); + if (is_cancelled(data_)) { + return; + } ASSERT(!has_result(data_) || !data_->result_->succeeded()); data_->result_ = std::move(ex); on_result_updated(std::move(lock), data_); diff --git a/cpp/async/promise.hpp b/cpp/async/promise.hpp index b7019733e2..2a5e42d89c 100644 --- a/cpp/async/promise.hpp +++ b/cpp/async/promise.hpp @@ -237,7 +237,8 @@ class promise * or re-raises the exception in case of failure. * * @pre The promise should have no callback registered. This is a mutually exclusive interface with set_callback. - * @warning The future will be forever locked if the promise will be cancelled. + * @warning Successful cancellation clears the callback and makes the future ready with + * std::future_errc::broken_promise, rather than delivering a result value. */ [[nodiscard]] inline std::future get_future() {