Program Listing for File memoize.hpp¶
↰ Return to documentation for file (SeQuant/core/utility/memoize.hpp)
#ifndef SEQUANT_CORE_UTILITY_MEMOIZE_HPP
#define SEQUANT_CORE_UTILITY_MEMOIZE_HPP
#include <SeQuant/core/container.hpp>
#include <condition_variable>
#include <mutex>
#include <optional>
#include <utility>
namespace sequant::detail {
template <typename Key, typename Value, typename ComputeFn>
const Value& memoize(container::map<Key, std::optional<Value>>& cache,
std::mutex& mutex, std::condition_variable& cv,
const Key& key, ComputeFn&& compute_fn) {
{
std::unique_lock<std::mutex> lock(mutex);
using cache_t = container::map<Key, std::optional<Value>>;
typename cache_t::iterator it;
bool inserted;
// N.B. Use std::tie instead of structured binding to allow lambda capture
// (C++17 does not support capturing structured bindings in lambdas)
std::tie(it, inserted) = cache.try_emplace(key, std::nullopt);
if (!inserted) {
cv.wait(lock, [&it] { return it->second.has_value(); });
return it->second.value();
}
}
Value result = compute_fn();
{
std::lock_guard<std::mutex> lock(mutex);
cache[key] = std::move(result);
cv.notify_all();
return cache[key].value();
}
}
} // namespace sequant::detail
#endif // SEQUANT_CORE_UTILITY_MEMOIZE_HPP