Swoole Coroutine Go and Co Methods

Go and Co

\Go can be used to create new coroutine which is the short name of \Swoole\Coroutine::create. \Co is the short name of \Swoole\Coroutine.

Create coroutine

<?php
go(function () {
    co::sleep(0.5);
    echo "hello";
});
go("test");
go([$object, "method"]);

Channels communication

<?php
$c = new chan(1);
$c->push($data);
$c->pop();

Sleep in Coroutine

<?php
Swoole\Coroutine::sleep(100);

Read file

<?php
Swoole\Coroutine::fread($fp);

Get host name

<?php
Swoole\Coroutine::gethostbyname('www.google.com');
Swoole\Coroutine::set(array $option) : void

Avaible options for Swoole\Coroutine:

<?php
$option = [
    "max_coroutine" => 4096, // max coroutine number can be created, the default value is 4096
    "stack_size" => 8192, // set the stack size of each coroutine, the default value is 8192
];
Swoole\Coroutine::set($option);
Swoole\Coroutine::getuid() : int

Get the ID of current coroutine.

<?php
echo Swoole\Coroutine::getuid();

Swoole\Coroutine::create(callable $function)

Create a new coroutine and execute it immediately.

Example of using \Go to create new coroutine:

<?php
go(function () {
    $db = new Co\MySQL();
    $server = array(
        'host' => '127.0.0.1',
        'user' => 'root',
        'password' => 'root',
        'database' => 'test',
    );

    $db->connect($server);

    $result = $db->query('SELECT * FROM userinfo WHERE id = 3');
    var_dump($result);
});
Execution order:
<?php
go(function() {
    go(function () {
        co::sleep(3.0);
        go(function () {
            co::sleep(2.0);
            echo "co[3] end\n";
        });
        echo "co[2] end\n";
    });

    co::sleep(1.0);
    echo "co[1] end\n";
});
Execution cost

Each coroutine use 8KB memory stack to store variables by default in PHP7.2+ or 256KB stack in <= PHP7.1.

Swoole\Coroutine::resume(string $coroutineId) : void

Resume the coroutine and continue execute the coroutine.

Example:

<?php
use Swoole\Coroutine as co;
$id = go(function(){
    $id = co::getUid();
    echo "start coro $id\n";
    co::suspend();
    echo "resume coro $id @1\n";
    co::suspend();
    echo "resume coro $id @2\n";
});
echo "start to resume $id @1\n";
co::resume($id);
echo "start to resume $id @2\n";
co::resume($id);
echo "main\n";
Swoole\Coroutine::suspend() : void

Suspend current coroutine.

Swoole\Coroutine::fread(resource $handle, int $length = 0) : string

Read files with coroutine.

Example:

<?php
use Swoole\Coroutine as co;
$fp = fopen(__DIR__ . "/defer_client.php", "r");
co::create(function () use ($fp)
{
    fseek($fp, 256);
    $r =  co::fread($fp);
    var_dump($r);
});
Swoole\Coroutine::fgets(resource $handle) : string

Read files line by line with coroutine.

Example:

<?php
$fp = fopen(__DIR__ . "/defer_client.php", "r");
go(function () use ($fp)
{
    $r =  co::fgets($fp);
    var_dump($r);
});
Swoole\Coroutine::fwrite(resource $handle, string $string, int $length = 0) : int

Write to the file with coroutine.

Example:

<?php
use Swoole\Coroutine as co;
$fp = fopen(__DIR__ . "/test.data", "a+");
co::create(function () use ($fp)
{
    $r =  co::fwrite($fp, "hello world\n", 5);
    var_dump($r);
});
Swoole\Coroutine::sleep(float $seconds) : int

Sleep in coroutine and release the CPU for other operations.

Example:

<?php
$serv = new Swoole\Http\Server("127.0.0.1", 9502);

$serv->on('Request', function($request, $response) {
    Swoole\Coroutine::sleep(0.2);
    $response->end("<h1>Hello Swoole!</h1>");
});

$serv->start();
Swoole\Coroutine::gethostbyname(string $domain, int $family = AF_INET): string

Get the IP from host name.

Example:

<?php
use Swoole\Coroutine as co;
$ip = co::gethostbyname("www.google.com");
Swoole\Coroutine::getaddrinfo(string $domain, int $family = AF_INET, int $socktype = SOCK_STREAM, int $protocol = IPPROTO_TCP, string $service = null): array | bool

Exmple:

<?php
$array = co::getaddrinfo("www.google.com");
Swoole\Coroutine::exec(string $cmd) : array

Execute shell command with coroutine.

Example:

<?php
go(function() {
    $ret = Co::exec("md5sum ".__FILE__);
});
Swoole\Coroutine::readFile(string $filename) : string

Read file with coroutine.

Example:

<?php
use Swoole\Coroutine as co;
$filename = __DIR__ . "/defer_client.php";
co::create(function () use ($filename)
{
    $r =  co::readFile($filename);
    var_dump($r);
});
Swoole\Coroutine::writeFile(string $filename, string $fileContent, int $flags)

Write file with coroutine.

<?php
use Swoole\Coroutine as co;
$filename = __DIR__ . "/defer_client.php";
co::create(function () use ($filename)
{
    $r =  co::writeFile($filename,"hello swoole!");
    var_dump($r);
});
Swoole\Coroutine::stats() : array

Get the current status of coroutine.

Example:

<?php
var_dump(Swoole\Coroutine::stats());

array(1) {
  ["coroutine_num"]=>
  int(132)
  ["coroutine_peak_num"]=>
  int(2)
}
Swoole\Coroutine::getBackTrace(int $cid=0, int $options=DEBUG_BACKTRACE_PROVIDE_OBJECT, int $limit=0) : array

Get call stack of the function.

Example:

<?php
function test1() {
    test2();
}

function test2() {
    while(true) {
        co::sleep(10);
        echo __FUNCTION__." \n";
    }
}

$cid = go(function () {
    test1();
});

go(function () use ($cid) {
    while(true) {
        echo "BackTrace[$cid]:\n-----------------------------------------------\n";
        var_dump(co::getBackTrace($cid))."\n";
        co::sleep(3);
    }
});
Swoole\Coroutine::listCoroutines() : Iterator

Get all the coroutines of current process.

Example:

<?php
$coros = Coroutine::listCoroutines();
foreach($coros as $cid)
{
    var_dump(Coroutine::getBackTrace($cid));
}
Runtime::enableCoroutine

Since version 4.1.0, it is possible to enable coroutine on any IO libraries using php_stream.

Support libraries:

  • Redis
  • mysqlnd PDO, mysqli
  • soap
  • file_get_contents, fopen
  • stream_socket_client
  • fsockopen

Not support:

  • mysql with libmysqlclient
  • curl with libcurl
  • mongo with mongo-c-client
  • pdo_pgsql, pdo_ori, pdo_odbc, pdo_firebird

Example:

<?php
Swoole\Runtime::enableCoroutine();

go(function () {
    $redis = new redis;
    $retval = $redis->connect("127.0.0.1", 6379);
    var_dump($retval, $redis->getLastError());
    var_dump($redis->get("key"));
    var_dump($redis->set("key", "value2"));
    var_dump($redis->get("key"));
    $redis->close();
});