Flag an arena whose reservation was refused

This commit is contained in:
Dennis Kobert
2026-08-29 22:07:27 +00:00
parent 641fcc88c6
commit 8fd2529e27
+16 -2
View File
@@ -2,7 +2,7 @@ use std::cell::UnsafeCell;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
/// Handle word layout: 24 generation bits above 40 offset bits, so a 1 TiB arena is /// Handle word layout: 24 generation bits above 40 offset bits, so a 1 TiB arena is
/// addressable and generations run out after ~3 days of 60fps resets. /// addressable and generations run out after ~3 days of 60fps resets.
@@ -18,6 +18,9 @@ pub struct Arena {
offset: AtomicUsize, offset: AtomicUsize,
buf: Box<[UnsafeCell<MaybeUninit<u8>>]>, buf: Box<[UnsafeCell<MaybeUninit<u8>>]>,
drops: Mutex<Vec<DropEntry>>, drops: Mutex<Vec<DropEntry>>,
/// Set by a refused reservation and cleared by [`Arena::reset`], so a region
/// no evaluation resets can be seen to need one.
exhausted: AtomicBool,
} }
impl std::fmt::Debug for Arena { impl std::fmt::Debug for Arena {
@@ -81,6 +84,7 @@ impl Arena {
offset: AtomicUsize::new(0), offset: AtomicUsize::new(0),
buf, buf,
drops: Mutex::new(Vec::new()), drops: Mutex::new(Vec::new()),
exhausted: AtomicBool::new(false),
}) })
} }
@@ -93,9 +97,15 @@ impl Arena {
offset: AtomicUsize::new(0), offset: AtomicUsize::new(0),
buf: Box::new([]), buf: Box::new([]),
drops: Mutex::new(Vec::new()), drops: Mutex::new(Vec::new()),
exhausted: AtomicBool::new(false),
} }
} }
/// Whether a reservation has been refused since the last [`Arena::reset`].
pub fn exhausted(&self) -> bool {
self.exhausted.load(Ordering::Relaxed)
}
pub fn generation(&self) -> u64 { pub fn generation(&self) -> u64 {
self.generation.load(Ordering::Acquire) self.generation.load(Ordering::Acquire)
} }
@@ -132,7 +142,10 @@ impl Arena {
} }
} }
} }
reserved?; if reserved.is_none() {
self.exhausted.store(true, Ordering::Relaxed);
return None;
}
Some(start) Some(start)
} }
@@ -196,6 +209,7 @@ impl Arena {
unsafe { (entry.drop_fn)(base.add(entry.offset)) } unsafe { (entry.drop_fn)(base.add(entry.offset)) }
} }
*self.offset.get_mut() = 0; *self.offset.get_mut() = 0;
*self.exhausted.get_mut() = false;
let Some(generation) = next_generation() else { return false }; let Some(generation) = next_generation() else { return false };
self.generation.store(generation, Ordering::Release); self.generation.store(generation, Ordering::Release);
true true