phasync
Coordination and limits / Synchronized

Class

Synchronized

A mutex for coroutines, identified by a string or an object: only one coroutine at a time runs a closure for the same token.

Introduction#

Unlike LockTrait, it is not reentrant: asking again from the coroutine that holds the lock throws. Other coroutines wait their turn, also those of the same context, in the order they asked: the holder hands the lock to the first in line.

Class synopsis#

final class Synchronized {
    /* Methods */
    public static Synchronized::run(object|string $token, Closure $closure): mixed
}

Methods#

MethodDescription
runRuns $closure once no other coroutine runs a closure for $token, and returns what it returns.

Examples#

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
            });
        });
    }
});

See also#

  • LockTraitImplements LockInterface: a lock that is reentrant for the coroutine holding it and fair for the others.
  • PoolA pool of interchangeable resources, of which only so many may exist at once.

Used in#

  • CodeIgniterRun a CodeIgniter 4 application on Swerve through its own worker mode, one request at a time per worker.
  • CakePHPRun a CakePHP 5 application on Swerve: booted once per worker, one request at a time, like PHP-FPM.
  • YiiRun a Yii 3 application on Swerve, one request at a time per worker.
  • LaminasRun a Laminas MVC or Mezzio application on Swerve. MVC rebuilds the application per request and serializes it; Mezzio runs concurrently.
  • FrameworksOne adapter per framework: your application runs unchanged. Which adapters serve requests concurrently, and which one at a time.