class Sync::Shared(T)

Overview

Safely share a value T across fibers and execution contexts using a RWLock to control when the access to a value can be shared (read-only) or must be exclusive (replace or mutate the value).

For example:

require "sync/shared"

class Queue
  @@running : Sync::Shared.new([] of Queue)

  def self.on_started(queue)
    @@running.write(&.push(queue))
  end

  def self.on_stopped(queue)
    @@running.write(&.delete(queue))
  end

  def self.each(&)
    @@running.read do |list|
      list.each { |queue| yield queue }
    end
  end
end

Included Modules

Defined in:

shared.cr

Constructors

Instance Method Summary

Constructor Detail

def self.new(value : T, type : Type = :checked) #

[View source]

Instance Method Detail

def clone : T #

Locks in shared mode and returns a deep copy of the value. The lock is released before returning the new value.


[View source]
def dup : T #

Locks in shared mode and returns a shallow copy of the value. The lock is released before returning the new value.


[View source]
def get : T #

Locks in shared mode and returns the value.

Always acquires the lock, so reading the value is synchronized in relation with the other methods. However, safely accessing the returned value entirely depends on the safety of T, which should be Sync::Safe.

Prefer #dup or #clone to get a shallow or deep copy of the value instead.

WARNING Breaks the shared/exclusive guarantees, since the returned value outlives the lock; it can be accessed in parallel to the synchronized methods.


[View source]
def read(& : T -> U) : U forall U #

Locks in shared mode and yields the value. The lock is released before returning.

The value is owned in shared mode for the duration of the block, and thus shouldn't be mutated for example, unless T can be safely mutated (it should be Sync::Safe).

WARNING The value musn't be retained and accessed after the block has returned.


[View source]
def replace(& : T -> T) : T #

Locks in exclusive mode, yields the current value and eventually replaces the value with the one returned by the block. The lock is released before returning.

The current value is owned: it can be safely mutated and even retained after the block returned.

WARNING The new value musn't be accessed after the block has returned.


[View source]
def set(value : T) : T #

Locks in exclusive mode and sets the value.


[View source]
def unsafe_get : T #

Returns the value without any synchronization.

WARNING Breaks the safety constraints! Only use when you can guarantee that the current fiber acquired the lock or to access a value that can be read in a single load operation from memory.


[View source]
def unsafe_set(value : T) : T #

Sets the value without any synchronization.

WARNING Breaks the safety constraints! Only use when you can guarantee that the current fiber acquired the lock or to access a value that can be written in a single store operation into memory.


[View source]
def write(& : T -> U) : U forall U #

Locks in exclusive mode and yields the value. The lock is released before returning.

The value is owned in exclusive mode for the duration of the block, as such it can be safely mutated.

WARNING The value musn't be retained and accessed after the block has returned.


[View source]