Coordination and limits
Examples
Every example of this topic, with its output.
Event#
$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 againLockInterface#
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#
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#
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#
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#
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";
});