use std::sync::atomic::{AtomicBool, Ordering};
use crate::query::WorldQuery;
pub struct WorldAccess<'a> {
world: std::ptr::NonNull<crate::World>,
_guard: WorldLockGuard<'a>,
}
pub(crate) struct WorldLock {
locked: AtomicBool,
}
pub(crate) struct WorldLockGuard<'a> {
lock: &'a WorldLock,
}
impl<'a> Drop for WorldLockGuard<'a> {
fn drop(&mut self) {
self.lock.unlock();
}
}
impl WorldLock {
pub fn new() -> Self {
Self {
locked: AtomicBool::new(false),
}
}
pub fn lock(&self) -> WorldLockGuard<'_> {
self.locked
.compare_exchange(false, true, Ordering::AcqRel, Ordering::Relaxed)
.expect("Can not be locked twice");
WorldLockGuard { lock: self }
}
pub fn unlock(&self) {
self.locked.store(false, Ordering::Release);
}
}
impl WorldAccess<'_> {
pub fn world(&self) -> &crate::World {
unsafe { self.world.as_ref() }
}
pub fn world_mut(&mut self) -> &mut crate::World {
unsafe { self.world.as_mut() }
}
}
unsafe impl Send for WorldAccess<'_> {}
unsafe impl Sync for WorldAccess<'_> {}
unsafe impl<'a> WorldQuery<'a> for WorldAccess<'a> {
fn new(db: &'a crate::World, _system_idx: usize) -> Self {
let _guard = db.this_lock.lock();
WorldAccess {
world: db.into(),
_guard,
}
}
fn exclusive() -> bool {
true
}
fn read_only() -> bool {
false
}
}