Files
nf7/iface/common/mutex.hh
2023-09-03 13:06:18 +09:00

66 lines
1.5 KiB
C++

// No copyright
#pragma once
#include <memory>
#include <utility>
#include "iface/common/future.hh"
#include "iface/common/task_context.hh"
namespace nf7 {
class Mutex final {
private:
class Impl;
public:
class Token;
using SharedToken = std::shared_ptr<Token>;
public:
Mutex();
~Mutex() noexcept;
Mutex(const Mutex&) = default;
Mutex(Mutex&&) = default;
Mutex& operator=(const Mutex&) = default;
Mutex& operator=(Mutex&&) = default;
public:
Future<SharedToken> Lock() noexcept;
SharedToken TryLock();
Future<SharedToken> LockEx() noexcept;
SharedToken TryLockEx();
public:
template <typename F,
typename R = std::invoke_result_t<F, const SharedToken&>>
Future<R> RunAsync(const std::shared_ptr<AsyncTaskQueue>& aq,
const std::shared_ptr<SyncTaskQueue>& sq,
F&& f,
bool ex = false) noexcept {
typename Future<R>::Completer comp;
(ex? LockEx(): Lock())
.Then([aq, sq, f = std::move(f), comp](auto& k) mutable {
comp.Attach(k);
comp.RunAsync(aq, sq, [f = std::move(f), k](auto&) mutable {
return f(k);
});
})
.Catch([comp](auto& e) mutable {
comp.Throw(std::make_exception_ptr(e));
});
return comp.future();
}
auto RunAsyncEx(const auto& aq, const auto& sq, auto&& f) noexcept {
return RunAsync(aq, sq, std::move(f), true);
}
private:
std::shared_ptr<Impl> impl_;
};
} // namespace nf7