Skip to content

Commit

Permalink
feat: add promise<>::unfulfill_and_harvest()
Browse files Browse the repository at this point in the history
  • Loading branch information
yulon committed Jul 27, 2023
1 parent 26241eb commit 50bb122
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 27 deletions.
2 changes: 1 addition & 1 deletion include/rua/sync/chan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class chan {
return future<T>(*prm);
}

prm->destroy();
prm->unfulfill_and_harvest();

return *std::move(val_opt);
}
Expand Down
11 changes: 5 additions & 6 deletions include/rua/sync/future.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,6 @@ class future : private enable_await_operators {
public:
virtual ~promise_type() = default;

void destroy() noexcept override {
coroutine_handle<promise_type>::from_promise(*this).destroy();
}

////////////////////////////////////////////////////////////////////

future get_return_object() noexcept {
return *static_cast<promise<PromiseValue> *>(this);
}
Expand All @@ -71,6 +65,11 @@ class future : private enable_await_operators {
this->fulfill(current_exception_error());
}
#endif

protected:
void on_destroy() noexcept override {
coroutine_handle<promise_type>::from_promise(*this).destroy();
}
};

////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion include/rua/sync/mutex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class mutex {
return future<>(*prm);
}

prm->destroy();
prm->unfulfill_and_harvest();

return future<>();
}
Expand Down
53 changes: 35 additions & 18 deletions include/rua/sync/promise.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ enum class promise_state : uintptr_t {
loss_notify,
has_notify,
fulfilled,
received
harvested
#ifndef NDEBUG
,
destroying
#endif
};

RUA_CVAR strv_error err_promise_unfulfilled("promise unfulfilled");
Expand All @@ -37,9 +41,14 @@ class promise<T, void> {
promise &operator=(const promise &) = delete;
promise &operator=(promise &&) = delete;

virtual ~promise() = default;
virtual ~promise() {
#ifndef NDEBUG
auto old_state = $state.load();
assert(old_state == promise_state::destroying);
#endif
}

/////////////////// fulfill side ///////////////////
//////////////////// fulfill ////////////////////

expected<T> fulfill(
expected<T> value = expected_or<T>(err_promise_unfulfilled)) noexcept {
Expand All @@ -56,9 +65,12 @@ class promise<T, void> {

switch (old_state) {

case promise_state::received:
case promise_state::harvested:
assert(
$state.exchange(promise_state::destroying) ==
promise_state::fulfilled);
refunded = std::move($val);
destroy();
on_destroy();
break;

case promise_state::has_notify: {
Expand All @@ -80,10 +92,10 @@ class promise<T, void> {
fulfill(err_promise_unfulfilled);
}

/////////////////// receive side ///////////////////
////////////////// harvesting //////////////////

bool await_ready() const noexcept {
assert($state.load() != promise_state::received);
assert($state.load() != promise_state::harvested);

return $state.load() == promise_state::fulfilled;
}
Expand All @@ -98,7 +110,7 @@ class promise<T, void> {
}

assert(old_state != promise_state::has_notify);
assert(old_state != promise_state::received);
assert(old_state != promise_state::harvested);
assert(
old_state == promise_state::loss_notify ||
old_state == promise_state::fulfilled);
Expand All @@ -109,26 +121,31 @@ class promise<T, void> {
expected<T> await_resume() noexcept {
expected<T> r;

auto old_state = $state.exchange(promise_state::received);
auto old_state = $state.exchange(promise_state::harvested);

assert(old_state != promise_state::received);
assert(old_state != promise_state::harvested);

if (old_state == promise_state::fulfilled) {
assert(
$state.exchange(promise_state::destroying) ==
promise_state::harvested);
r = std::move($val);
destroy();
on_destroy();
} else {
r = err_promise_not_yet_fulfilled;
}
return r;
}

/////////////////// destroy side ///////////////////
//////////////////// unused ////////////////////

void unfulfill_and_harvest() noexcept {
unfulfill();
await_resume();
}

/*
1. If fulfilled and received, will destroy() automatically.
2. If unfulfilled and unreceived, need destroy() manually.
*/
virtual void destroy() noexcept {}
protected:
virtual void on_destroy() noexcept {}

private:
std::atomic<promise_state> $state;
Expand Down Expand Up @@ -182,7 +199,7 @@ class newable_promise : public promise<T, Extend> {

virtual ~newable_promise() = default;

void destroy() noexcept override {
void on_destroy() noexcept override {
delete this;
}
};
Expand Down
2 changes: 1 addition & 1 deletion include/rua/sync/then.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ inline future<R> then(Awaitable &&awaitable, Callback &&callback) {
return prm->extend().aw->await_resume();
});

prm->destroy();
prm->unfulfill_and_harvest();

return exp;
}
Expand Down

0 comments on commit 50bb122

Please sign in to comment.