silk.mem.frozen.
Shared ownership of one value that never changes, on one thread, with plain shared borrows.
When to use#
Use Frozen when many owners hold the same value and only read it, such as the nodes of a
hash-consed tree. Equal values can then share one allocation, and code can read two handles to
the same value at once. For a value that changes, use silk.mem.shared.Shared.
Details#
Frozen.make allocates one time. Frozen.clone, Frozen.with and Frozen.get do not
allocate. The value is dropped when the last handle is dropped. A handle stays on the thread that
made it; share across threads with silk.concurrency.sync.Arc.
Unlike Shared, access is not exclusive: a nested read of the same value through any handle is
allowed, since no handle can change it.
Gotchas#
Handles that refer to each other in a cycle are never dropped. A value that never changes cannot
form a cycle unless it held a mutable handle, such as a Shared, that was changed later.
Examples#
Read one value through two handles at once#
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.core.effect { Effect }
import silk.mem.frozen { Frozen }
pub effect fn main() -> i32
! OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
let first = run Frozen<i32>.make(40) |> Effect.provideMut<Allocator>(&mut allocator)
let second = Frozen<i32>.clone(&first)
let sum = Frozen<i32>.with<i32>(&first, fn(left: &i32) -> i32 {
return Frozen<i32>.with<i32>(&second, fn(right: &i32) -> i32 { return left.* + right.* })
})
if sum != 80 || Frozen<i32>.count(&first) != 2 { return 1 }
return 0
}Import as Frozen with import silk.mem.frozen { Frozen }.
Public declarations: 1.
Frozen#
pub struct Frozen<T>A handle to one value of type T that never changes and that other handles can also own.
Details#
The handle is one pointer. Its count is a plain word, so a handle cannot move to another thread.
Frozen.with and Frozen.get give shared borrows only, and any number of them can be live
at once, also to the same value.
Implementation Frozen<T>#
impl<T> Frozen<T>Associated function make#
pub effect<'env> fn make<'env>(value: T) -> Frozen<T> ! OutOfMemoryError ? &mut AllocatorAllocates storage, moves value into it, and returns the first handle.
Errors#
OutOfMemoryErrorif theAllocatorcannot supply the storage.valueis dropped.
Method clone#
pub fn clone(self: &Self) -> Frozen<T>Returns a new handle to the same value. It does not allocate and does not touch the value.
Gotchas#
A count past half the range of a word traps before the handle exists.
Method get#
pub fn get<'a>(self: &'a Self) -> &'a TBorrows the value for as long as this handle is borrowed.
Method with#
pub fn with<A>(self: &Self, use: once fn(&T) -> A) -> ACalls use one time with a shared borrow of the value and returns the result of use.
Details#
The callback can read this value again, through this handle or any other.
Method count#
pub fn count(self: &Self) -> usizeReturns the number of handles to the value.
Method address#
pub fn address(self: &Self) -> usizeThe address of the value's allocation, which every handle to it shares. It stays the same while any handle lives, and another value can reuse it after the last handle drops.
Associated function same#
pub fn same(left: &Self, right: &Self) -> boolWhether both handles refer to the same allocation, which equal values made apart do not.
Implementation Drop for Frozen<T>#
impl<T> Drop for Frozen<T>Operation drop#
fn drop(self: &mut Frozen<T>) -> ()Category: Memory.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.