phasync
Coordination and limits / Examples

Coordination and limits

Examples

Every example of this topic, with its output.

Event#

Example 1
$onMessage = new phasync\Util\Event();
$onMessage->listen(function (string $data, bool $binary) {
    echo "got $data\n";
});
$onMessage->once(fn () => print("first message only\n"));

$onMessage->trigger('hello', false);   // got hello, then: first message only
$onMessage->trigger('again', false);   // got again

LockInterface#

Example 1
class Counter implements phasync\Util\LockInterface
{
    use phasync\Util\LockTrait;

    public int $value = 0;
}

phasync::run(function () {
    $counter = new Counter();
    $counter->lock(function () use ($counter) {
        $counter->value++;
    });
});

LockTrait#

Example 1
class Account
{
    use phasync\Util\LockTrait;

    private int $balance = 100;

    public function withdraw(int $amount): void
    {
        $this->lock(function () use ($amount) {
            $balance = $this->balance;
            phasync::sleep(0.01);              // another coroutine would interleave here, without the lock
            $this->balance = $balance - $amount;
        });
    }
}

RateLimiter#

Example 1
phasync::run(function () {
    $limiter = new phasync\Util\RateLimiter(10);

    for ($i = 0; $i < 5; $i++) {
        $limiter->wait();
        echo "at most 10 per second\n";
    }
});

Synchronized#

Example 1
phasync::run(function () {
    foreach ([1, 2, 3] as $i) {
        phasync::go(function () use ($i) {
            phasync\Util\Synchronized::run('report', function () use ($i) {
                echo "start $i\n";
                phasync::sleep(0.01);
                echo "end $i\n";           // start and end of different jobs never interleave
            });
        });
    }
});

WaitGroup#

Example 1
phasync::run(function () {
    $group = new phasync\Util\WaitGroup();

    foreach ([0.02, 0.01] as $delay) {
        $group->add();
        phasync::go(function () use ($group, $delay) {
            try {
                phasync::sleep($delay);
            } finally {
                $group->done();
            }
        });
    }
    $group->await();
    echo "both done\n";
});