Channels, Locks and Atomics

37.1 Channels (Thread-Safe Queues)

my $channel = Channel.new;
my $producer = start {
    for 1..5 { $channel.send($_); sleep 0.05 }
    $channel.close;
};
my @consumers = (1..2).map: -> $id {
    start {
        my @got;
        for $channel.list -> $item { @got.push($item * 10) }   # blocks until items arrive or the channel closes
        "consumer $id got {@got}";
    }
};
await $producer;
.say for await @consumers;

# Non-blocking poll and react integration
my $c2 = Channel.new;
$c2.send('hello'); $c2.close;
with $c2.poll { say "polled: $_" }
react { whenever $c2 -> $v { say $v } }   # Channels work in whenever too

37.2 Locks and Atomic Operations

Prefer higher-level tools (Promises, Supplies, Channels, hyper/race) over locks. Mutable shared state across threads needs a Lock, atomics, or Lock::Async.

# Lock
my $lock = Lock.new;
my $counter = 0;
await (^10).map: { start { for ^1000 { $lock.protect({ $counter++ }) } } };
say $counter;                         # 10000

# Atomic integers (⚛ operators; ASCII names atomic-fetch-inc etc.)
my atomicint $atomic = 0;
await (^10).map: { start { for ^1000 { $atomic⚛++ } } };
say ⚛$atomic;                          # 10000
my atomicint $n = 5;
say cas($n, 5, 10), ' ', $n;           # compare-and-swap: 5 10

# Lock::Async (non-blocking, works well with await)
my $alock = Lock::Async.new;
await start { $alock.protect({ say 'async-protected section' }) };