1
Fork 0

Use Freeze for SourceFile.external_src

This commit is contained in:
John Kåre Alsaker 2023-08-31 12:50:44 +02:00
parent f00c139998
commit c5996b80be
8 changed files with 91 additions and 46 deletions

View file

@ -27,7 +27,26 @@ unsafe impl<T: DynSync + DynSend> DynSync for FreezeLock<T> {}
impl<T> FreezeLock<T> {
#[inline]
pub fn new(value: T) -> Self {
Self { data: UnsafeCell::new(value), frozen: AtomicBool::new(false), lock: RwLock::new(()) }
Self::with(value, false)
}
#[inline]
pub fn frozen(value: T) -> Self {
Self::with(value, true)
}
#[inline]
pub fn with(value: T, frozen: bool) -> Self {
Self {
data: UnsafeCell::new(value),
frozen: AtomicBool::new(frozen),
lock: RwLock::new(()),
}
}
#[inline]
pub fn is_frozen(&self) -> bool {
self.frozen.load(Ordering::Acquire)
}
#[inline]
@ -42,13 +61,26 @@ impl<T> FreezeLock<T> {
}
}
#[inline]
pub fn borrow(&self) -> FreezeReadGuard<'_, T> {
self.read()
}
#[inline]
#[track_caller]
pub fn write(&self) -> FreezeWriteGuard<'_, T> {
self.try_write().expect("still mutable")
}
#[inline]
pub fn try_write(&self) -> Option<FreezeWriteGuard<'_, T>> {
let _lock_guard = self.lock.write();
// Use relaxed ordering since we're in the write lock.
assert!(!self.frozen.load(Ordering::Relaxed), "still mutable");
FreezeWriteGuard { _lock_guard, lock: self, marker: PhantomData }
if self.frozen.load(Ordering::Relaxed) {
None
} else {
Some(FreezeWriteGuard { _lock_guard, lock: self, marker: PhantomData })
}
}
#[inline]
@ -90,6 +122,15 @@ pub struct FreezeWriteGuard<'a, T> {
marker: PhantomData<&'a mut T>,
}
impl<'a, T> FreezeWriteGuard<'a, T> {
pub fn freeze(self) -> &'a T {
self.lock.frozen.store(true, Ordering::Release);
// SAFETY: This is frozen so the data cannot be modified and shared access is sound.
unsafe { &*self.lock.data.get() }
}
}
impl<'a, T: 'a> Deref for FreezeWriteGuard<'a, T> {
type Target = T;
#[inline]