Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
Development · Evolving reference

RwLock

Owns one retained reader/writer lock and its movable payload. Creation may allocate; guards retain payload/native storage independently. Separate readonly published borrows may acquire concurrently. Mutating/moving the owner handle itself requires external synchronization. Blocking acquisition occupies the calling thread; try acquisition reports contention as an optional. Guards release on their acquiring thread and cannot cross await. No fairness, lock upgrade or recursive exclusive acquisition is promised.

Sn is under heavy development. This reference includes the intended 1.0 design; features may be incomplete in the current compiler. Read the status →

Module std.sync

import std.sync;

Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.

RwLock

pub final class RwLock<T> where T: Movable

Owns one retained reader/writer lock and its movable payload. Creation may allocate; guards retain payload/native storage independently. Separate readonly published borrows may acquire concurrently. Mutating/moving the owner handle itself requires external synchronization. Blocking acquisition occupies the calling thread; try acquisition reports contention as an optional. Guards release on their acquiring thread and cannot cross await. No fairness, lock upgrade or recursive exclusive acquisition is promised. T: Movable payload protected by guard-controlled interior access.

Example

module example.rwlock;
from std.sync import RwLock, RwReadGuard, RwWriteGuard;
fn Main() -> i32 {
    var Owner = {
        // Keep writable result storage through the explicit noncopy payload transfer.
        var OwnerCreation = RwLock<i32>.TryCreate(40);
        switch OwnerCreation {
            case .Ok { Value = Value: mut RwLock<i32>& } => break move(Value);
            case .Err => return 1;
        }
    };
    {
        var Writer = {
            // Keep writable result storage through the explicit noncopy payload transfer.
            var WriterCreation = Owner.Write();
            switch WriterCreation {
                case .Ok { Value = Value: mut RwWriteGuard<i32>& } => break move(Value);
                case .Err => return 2;
            }
        };
        Writer.Value() += 2;
        switch Owner.TryRead() { case .Ok { Value = Value } => { if Value is .Some { Value = _ } { return 3; } } case .Err => return 4; }
    }
    {
        let Reader = {
            // Keep writable result storage through the explicit noncopy payload transfer.
            var ReaderCreation = Owner.Read();
            switch ReaderCreation {
                case .Ok { Value = Value: mut RwReadGuard<i32>& } => break move(Value);
                case .Err => return 5;
            }
        };
        if Reader.Value() != 42 { return 6; }
        switch Owner.TryWrite() { case .Ok { Value = Value } => { if Value is .Some { Value = _ } { return 7; } } case .Err => return 8; }
        // The second guard remains owned by writable wrapper storage until transfer.
        var ReadAttempt = Owner.TryRead();
        switch ReadAttempt { case .Ok { Value = Value: mut RwReadGuard<i32>?& } => { switch move(Value) { case .Some { Value = Second } => { if Second.Value() != 42 { return 9; } } case .None => return 10; } } case .Err => return 11; }
    }
    return 0;
}

RwLock.init

pub init()

Creates an inert owner without allocation.

RwLock.init

pub init(Source: readonly Self&) = delete;

Rejects copying owner authority. Source: Existing owner.

RwLock.init

pub init(Source: mut Self&&)

Transfers owner storage without invalidating independently retained guards. Source: Owner left inert.

RwLock.operator

pub fn operator =(Source: readonly Self&) -> void = delete;

Rejects copying owner authority. Source: Existing owner. Return: No runtime result; this assignment is deleted and cannot be invoked.

RwLock.operator

pub fn operator =(Source: mut Self&&) -> void

Releases previous visible ownership and transfers new storage without blocking. Source: Owner left inert; self-move is preserved by shared transport. Return: No value after transferring shared state and releasing displaced visible ownership without waiting.

RwLock.IsEmpty

pub IsEmpty: bool;

Reports inert/default/moved ownership.

RwLock.TryCreate

pub static fn TryCreate(mut Value: T) -> Result<Self, LockCreationError<T>>

Allocates native/shared storage and moves the input only into successful ownership. Value: Owned payload, returned in LockCreationError on failure. Return: Initialized owner or exact portable error retaining Value.

RwLock.Read

pub readonly fn Read() -> Result<RwReadGuard<T>, LockError>

Blocks this thread until guarded access or provider failure. Return: Retained guard or portable error.

RwLock.TryRead

pub readonly fn TryRead() -> Result<RwReadGuard<T>?, LockError>

Attempts access without blocking on contention. Return: Optional retained guard, empty for contention, or portable error.

RwLock.Write

pub readonly fn Write() -> Result<RwWriteGuard<T>, LockError>

Blocks this thread until guarded access or provider failure. Return: Retained guard or portable error.

RwLock.TryWrite

pub readonly fn TryWrite() -> Result<RwWriteGuard<T>?, LockError>

Attempts access without blocking on contention. Return: Optional retained guard, empty for contention, or portable error.

Documentation snapshot: October 24, 2026 About versions ↗
Searching Development · language & standard library