mindustry logic execution, map- and schematic- parsing and rendering
remove once cell
bendn 2023-06-23
parent 58da0a1 · commit da3a3f6
-rw-r--r--src/block/mod.rs14
-rw-r--r--src/data/schematic.rs2
-rw-r--r--src/lib.rs1
-rw-r--r--src/utils/mod.rs2
-rw-r--r--src/utils/once_cell.rs169
5 files changed, 4 insertions, 184 deletions
diff --git a/src/block/mod.rs b/src/block/mod.rs
index aa8d2bb..74e8c2c 100644
--- a/src/block/mod.rs
+++ b/src/block/mod.rs
@@ -8,7 +8,6 @@ use crate::data::dynamic::{DynData, DynType};
use crate::data::GridPos;
use crate::item::storage::Storage as ItemStorage;
use crate::registry::RegistryEntry;
-use crate::utils::OnceCell;
pub mod base;
pub mod content;
@@ -167,7 +166,6 @@ impl Error for SerializeError {
pub struct Block {
name: Cow<'static, str>,
logic: BoxAccess<'static, dyn BlockLogic + Sync>,
- build_cost: OnceCell<Option<ItemStorage>>,
}
impl Block {
@@ -176,11 +174,7 @@ impl Block {
name: Cow<'static, str>,
logic: BoxAccess<'static, dyn BlockLogic + Sync>,
) -> Self {
- Self {
- name,
- logic,
- build_cost: OnceCell::new(),
- }
+ Self { name, logic }
}
pub fn get_size(&self) -> u8 {
@@ -191,10 +185,8 @@ impl Block {
self.logic.is_symmetric()
}
- pub fn get_build_cost(&self) -> Option<&ItemStorage> {
- self.build_cost
- .get_or_init(|| self.logic.as_ref().create_build_cost())
- .as_ref()
+ pub fn get_build_cost(&self) -> Option<ItemStorage> {
+ self.logic.as_ref().create_build_cost()
}
pub fn data_from_i32(&self, config: i32, pos: GridPos) -> Result<DynData, DataConvertError> {
diff --git a/src/data/schematic.rs b/src/data/schematic.rs
index a3b104d..9927ad2 100644
--- a/src/data/schematic.rs
+++ b/src/data/schematic.rs
@@ -591,7 +591,7 @@ impl<'l> Schematic<'l> {
let mut sandbox = false;
for &Placement { block, .. } in &self.blocks {
if let Some(curr) = block.get_build_cost() {
- cost.add_all(curr, u32::MAX);
+ cost.add_all(&curr, u32::MAX);
} else {
sandbox = true;
}
diff --git a/src/lib.rs b/src/lib.rs
index c5db7d4..300937d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,4 +9,3 @@ pub mod modifier;
pub mod registry;
pub mod team;
pub mod unit;
-pub mod utils;
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
deleted file mode 100644
index 396b1e2..0000000
--- a/src/utils/mod.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-pub mod once_cell;
-pub use once_cell::OnceCell;
diff --git a/src/utils/once_cell.rs b/src/utils/once_cell.rs
deleted file mode 100644
index 9dda9ff..0000000
--- a/src/utils/once_cell.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-use std::cell::UnsafeCell;
-use std::mem::MaybeUninit;
-use std::ptr;
-use std::sync::atomic::{AtomicU8, Ordering};
-
-const STATE_INIT: u8 = 0;
-const STATE_LOCKED: u8 = STATE_INIT + 1;
-const STATE_READY: u8 = STATE_LOCKED + 1;
-
-pub struct OnceCell<T> {
- value: UnsafeCell<MaybeUninit<T>>,
- state: AtomicU8,
-}
-
-impl<T> OnceCell<T> {
- #[must_use]
- pub const fn new() -> Self {
- Self {
- value: UnsafeCell::new(MaybeUninit::uninit()),
- state: AtomicU8::new(STATE_INIT),
- }
- }
-
- pub const fn new_init(value: T) -> Self {
- Self {
- value: UnsafeCell::new(MaybeUninit::new(value)),
- state: AtomicU8::new(STATE_READY),
- }
- }
-
- pub fn get(&self) -> Option<&T> {
- if self.state.load(Ordering::Acquire) == STATE_READY {
- // SAFETY: won't be overwritten for the lifetime of this reference
- Some(unsafe { (*self.value.get()).assume_init_ref() })
- } else {
- None
- }
- }
-
- pub fn get_or_wait(&self) -> Option<&T> {
- loop {
- match self.state.load(Ordering::Acquire) {
- STATE_INIT => return None,
- STATE_LOCKED => (), // continue
- STATE_READY => return Some(unsafe { (*self.value.get()).assume_init_ref() }),
- x => unreachable!("invalid state {x}"),
- }
- }
- }
-
- pub fn get_or_init<F: Fn() -> T>(&self, init: F) -> &T {
- loop {
- match self.state.compare_exchange(
- STATE_INIT,
- STATE_LOCKED,
- Ordering::AcqRel,
- Ordering::Acquire,
- ) {
- Ok(..) => {
- let value = init();
- let written = &*unsafe { &mut *self.value.get() }.write(value);
- self.state.store(STATE_READY, Ordering::Release);
- return written;
- }
- Err(STATE_READY) => return unsafe { (*self.value.get()).assume_init_ref() },
- Err(..) => (), // locked or spurious failure
- }
- }
- }
-
- pub fn set(&self, value: T) -> Result<&T, T> {
- // don't set state to STATE_READY on success because we have to release afterward anyway
- match self.state.compare_exchange(
- STATE_INIT,
- STATE_LOCKED,
- Ordering::AcqRel,
- Ordering::Acquire,
- ) {
- Ok(..) => {
- // SAFETY: unique because only one thread can lock the atomic state
- let written = &*unsafe { &mut *self.value.get() }.write(value);
- self.state.store(STATE_READY, Ordering::Release);
- Ok(written)
- }
- // SAFETY: guaranteed to be initialized & protected by acquire ordering
- Err(STATE_READY) => return Ok(unsafe { (*self.value.get()).assume_init_ref() }),
- Err(..) => Err(value), // locked or spurious failure
- }
- }
-
- pub fn set_mut(&mut self, mut value: T) -> Result<Option<T>, T> {
- // don't set state to STATE_READY on success because we have to release afterward anyway
- match self.state.compare_exchange(
- STATE_INIT,
- STATE_LOCKED,
- Ordering::AcqRel,
- Ordering::Acquire,
- ) {
- Ok(..) => {
- self.value.get_mut().write(value);
- self.state.store(STATE_READY, Ordering::Release);
- Ok(None)
- }
- Err(STATE_READY) => {
- // SAFETY: guaranteed to be initialized & protected by acquire ordering
- std::mem::swap(
- unsafe { self.value.get_mut().assume_init_mut() },
- &mut value,
- );
- // ensure changes are visible to others acquiring the atomic state
- self.state.store(STATE_READY, Ordering::Release);
- // we've swapped the previous value into this variable
- Ok(Some(value))
- }
- Err(..) => Err(value), // locked or spurious failure
- }
- }
-
- pub fn into_inner(mut self) -> Option<T> {
- // must be atomic so potential writes during the drop see a valid state
- let inner = match self.state.load(Ordering::Acquire) {
- STATE_INIT => None,
- STATE_LOCKED => unreachable!("consumed cell during initialization"),
- // SAFETY: initialized & we'll forget about it afterwards
- STATE_READY => Some(unsafe { self.value.get_mut().assume_init_read() }),
- x => unreachable!("invalid state {x}"),
- };
- // SAFETY: just in case AtomicU8 has a drop handler
- unsafe {
- ptr::drop_in_place(std::ptr::addr_of_mut!(self.state));
- }
- std::mem::forget(self);
- inner
- }
-}
-
-impl<T> Default for OnceCell<T> {
- fn default() -> Self {
- OnceCell::new()
- }
-}
-
-impl<T> From<T> for OnceCell<T> {
- fn from(value: T) -> Self {
- OnceCell::new_init(value)
- }
-}
-
-impl<T> From<OnceCell<T>> for Option<T> {
- fn from(value: OnceCell<T>) -> Self {
- value.into_inner()
- }
-}
-
-impl<T> Drop for OnceCell<T> {
- fn drop(&mut self) {
- match *self.state.get_mut() {
- STATE_INIT => (),
- STATE_LOCKED => unreachable!("dropped cell during initialization"),
- // MaybeUninit requires us to manually drop the value
- STATE_READY => unsafe { self.value.get_mut().assume_init_drop() },
- x => unreachable!("invalid state {x}"),
- }
- }
-}
-
-unsafe impl<T: Send> Send for OnceCell<T> {}
-
-unsafe impl<T: Sync> Sync for OnceCell<T> {}