1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
use crate::ops::Deref;
use crate::{fmt, mem};
use super::UnsafeCell;
enum State<T, F> {
Uninit(F),
Init(T),
Poisoned,
}
/// 在首次访问时初始化的值。
///
/// 有关此结构体的线程安全版本,请参见 [`std::sync::LazyLock`]。
///
/// [`std::sync::LazyLock`]: ../../std/sync/struct.LazyLock.html
///
/// # Examples
///
/// ```
/// #![feature(lazy_cell)]
///
/// use std::cell::LazyCell;
///
/// let lazy: LazyCell<i32> = LazyCell::new(|| {
/// println!("initializing");
/// 92
/// });
/// println!("ready");
/// println!("{}", *lazy);
/// println!("{}", *lazy);
///
/// // Prints:
/// // 准备初始化
/////
/// // 92
/// // 92
/// ```
#[unstable(feature = "lazy_cell", issue = "109736")]
pub struct LazyCell<T, F = fn() -> T> {
state: UnsafeCell<State<T, F>>,
}
impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// 使用给定的初始化函数创建一个新的惰性值。
///
/// # Examples
///
/// ```
/// #![feature(lazy_cell)]
///
/// use std::cell::LazyCell;
///
/// let hello = "Hello, World!".to_string();
///
/// let lazy = LazyCell::new(|| hello.to_uppercase());
///
/// assert_eq!(&*lazy, "HELLO, WORLD!");
/// ```
#[inline]
#[unstable(feature = "lazy_cell", issue = "109736")]
pub const fn new(f: F) -> LazyCell<T, F> {
LazyCell { state: UnsafeCell::new(State::Uninit(f)) }
}
/// 使用此 `LazyCell` 返回存储的值。
///
/// 如果 `Lazy` 已初始化,则返回 `Ok(value)`,否则返回 `Err(f)`。
///
/// # Examples
///
/// ```
/// #![feature(lazy_cell)]
/// #![feature(lazy_cell_consume)]
///
/// use std::cell::LazyCell;
///
/// let hello = "Hello, World!".to_string();
///
/// let lazy = LazyCell::new(|| hello.to_uppercase());
///
/// assert_eq!(&*lazy, "HELLO, WORLD!");
/// assert_eq!(LazyCell::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
/// ```
#[unstable(feature = "lazy_cell_consume", issue = "109736")]
pub fn into_inner(this: Self) -> Result<T, F> {
match this.state.into_inner() {
State::Init(data) => Ok(data),
State::Uninit(f) => Err(f),
State::Poisoned => panic!("LazyCell instance has previously been poisoned"),
}
}
/// 强制对此延迟值求值,并向结果返回引用。
///
///
/// 这等效于 `Deref` impl,但是是显式的。
///
/// # Examples
///
/// ```
/// #![feature(lazy_cell)]
///
/// use std::cell::LazyCell;
///
/// let lazy = LazyCell::new(|| 92);
///
/// assert_eq!(LazyCell::force(&lazy), &92);
/// assert_eq!(&*lazy, &92);
/// ```
#[inline]
#[unstable(feature = "lazy_cell", issue = "109736")]
pub fn force(this: &LazyCell<T, F>) -> &T {
// SAFETY:
// 这会使对数据的任何可变引用无效。
// 生成的引用要么一直存在到 `this` 的引用结束 (在初始化的情况下),要么在 `really_init` 中失效 (在未初始化的情况下; `really_init` 将创建并返回一个新的引用)。
//
//
let state = unsafe { &*this.state.get() };
match state {
State::Init(data) => data,
// SAFETY: 状态未初始化。
State::Uninit(_) => unsafe { LazyCell::really_init(this) },
State::Poisoned => panic!("LazyCell has previously been poisoned"),
}
}
/// # Safety
/// 只能在状态为 `Uninit` 时调用。
#[cold]
unsafe fn really_init(this: &LazyCell<T, F>) -> &T {
// SAFETY:
// 该函数只有在状态未初始化时才会被调用,所以对 `state` 的引用不能存在,除了 `force` 中的引用,在这里失效,不再访问。
//
//
let state = unsafe { &mut *this.state.get() };
// 暂时将状态标记为中毒。
// 这可以防止重入访问并在封包 panic 时正确地使 cell 中毒。
let State::Uninit(f) = mem::replace(state, State::Poisoned) else { unreachable!() };
let data = f();
// SAFETY:
// 如果关闭包通过重入互锁之类的方式访问了 cell,但是捕获了状态中毒导致的 panic,那么 `state` 的可变借用就会失效,所以我们需要在这里通过 `UnsafeCell` 指针。
// 状态只能在此时中毒,所以使用 `write` 跳过 `State` 的析构函数应该有助于优化器。
//
//
//
//
unsafe { this.state.get().write(State::Init(data)) };
// SAFETY:
// 之前的引用被上面的 `write` 调用失效了,所以做一个新的状态共享引用代替。
//
let state = unsafe { &*this.state.get() };
let State::Init(data) = state else { unreachable!() };
data
}
}
impl<T, F> LazyCell<T, F> {
#[inline]
fn get(&self) -> Option<&T> {
// SAFETY:
// 这与 `force` 中的原因相同: 一旦状态被初始化,它就不会再次被可变地访问,所以这个引用将在对 `self` 的引用期间保持有效。
//
//
let state = unsafe { &*self.state.get() };
match state {
State::Init(data) => Some(data),
_ => None,
}
}
}
#[unstable(feature = "lazy_cell", issue = "109736")]
impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
LazyCell::force(self)
}
}
#[unstable(feature = "lazy_cell", issue = "109736")]
impl<T: Default> Default for LazyCell<T> {
/// 使用 `Default` 作为初始化函数创建一个新的惰性值。
#[inline]
fn default() -> LazyCell<T> {
LazyCell::new(T::default)
}
}
#[unstable(feature = "lazy_cell", issue = "109736")]
impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_tuple("LazyCell");
match self.get() {
Some(data) => d.field(data),
None => d.field(&format_args!("<uninit>")),
};
d.finish()
}
}