Struct LazyLock

Source
pub struct LazyLock<T, I = fn() -> T> { /* private fields */ }
Expand description

A thread-safe value which is initialized on first access.

This type is a thread-safe LazyCell, and can be used in statics.

§Differences from std::sync::LazyLock

There are two possible edge cases that can cause different behavior in this type compared to its std counterpart:

  • If the type is lazily initialized from within its own initialization function, a panic will occur rather than an infinite deadlock.
  • By extension, if the initialization function uses block_on to execute async code and another task attempts to access the underlying value of this type (through either dereferencing or using LazyLock::force) before the initialization function has returned a value, this function will panic rather than block. As such, you should generally avoid using block_on when creating a value inside of a LazyLock.

These two differences allow us to implement LazyLock without an actual lock at all, since we guarantee exclusive access after initialization due to the V5 being single-threaded.

Implementations§

Source§

impl<T, I: FnOnce() -> T> LazyLock<T, I>

Source

pub const fn new(init: I) -> Self

Creates a new LazyLock with the given initializer.

Source

pub fn into_inner(self) -> Result<T, I>

Consume the LazyLock and return the inner value if it has been initialized.

§Errors

If the inner value has not been initialized, this function returns an error containing the initializer function.

Source

pub fn force(&self) -> &T

Forces the evaluation of this lazy value and returns a reference to result. This is equivalent to the Deref impl, but is explicit.

§Panics

This method will panic under two possible edge-cases:

  • It is called recursively from within its own initialization function.
  • The initialization function uses block_on to execute async code, and another task attempts to access the underlying value of this type in the middle of it lazily initializing.

This behavior differs from the standard library, which would normally either block the current thread or deadlock forever. Since the V5 brain is a single-core system, it was determined that panicking is a more acceptable compromise than an unrecoverable deadlock.

Source

pub fn force_mut(&mut self) -> &mut T

Forces the evaluation of this lazy value and returns a mutable reference to the result. This is equivalent to the DerefMut impl, but is explicit.

§Panics

This method will panic under two possible edge-cases:

  • It is called recursively from within its own initialization function.
  • The initialization function uses block_on to execute async code, and another task attempts to access the underlying value of this type in the middle of it lazily initializing.

This behavior differs from the standard library, which would normally either block the current thread or deadlock forever. Since the V5 brain is a single-core system, it was determined that panicking is a more acceptable compromise than an unrecoverable deadlock.

Trait Implementations§

Source§

impl<T: Debug, I> Debug for LazyLock<T, I>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Default> Default for LazyLock<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<T, I: FnOnce() -> T> Deref for LazyLock<T, I>

Source§

fn deref(&self) -> &Self::Target

Dereferences the value.

§Panics

This method will panic under two possible edge-cases:

  • It is called recursively from within its own initialization function.
  • The initialization function uses block_on to execute async code, and another task attempts to access the underlying value of this type in the middle of it lazily initializing.

This behavior differs from the standard library, which would normally either block the current thread or deadlock forever. Since the V5 brain is a single-core system, it was determined that panicking is a more acceptable compromise than an unrecoverable deadlock.

Source§

type Target = T

The resulting type after dereferencing.
Source§

impl<T, I: FnOnce() -> T> DerefMut for LazyLock<T, I>

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.

§Panics

This method will panic under two possible edge-cases:

  • It is called recursively from within its own initialization function.
  • The initialization function uses block_on to execute async code, and another task attempts to access the underlying value of this type in the middle of it lazily initializing.

This behavior differs from the standard library, which would normally either block the current thread or deadlock forever. Since the V5 brain is a single-core system, it was determined that panicking is a more acceptable compromise than an unrecoverable deadlock.

Source§

impl<T, I> Drop for LazyLock<T, I>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<T: Send + Sync, I: Send> Sync for LazyLock<T, I>

Auto Trait Implementations§

§

impl<T, I = fn() -> T> !Freeze for LazyLock<T, I>

§

impl<T, I = fn() -> T> !RefUnwindSafe for LazyLock<T, I>

§

impl<T, I> Send for LazyLock<T, I>
where T: Send, I: Send,

§

impl<T, I> Unpin for LazyLock<T, I>
where T: Unpin, I: Unpin,

§

impl<T, I> UnwindSafe for LazyLock<T, I>
where T: UnwindSafe, I: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.