10#include <userver/engine/condition_variable.hpp>
11#include <userver/engine/exception.hpp>
12#include <userver/engine/task/cancel.hpp>
13#include <userver/utils/assert.hpp>
14#include <userver/utils/result_store.hpp>
16USERVER_NAMESPACE_BEGIN
22class LazyValue final {
24 explicit LazyValue(std::function<T()> f) : f_(std::move(f)) {
UASSERT(f_); }
33 std::function<T()> f_;
34 std::atomic<
bool> started_{
false};
35 utils::ResultStore<T> result_;
37 engine::ConditionVariable cv_finished_;
38 engine::Mutex m_finished_;
39 std::atomic<
bool> finished_{
false};
44 if (finished_)
return result_.Get();
46 auto old = started_.exchange(
true);
49 result_.SetValue(f_());
51 std::lock_guard lock(m_finished_);
53 cv_finished_.NotifyAll();
55 result_.SetException(std::current_exception());
57 std::lock_guard lock(m_finished_);
59 cv_finished_.NotifyAll();
63 std::unique_lock lock(m_finished_);
64 auto rc = cv_finished_.Wait(lock, [
this]() {
return finished_.load(); });