fix data race

This commit is contained in:
falsycat 2022-09-26 00:59:20 +09:00
parent 2082a6e482
commit 007882ccfd
2 changed files with 14 additions and 6 deletions

View File

@ -96,11 +96,14 @@ class Future final {
auto Return(T&& v) noexcept {
std::unique_lock<std::mutex> k(data_->mtx);
if (data_->state == kYet) {
data_->state = kDone;
data_->value = std::move(v);
data_->state = kDone;
CallReceivers();
}
}
auto Return(const T& v) noexcept {
Return(T {v});
}
// thread-safe
void Throw(std::exception_ptr e) noexcept {
std::unique_lock<std::mutex> k(data_->mtx);
@ -110,6 +113,10 @@ class Future final {
CallReceivers();
}
}
template <typename E, typename... Args>
void Throw(Args&&... args) noexcept {
return Throw(std::make_exception_ptr<E>(E {std::forward<Args>(args)...}));
}
// thread-safe
// Do Return(f()) if no exception is thrown, otherwise call Throw().
@ -247,7 +254,7 @@ class Future final {
typename nf7::Future<R>::Promise pro;
Then(ctx, [pro, f = std::move(f)](auto& fu) mutable {
try {
fun(fu, pro);
f(fu, pro);
} catch (...) {
pro.Throw(std::current_exception());
}
@ -277,8 +284,9 @@ class Future final {
});
return *this;
}
template <typename E>
ThisFuture& Catch(auto&& f) noexcept {
return Catch(nullptr, std::move(f));
return Catch<E>(nullptr, std::move(f));
}
auto& value() {

View File

@ -138,16 +138,16 @@ class Thread final : public std::enable_shared_from_this<Thread> {
template <typename T>
Thread::Handler Thread::CreatePromiseHandler(
nf7::Future<T>::Promise& pro, std::function<T(lua_State*)>&& f) noexcept {
return [&pro, f = std::move(f)](auto& self, auto L) {
return [pro = pro, f = std::move(f)](auto& self, auto L) mutable {
switch (self.state()) {
case kPaused:
pro.Throw(std::make_exception_ptr<nf7::Exception>({"unexpected yield"}));
pro.template Throw<nf7::Exception>("unexpected yield");
break;
case kFinished:
pro.Wrap([&]() { return f(L); });
break;
case kAborted:
pro.Throw(std::make_exception_ptr<nf7::Exception>({lua_tostring(L, -1)}));
pro.template Throw<nf7::Exception>(lua_tostring(L, -1));
break;
default:
assert(false);