refactor: use MaybeUninit in RoCell

This commit is contained in:
sxyazi 2025-02-27 22:55:21 +08:00
parent 6b0a5306c2
commit 22b46b3fa0
No known key found for this signature in database
3 changed files with 39 additions and 20 deletions

12
Cargo.lock generated
View file

@ -1412,9 +1412,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "litemap"
version = "0.7.4"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
[[package]]
name = "lock_api"
@ -3684,18 +3684,18 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",

View file

@ -1,7 +1,7 @@
const LABEL_NAME = "needs info"
const RE_VERSION = /Yazi\s+Version\s*:\s\d+\.\d+\.\d+\s\(/gm
const RE_DEPENDENCIES = /Dependencies\s+[/a-z]+\s*:\s/gm
const RE_CHECKLIST = /#{3}\s+Checklist\s+(?:^-\s+\[x]\s+.+?\n){2}/gm
const RE_CHECKLIST = /#{3}\s+Checklist\s+(?:^-\s+\[x]\s+.+?(?:\n|\r\n|$)){2}/gm
function bugReportBody(creator, content, hash) {
if (content.includes(` (${hash} `) && RE_CHECKLIST.test(content)) {

View file

@ -1,24 +1,41 @@
use std::{cell::UnsafeCell, fmt::{self, Display}, mem, ops::Deref};
use std::{cell::UnsafeCell, fmt::{self, Display}, mem::MaybeUninit, ops::Deref};
// Read-only cell. It's safe to use this in a static variable, but it's not safe
// to mutate it. This is useful for storing static data that is expensive to
// initialize, but is immutable once.
pub struct RoCell<T>(UnsafeCell<Option<T>>);
pub struct RoCell<T> {
inner: UnsafeCell<MaybeUninit<T>>,
#[cfg(debug_assertions)]
initialized: UnsafeCell<bool>,
}
unsafe impl<T> Sync for RoCell<T> {}
impl<T> RoCell<T> {
#[inline]
pub const fn new() -> Self { Self(UnsafeCell::new(None)) }
pub const fn new() -> Self {
Self {
inner: UnsafeCell::new(MaybeUninit::uninit()),
#[cfg(debug_assertions)]
initialized: UnsafeCell::new(false),
}
}
#[inline]
pub const fn new_const(value: T) -> Self { Self(UnsafeCell::new(Some(value))) }
pub const fn new_const(value: T) -> Self {
Self {
inner: UnsafeCell::new(MaybeUninit::new(value)),
#[cfg(debug_assertions)]
initialized: UnsafeCell::new(true),
}
}
#[inline]
pub fn init(&self, value: T) {
debug_assert!(!self.initialized());
unsafe {
*self.0.get() = Some(value);
debug_assert!(!*self.initialized.get());
*self.inner.get() = MaybeUninit::new(value);
*self.initialized.get() = true;
}
}
@ -32,12 +49,12 @@ impl<T> RoCell<T> {
#[inline]
pub fn drop(&self) -> T {
debug_assert!(self.initialized());
unsafe { mem::take(&mut *self.0.get()).unwrap_unchecked() }
unsafe {
debug_assert!(*self.initialized.get());
*self.initialized.get() = false;
self.inner.get().replace(MaybeUninit::uninit()).assume_init()
}
}
#[inline]
fn initialized(&self) -> bool { unsafe { (*self.0.get()).is_some() } }
}
impl<T> Default for RoCell<T> {
@ -48,8 +65,10 @@ impl<T> Deref for RoCell<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
debug_assert!(self.initialized());
unsafe { (*self.0.get()).as_ref().unwrap_unchecked() }
unsafe {
debug_assert!(*self.initialized.get());
(*self.inner.get()).assume_init_ref()
}
}
}