steel_core/world/tick_scheduler/
run_batch.rs1use super::{
2 AtomicOrdering, AtomicUsize, BlockPos, FxHashMap, OnceLock, ScheduledTick, ScheduledTickKey,
3 TickKey,
4};
5
6#[derive(Debug)]
11pub(crate) struct ScheduledTickRunBatch<T: TickKey> {
12 ticks: Vec<ScheduledTick<T>>,
13 next_index: AtomicUsize,
14 lookup: OnceLock<FxHashMap<ScheduledTickKey, usize>>,
15}
16
17impl<T: TickKey> ScheduledTickRunBatch<T> {
18 #[must_use]
19 pub(crate) const fn new(ticks: Vec<ScheduledTick<T>>) -> Self {
20 Self {
21 ticks,
22 next_index: AtomicUsize::new(0),
23 lookup: OnceLock::new(),
24 }
25 }
26
27 #[must_use]
28 pub(crate) fn ticks(&self) -> &[ScheduledTick<T>] {
29 &self.ticks
30 }
31
32 pub(crate) fn start(&self, index: usize) {
33 assert!(
34 index < self.ticks.len(),
35 "scheduled-tick batch index out of bounds"
36 );
37 self.next_index.store(index + 1, AtomicOrdering::Relaxed);
38 }
39
40 #[must_use]
41 pub(crate) fn contains(&self, pos: BlockPos, tick_type: T) -> bool {
42 let initial_index = self.next_index.load(AtomicOrdering::Relaxed);
43 if initial_index >= self.ticks.len() {
44 return false;
45 }
46 let lookup = self.lookup.get_or_init(|| {
47 self.ticks[initial_index..]
48 .iter()
49 .enumerate()
50 .map(|(index, tick)| (tick.key(), initial_index + index))
51 .collect()
52 });
53 let next_index = self.next_index.load(AtomicOrdering::Relaxed);
54 lookup
55 .get(&(pos, tick_type.key()))
56 .is_some_and(|&index| index >= next_index)
57 }
58
59 #[cfg(test)]
60 pub(super) fn lookup_is_initialized(&self) -> bool {
61 self.lookup.get().is_some()
62 }
63}