draconisplusplus/include/rfl/internal/Memoization.hpp

50 lines
947 B
C++
Raw Normal View History

2024-05-31 22:59:00 -04:00
#ifndef RFL_INTERNAL_MEMOIZATION_HPP_
#define RFL_INTERNAL_MEMOIZATION_HPP_
#include <atomic>
#include <mutex>
namespace rfl {
2024-06-08 14:10:59 -04:00
namespace internal {
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
/// For a thread-safe memoization pattern.
template <class T>
class Memoization {
public:
Memoization() { flag_.clear(); }
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
~Memoization() = default;
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
public:
/// Returns the underlying value.
template <class F>
const T& value(const F& _f) {
if (flag_.test()) { return value_; }
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
std::lock_guard<std::mutex> guard(mtx_);
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
if (flag_.test()) { return value_; }
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
_f(&value_);
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
flag_.test_and_set();
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
return value_;
}
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
private:
/// Signifies whether t_ has been set.
std::atomic_flag flag_;
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
/// A mutex, only needed for writing.
std::mutex mtx_;
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
/// The type to be initialized.
T value_;
};
2024-05-31 22:59:00 -04:00
2024-06-08 14:10:59 -04:00
} // namespace internal
} // namespace rfl
2024-05-31 22:59:00 -04:00
#endif