88 lines
2.3 KiB
Rust
88 lines
2.3 KiB
Rust
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||
|
|
||
|
/// TickTracker is used for tracking changes of [`Component`]s and entities.
|
||
|
///
|
||
|
/// TickTracker stores an [`AtomicU64`], making all operations on `TickTracker`, atomic as well.
|
||
|
/// Note that [`Tick::Clone`] only clones the inner value of atomic, and not the atomic itself.
|
||
|
#[derive(Debug, Default)]
|
||
|
pub struct TickTracker {
|
||
|
tick: AtomicU64,
|
||
|
}
|
||
|
|
||
|
impl Clone for TickTracker {
|
||
|
fn clone(&self) -> Self {
|
||
|
Self {
|
||
|
tick: AtomicU64::from(self.tick.load(Ordering::Acquire)),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl From<u64> for TickTracker {
|
||
|
fn from(value: u64) -> Self {
|
||
|
Self {
|
||
|
tick: AtomicU64::from(value),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl TickTracker {
|
||
|
/// Create a new tracker starting at zero ticks.
|
||
|
pub fn new() -> Self {
|
||
|
Self::default()
|
||
|
}
|
||
|
|
||
|
/// Increment the tick counter, and return the new Tick.
|
||
|
pub fn tick(&self) -> Tick {
|
||
|
let old = self.tick.fetch_add(1, Ordering::Relaxed);
|
||
|
Tick(old + 1)
|
||
|
}
|
||
|
|
||
|
/// If `when` is true, increment the tick counter.
|
||
|
pub fn tick_when(&self, when: bool) -> Tick {
|
||
|
if when {
|
||
|
self.tick()
|
||
|
} else {
|
||
|
self.current()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Sync this TickTracker with the provided `Tick`.
|
||
|
///
|
||
|
/// This will only update the tracker if `Tick` is larger than self.
|
||
|
pub fn tick_to(&self, other: &Tick) -> Tick {
|
||
|
self.tick.fetch_max(other.0, Ordering::AcqRel);
|
||
|
Tick(self.tick.load(Ordering::Acquire))
|
||
|
}
|
||
|
|
||
|
/// Sync this TickTracker with the other tracker.
|
||
|
///
|
||
|
/// This will only update the tracker if other is larger than self.
|
||
|
pub fn sync_tracker(&self, other: &TickTracker) -> Tick {
|
||
|
let other = other.tick.load(Ordering::Acquire);
|
||
|
self.tick_to(&Tick(other))
|
||
|
}
|
||
|
|
||
|
/// Gets the current Tick that the tracker is at.
|
||
|
pub fn current(&self) -> Tick {
|
||
|
Tick(self.tick.load(Ordering::Acquire))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// A specific Tick that was resulted from ticking a [`TickTracker`].
|
||
|
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Default, PartialOrd, Ord)]
|
||
|
pub struct Tick(u64);
|
||
|
|
||
|
impl std::ops::Deref for Tick {
|
||
|
type Target = u64;
|
||
|
|
||
|
fn deref(&self) -> &Self::Target {
|
||
|
&self.0
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Tick {
|
||
|
/// Increment this Tick up to `other`
|
||
|
pub fn tick_to(&mut self, other: &Tick) {
|
||
|
self.0 = self.0.max(other.0);
|
||
|
}
|
||
|
}
|