Sparkle 0.0.1
Loading...
Searching...
No Matches
spk_cached_data.hpp
1#pragma once
2
3#include <functional>
4#include <mutex>
5#include <optional>
6#include <stdexcept>
7#include <utility>
8
9#include "utils/spk_debug_macro.hpp"
10
11namespace spk
12{
24 template <typename TType>
26 {
27 static_assert(!std::is_void_v<TType>, "TType must not be void");
28
29 public:
31 using value_type = TType;
33 using Generator = std::function<TType()>;
35 using Destructor = std::function<void(TType &)>;
36
37 private:
38 Generator _generator;
39 Destructor _destructor;
40 mutable std::optional<TType> _data;
41 mutable std::mutex _mutex;
42
43 void _destroyDataLocked() const
44 {
45 if (_data.has_value() == false)
46 {
47 return;
48 }
49
50 if (_destructor != nullptr)
51 {
52 _destructor(*_data);
53 }
54 _data.reset();
55 }
56
57 void _generateData() const
58 {
59 if (_data.has_value() == true)
60 {
61 return;
62 }
63
64 std::scoped_lock lock(_mutex);
65 if (_data.has_value() == false)
66 {
67 if (_generator == nullptr)
68 {
69 throw std::logic_error("CachedData: generator not set");
70 }
71 _data = _generator();
72 }
73 }
74
75 void _destroyData() const
76 {
77 std::scoped_lock lock(_mutex);
78 if (_data.has_value() == false)
79 {
80 return;
81 }
82
83 _destroyDataLocked();
84 }
85
86 public:
92 explicit CachedData(Generator p_generator, Destructor p_destructor = nullptr) :
93 _generator(std::move(p_generator)),
94 _destructor(std::move(p_destructor))
95 {
96 }
97
102 {
103 _destroyData();
104 }
105
106 CachedData(const CachedData &) = delete;
107 CachedData &operator=(const CachedData &) = delete;
108
109 CachedData(CachedData &&p_other) = delete;
110 CachedData &operator=(CachedData &&p_other) = delete;
111
116 TType &get()
117 {
118 _generateData();
119 return _data.value();
120 }
121
126 const TType &get() const
127 {
128 _generateData();
129 return _data.value();
130 }
131
136 TType &operator*()
137 {
138 return get();
139 }
140
144 const TType &operator*() const
145 {
146 return get();
147 }
148
153 TType *operator->()
154 {
155 _generateData();
156 return &(_data.value());
157 }
158
163 const TType *operator->() const
164 {
165 _generateData();
166 return &(_data.value());
167 }
168
173 operator TType &()
174 {
175 return get();
176 }
177
182 operator const TType &() const
183 {
184 return get();
185 }
186
190 void release() const
191 {
192 _destroyData();
193 }
194
200 void configure(Generator p_generator, Destructor p_destructor = nullptr)
201 {
202 std::scoped_lock lock(_mutex);
203 _destroyDataLocked();
204 _generator = std::move(p_generator);
205 _destructor = std::move(p_destructor);
206 }
207
212 void set(const TType &p_value)
213 {
214 std::scoped_lock lock(_mutex);
215 _destroyDataLocked();
216 _data = p_value;
217 }
218
223 void set(TType &&p_value)
224 {
225 std::scoped_lock lock(_mutex);
226 _destroyDataLocked();
227 _data = std::move(p_value);
228 }
229
234 std::optional<TType> take()
235 {
236 std::scoped_lock lock(_mutex);
237 std::optional<TType> extracted;
238 if (_data.has_value())
239 {
240 extracted.emplace(std::move(*_data));
241 _data.reset();
242 }
243 return extracted;
244 }
245
250 bool isCached() const
251 {
252 return _data.has_value();
253 }
254
259 TType &refresh()
260 {
261 release();
262 return get();
263 }
264 };
265}
Lazily generates and caches a value with optional custom destructor.
Definition spk_cached_data.hpp:26
std::function< TType()> Generator
Callable used to lazily produce the cached value.
Definition spk_cached_data.hpp:33
~CachedData()
Destroys any cached value using the destructor callback if set.
Definition spk_cached_data.hpp:101
const TType & get() const
Retrieves the cached value, generating it on first access.
Definition spk_cached_data.hpp:126
const TType * operator->() const
Member access to the cached value, generating if needed.
Definition spk_cached_data.hpp:163
void release() const
Releases the cached value by invoking destructor if provided.
Definition spk_cached_data.hpp:190
void set(TType &&p_value)
Stores a value directly, bypassing the generator (move overload).
Definition spk_cached_data.hpp:223
std::function< void(TType &)> Destructor
Optional cleanup function invoked when the cache is cleared.
Definition spk_cached_data.hpp:35
TType & operator*()
Dereferences to the cached value, generating if needed.
Definition spk_cached_data.hpp:136
void set(const TType &p_value)
Stores a value directly, bypassing the generator.
Definition spk_cached_data.hpp:212
bool isCached() const
Checks if a value is currently cached.
Definition spk_cached_data.hpp:250
TType & get()
Retrieves the cached value, generating it on first access.
Definition spk_cached_data.hpp:116
TType & refresh()
Drops the cached value and regenerates it.
Definition spk_cached_data.hpp:259
const TType & operator*() const
Dereferences to the cached value, generating if needed.
Definition spk_cached_data.hpp:144
TType * operator->()
Member access to the cached value, generating if needed.
Definition spk_cached_data.hpp:153
void configure(Generator p_generator, Destructor p_destructor=nullptr)
Replaces the generator/destructor pair and clears any cached value.
Definition spk_cached_data.hpp:200
TType value_type
Stored value type.
Definition spk_cached_data.hpp:31
std::optional< TType > take()
Moves the cached value out of the cache without invoking the destructor.
Definition spk_cached_data.hpp:234
CachedData(Generator p_generator, Destructor p_destructor=nullptr)
Builds a cache with a generator and optional destructor.
Definition spk_cached_data.hpp:92
STL namespace.