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#

silk
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#

silk
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>#

silk
impl<T> Frozen<T>

Associated function make#

silk
pub effect<'env> fn make<'env>(value: T) -> Frozen<T> ! OutOfMemoryError ? &mut Allocator

Allocates storage, moves value into it, and returns the first handle.

Errors#

  • OutOfMemoryError if the Allocator cannot supply the storage. value is dropped.

Method clone#

silk
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#

silk
pub fn get<'a>(self: &'a Self) -> &'a T

Borrows the value for as long as this handle is borrowed.

Method with#

silk
pub fn with<A>(self: &Self, use: once fn(&T) -> A) -> A

Calls 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#

silk
pub fn count(self: &Self) -> usize

Returns the number of handles to the value.

Method address#

silk
pub fn address(self: &Self) -> usize

The 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#

silk
pub fn same(left: &Self, right: &Self) -> bool

Whether both handles refer to the same allocation, which equal values made apart do not.

Implementation Drop for Frozen<T>#

silk
impl<T> Drop for Frozen<T>

Operation drop#

silk
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.

View the source of this page