29class LazySharedPtr final {
32 LazySharedPtr()
noexcept : value_(
nullptr), shared_filled_(
true), get_data_() {}
36 : value_(ptr.Get()), shared_filled_(
true), shared_(std::move(ptr)) {}
39 LazySharedPtr(std::function<
utils::SharedReadablePtr<T>()> function)
noexcept : get_data_(std::move(function)) {}
46 : get_data_(other.get_data_)
48 if (other.shared_filled_.load()) {
49 value_.store(other.shared_.Get());
50 shared_ = other.shared_;
51 shared_filled_.store(
true);
57 : value_(other.value_.load()),
58 shared_filled_(other.shared_filled_.load()),
59 shared_(std::move(other.shared_)),
60 get_data_(std::move(other.get_data_)) {}
65 LazySharedPtr&
operator=(
const LazySharedPtr& other) {
66 *
this = LazySharedPtr(other);
71 LazySharedPtr&
operator=(LazySharedPtr&& other)
noexcept {
72 value_.store(other.value_.load(), std::memory_order_relaxed);
73 shared_filled_.store(other.shared_filled_.load(), std::memory_order_relaxed);
74 shared_ = std::move(other.shared_);
75 get_data_ = std::move(other.get_data_);
80 const T*
Get()
const& USERVER_IMPL_LIFETIME_BOUND {
81 if (
const auto* current_value = value_.load(); current_value != kUnfilled) {
84 auto readable = get_data_();
85 if (
const auto* expected = kUnfilled; value_.compare_exchange_strong(expected, readable.Get())) {
86 shared_ = std::move(readable);
87 shared_filled_.store(
true);
94 const utils::SharedReadablePtr<T>&
GetShared()
const& USERVER_IMPL_LIFETIME_BOUND {
95 if (value_ == kUnfilled) {
96 auto readable = get_data_();
97 if (
const auto* expected = kUnfilled; value_.compare_exchange_strong(expected, readable.Get())) {
98 shared_ = std::move(readable);
99 shared_filled_.store(
true);
102 while (!shared_filled_.load()) {
113 const T&
operator*()
const& USERVER_IMPL_LIFETIME_BOUND {
114 const auto* res =
Get();
121 const T*
operator->()
const& USERVER_IMPL_LIFETIME_BOUND {
return &**
this; }
124 explicit operator bool()
const& USERVER_IMPL_LIFETIME_BOUND {
return !!
Get(); }
133 static inline const auto kUnfilled =
reinterpret_cast<
const T*>(std::uintptr_t{1});
135 mutable std::atomic<
const T*> value_{kUnfilled};
136 mutable std::atomic<
bool> shared_filled_{
false};
137 mutable utils::SharedReadablePtr<T> shared_{
nullptr};
138 std::function<
utils::SharedReadablePtr<T>()> get_data_{};