13#if !defined(ULTRA_CACHE_H)
14# error "Don't include this file directly, include the specific .h instead"
17#if !defined(ULTRA_CACHE_TCC)
18#define ULTRA_CACHE_TCC
30[[nodiscard]]
inline std::size_t
div_ceil(std::size_t x, std::size_t y)
34 return x/y + (x%y != 0);
41template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
42std::size_t cache<F, LOCK_GROUP_SIZE>::table_size(bitwidth n)
44 Expects(n <= max_cache_bitwidth);
56template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
57cache<F, LOCK_GROUP_SIZE>::cache(bitwidth n)
58 : table_(table_size(n)),
60 k_mask(table_.size() - 1)
74template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
75void cache<F, LOCK_GROUP_SIZE>::resize(bitwidth n)
77 const std::size_t nelem(table_size(n));
79 table_ =
decltype(table_)(nelem);
90template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
91std::size_t cache<F, LOCK_GROUP_SIZE>::index(
const hash_t &h)
const noexcept
94 return h.data[0] & k_mask;
102template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
104cache<F, LOCK_GROUP_SIZE>::lock_index(std::size_t idx)
const noexcept
106 return idx / LOCK_GROUP_SIZE;
118template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
119void cache<F, LOCK_GROUP_SIZE>::clear() noexcept
123 for (
auto &slot : table_)
137template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
138void cache<F, LOCK_GROUP_SIZE>::clear(
const hash_t &h)
140 const auto idx(index(h));
141 auto &mutex(locks_[lock_index(idx)]);
143 std::lock_guard lock(mutex);
146 table_[idx].seal = 0;
156template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
157std::optional<F> cache<F, LOCK_GROUP_SIZE>::find(
const hash_t &h)
const
159 const auto idx(index(h));
160 auto &mutex(locks_[lock_index(idx)]);
163 std::shared_lock lock(mutex);
165 if (
const slot &s(table_[idx]); s.seal == seal_ && s.hash == h)
179template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
180void cache<F, LOCK_GROUP_SIZE>::insert(
const hash_t &h,
const F &fitness)
182 const auto idx(index(h));
183 auto &mutex(locks_[lock_index(idx)]);
185 std::lock_guard lock(mutex);
187 table_[idx] = {h, fitness, seal_};
202template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
203bool cache<F, LOCK_GROUP_SIZE>::load(std::istream &in)
216 if (!s.hash.load(in))
218 if (!ultra::load(in, &s.fitness))
221 table_[index(s.hash)] = s;
236template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
237bool cache<F, LOCK_GROUP_SIZE>::save(std::ostream &
out)
const
239 std::size_t num(std::ranges::count_if(
240 table_, [
this](
const auto &s) {
return s.seal == seal_;}));
244 for (
const auto &s : table_)
247 if (!s.hash.save(
out))
262template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
263bitwidth cache<F, LOCK_GROUP_SIZE>::bits()
const
265 return std::bit_width(k_mask);
274template<Fitness F, std::
size_t LOCK_GROUP_SIZE>
275bool cache<F, LOCK_GROUP_SIZE>::is_valid()
const
283 return std::has_single_bit(table_.size()) && table_.size() - 1 == k_mask;
std::size_t div_ceil(std::size_t x, std::size_t y)
Definition cache.h:31
std::size_t div_ceil(std::size_t x, std::size_t y)
Definition cache.tcc:30
bool save(std::ostream &out, F f)
Definition fitness.h:151
unsigned bitwidth
Type alias for the number of bits.
Definition cache.h:30