use std::cell::RefCell;
thread_local! {
static SCRATCH: RefCell<Vec<u64>> = const { RefCell::new(Vec::new()) };
}
#[inline(always)]
pub(crate) fn words_for(n_patterns: usize) -> usize {
n_patterns.div_ceil(64)
}
#[inline]
pub(crate) fn new_trigger_bitmap(n_patterns: usize) -> Vec<u64> {
vec![0u64; words_for(n_patterns)]
}
#[inline]
pub(crate) fn with_scratch<R>(n_patterns: usize, f: impl FnOnce(&mut [u64]) -> R) -> R {
SCRATCH.with(|cell| {
let mut words = cell.borrow_mut();
let words_needed = words_for(n_patterns);
if words.len() < words_needed {
words.resize(words_needed, 0);
}
let result = {
let scratch = &mut words[..words_needed];
scratch.fill(0);
f(scratch)
};
if words.capacity().saturating_mul(std::mem::size_of::<u64>())
> super::MAX_RETAINED_WORKER_SCRATCH_BYTES
{
*words = Vec::new();
}
result
})
}
#[inline(always)]
pub(crate) fn for_each_set_bit(words: &[u64], mut f: impl FnMut(usize)) {
for (word_idx, &word) in words.iter().enumerate() {
let mut bits = word;
while bits != 0 {
f(word_idx * 64 + bits.trailing_zeros() as usize);
bits &= bits - 1; }
}
}