Menu

Reference / Async

select()

function
function select(array $cases): Selected

Wait for whichever case is ready first.

Cases are SelectCases; a bare Channel is shorthand for a receive. If several are ready right now, the first in list order wins. Otherwise the task parks on every case and the first channel to reach it claims it: exactly one case fires, and the losers are deregistered. A receive on a closed channel counts as ready with ok false.

$r = Async\select([$a, SelectCase::send($b, $v)]);
if ($r->isSend) { echo "sent"; } else { echo $r->value; }

Parameters

$cases array<int, Channel|SelectCase>

Returns

Selected — which case fired and with what

Throws

\LogicException
when $cases is empty
ChannelClosedException
when a send case targets a closed channel
CancelledException
when the task is cancelled while waiting

Example

use Async\SelectCase;
use function Async\async;
use function Async\channel;
use function Async\delay;
use function Async\select;
use function Async\selectNow;
use function Async\selectWithin;
use function Async\spawn;

async(function () {
    $fast = channel();
    $slow = channel();

    spawn(function () use ($fast) { delay(0.01); $fast->send("from fast"); });
    spawn(function () use ($slow) { delay(0.05); $slow->send("from slow"); });

    // A bare channel is shorthand for a receive case.
    $r = select([$slow, $fast]);
    echo "case {$r->index}: {$r->value}\n";

    // Nothing is ready right now.
    var_dump(selectNow([$fast]));

    // A deadline: null when it expires first.
    var_dump(selectWithin(0.01, [$fast]));

    // The other value is still on its way.
    $r = select([$slow]);
    echo $r->value, "\n";

    // A send arm completes when a receiver (or buffer space) is available.
    $out = channel(1);
    $r = select([SelectCase::send($out, 7)]);
    echo $r->isSend ? "sent " : "received ", $out->recv(), "\n";
});

Output

case 1: from fast
NULL
NULL
from slow
sent 7

See also: selectNow, selectWithin

View source