Skip to content
CryoCryo home
Stdlibsync

mpsc

import std::sync::mpsc; · source

Types

Sender<T>

type struct Sender<T> {
    inner: ChannelInner<T>*;

    send(&this, value: T) -> Result<(), SendError<T>>;
    clone(&this) -> Sender<T>;
    close(mut this) -> void;
}

send moves a value into the queue. clone() mints another producer; close() consumes the sender and is equivalent to dropping it early.

Properties

PropertyType
innerChannelInner<T>*

Methods

send(&this, value: T) -> Result<(), SendError<T>>;

Enqueue value. Returns Err(SendError{value}) if the receiver has already been dropped (the value is handed back unconsumed).

clone(&this) -> Sender<T>;

Create another sender on the same channel (multi-producer).

close(mut this) -> void;

Explicitly drop this sender now (rather than at scope end). Useful after moving a sender into a thread body, where the value must be released before the body returns.

Receiver<T>

type struct Receiver<T> {
    inner: ChannelInner<T>*;

    sender(&this) -> Sender<T>;
    recv(&this) -> Result<T, RecvError>;
    try_recv(&this) -> Result<T, TryRecvError>;
}

recv() blocks; try_recv() returns Err(Empty) immediately when nothing is queued. sender() mints producers from the receiver, which is why channel returns only the receiver.

Properties

PropertyType
innerChannelInner<T>*

Methods

sender(&this) -> Sender<T>;

Create a new Sender<T> feeding this channel. Call once per producer (each returned sender is independently owned and may be moved into its own thread); clone an existing sender as an alternative. The channel stays open for recv as long as any sender is alive.

recv(&this) -> Result<T, RecvError>;

Block until a value is available and return it, or return Err(Disconnected) once every sender has dropped and the queue is drained.

try_recv(&this) -> Result<T, TryRecvError>;

Non-blocking receive. Returns Err(Empty) if no value is ready but senders remain, Err(Disconnected) if the channel is drained and all senders have dropped.

The errors

type struct SendError<T> {
    value: T;
}
type enum RecvError {
    Disconnected;
}
type enum TryRecvError {
    Empty;
    Disconnected;
}
SendError
Properties
PropertyType
valueT
RecvError
Variants
Variant
Disconnected
TryRecvError
Variants
Variant
Empty
Disconnected

Disconnection

When every Sender has been dropped, a blocked recv() returns Err(RecvError::Disconnected) and try_recv() returns Err(TryRecvError::Disconnected).

When the Receiver is dropped, send() returns Err(SendError) handing the value back, rather than queueing into a channel nobody will drain.

Underneath, a heap inner holds a mutex and condition variable guarding a raw singly-linked node queue, plus a live-sender count and a total-handle refcount; the inner is reclaimed when the last handle of either kind drops. Values move out of dequeued nodes through raw pointers, so the move-checker sees each as a clean transfer — no aliasing, no double free.

Trait implementations

Sender

implement<T> trait Drop for struct Sender<T>

Receiver

implement<T> trait Drop for struct Receiver<T>

Receiver::drop drains and drops whatever is still queued, which is why it carries the T: Drop bound.

Free Functions

function channel<T>() -> Receiver<T>;

Create an unbounded channel and return its Receiver<T> - the channel's owning end. Mint one or more producers with rx.sender() (each is independently owned and movable into its own thread):

Each Sender<T> is independently owned and movable into its own thread, and cloneable for further fan-out. Values of any type — including owned data like String — move through an unbounded FIFO queue.

import std::sync::mpsc;
import std::thread;

mut rx: mpsc::Receiver<i32> = mpsc::channel::<i32>();
const tx: mpsc::Sender<i32> = rx.sender();

const h = thread::spawn::<mpsc::Sender<i32>, i32>(tx, (s: mpsc::Sender<i32>) -> i32 {
    mut snd: mpsc::Sender<i32> = s;
    snd.send(42);
    snd.close();
    return 0;
});

match (rx.recv()) {
    Result::Ok(v)  => { use(v); }
    Result::Err(_) => { }
}
h.join();