use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use memmap2::MmapMut;
pub(crate) struct SharedChangeDetector {
mmap: Arc<MmapMut>,
last_read: AtomicU64,
}
impl Clone for SharedChangeDetector {
fn clone(&self) -> Self {
Self {
mmap: self.mmap.clone(),
last_read: AtomicU64::new(self.last_read.load(Ordering::Acquire)),
}
}
}
impl SharedChangeDetector {
pub fn new(mmap: MmapMut) -> Self {
assert!(mmap.len() >= std::mem::size_of::<AtomicU64>());
let last_read = AtomicU64::new(mmap_as_atomic_u64(&mmap).load(Ordering::Acquire));
Self {
mmap: Arc::new(mmap),
last_read,
}
}
pub fn set(&self, value: u64) {
mmap_as_atomic_u64(&self.mmap).store(value, Ordering::Release);
self.last_read.store(value, Ordering::Release);
}
pub fn is_changed(&self) -> bool {
let current = mmap_as_atomic_u64(&self.mmap).load(Ordering::Acquire);
let last = self.last_read.load(Ordering::Acquire);
last != current
}
}
fn mmap_as_atomic_u64(mmap: &MmapMut) -> &AtomicU64 {
let ptr = mmap.as_ptr() as *mut u8 as *mut u64;
unsafe { AtomicU64::from_ptr(ptr) }
}
impl Drop for SharedChangeDetector {
fn drop(&mut self) {
if let Some(mmap) = Arc::get_mut(&mut self.mmap) {
let _ = mmap.flush_async();
}
}
}