Swoole Coroutine Methods

Methods list:

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

Coroutine clients

<?php
$redis = new Co\Redis;
$mysql = new Co\MySQL;
$http = new Co\Http\Client;
$tcp = new Co\Client;
$http2 = new Co\Http2\Client;

Sleep in Coroutine

<?php
co::sleep(100);

Read file

<?php
co::fread($fp);

Get host name

<?php
co::gethostbyname('www.google.com');

Coroutine::getuid

function \Swoole\Coroutine::getuid() : int

Get the unique ID of current coroutine.

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

Coroutine::create

Create a new coroutine and execute it immediately.

function Swoole\Coroutine::create(callable $function)

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.

Coroutine::resume

Resume the coroutine and continue execute the coroutine.

function Swoole\Coroutine::resume(string $coroutineId);

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";

--EXPECT--
start coro 1
start to resume 1 @1
resume coro 1 @1
start to resume 1 @2
resume coro 1 @2
main

Coroutine::suspend

function Swoole\Coroutine::suspend();

Suspend current coroutine.

Coroutine::fread

function Coroutine::fread(resource $handle, int $length = 0);

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

Coroutine::fgets

function Coroutine::fgets(resource $handle);

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

Coroutine::fwrite

function Coroutine::fwrite(resource $handle, string $data, int $length = 0);

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

Coroutine::sleep

function Coroutine::sleep(float $seconds);

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

Coroutine::gethostbyname

function Coroutine::gethostbyname(string $domain, int $family = AF_INET): string | bool

Get the IP from host name.

Example:

<?php
use Swoole\Coroutine as co;
$ip = co::gethostbyname("www.google.com");

Coroutine::getaddrinfo

function 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");

Coroutine::exec

function Coroutine::exec(string $cmd) : array;

Execute shell command with coroutine.

Example:

<?php
go(function() {
    $ret = Co::exec("md5sum ".__FILE__);
});

Coroutine::readFile

function Coroutine::readFile(string $filename);

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

Coroutine::writeFile

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

Coroutine::stats

function \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)
}

Coroutine::getBackTrace

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

Coroutine::listCoroutines

function Coroutine::listCoroutines() : Iterator

Get all the coroutines of current process.

Example:

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

Coroutine\Channel

Channel for communction between coroutines. Similar to chan in Golang.

Example:

<?php
use Swoole\Coroutine as co;
$chan = new co\Channel(1);
co::create(function () use ($chan) {
    for($i = 0; $i < 100000; $i++) {
        co::sleep(1.0);
        $chan->push(['rand' => rand(1000, 9999), 'index' => $i]);
        echo "$i\n";
    }
});
co::create(function () use ($chan) {
    while(1) {
        $data = $chan->pop();
        var_dump($data);
    }
});
swoole_event::wait();

Coroutine\Channel->__construct

Coroutine\Channel->__construct(int $capacity = 1)

Construction method.

Coroutine\Channel->push

function Coroutine\Channel->push(mixed $data) : bool;

Write data into channel.

Coroutine\Channel->pop

function Coroutine\Channel->pop(float $timeout = 0) : mixed;

Read data from channel.

Coroutine\Channel->stats

function Coroutine\Channel->stats() : array;

Get the stats of the channel.

Coroutine\Channel->close

funtion Coroutine\Channel->close();

Close channel and resume the other Coroutine.

Coroutine\Channel->length

public function length(): int

Get the number of items in channel.

Coroutine\Channel->isEmpty

public function isEmpty(): bool

Check if the channel is empty.

Coroutine\Channel->isFull

Check if the channel is full.

Coroutine\Channel->$capacity

The capacity of the channel.

Coroutine\Channel->$errCode

Get he error code of the channel.

Coroutine\Client

The coroutine version of TCP and UDP client.

Example:

<?php
$client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
if (!$client->connect('127.0.0.1', 9501, 0.5))
{
    exit("connect failed. Error: {$client->errCode}\n");
}
$client->send("hello world\n");
echo $client->recv();
$client->close();

Coroutine\Client->connect

bool $swoole_client->connect(string $host, int $port, float $timeout = 0.1)

Connect to the remote server.

Example:

<?php
if ($cli->connect('127.0.0.1', 9501)) {
      $cli->send("data");
} else {
      echo "connect failed.";
}

Coroutine\Client->send

function client->send(string $data);

Send data to the remote server.

Coroutine\Client->recv

function Coroutine\Client->recv(float $timeout = -1) : string;

Receive data from the remote server.

Coroutine\Client->close

function Coroutine\Client->close() : bool;

Close the connection.

Coroutine\Client->peek

function Coroutine\Client->peek(int $length = 65535) : string;

Check the data in the socket buffer.

Coroutine\Http\Client

Enable Coroutine HTTP client

Example:

<?php
$cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$cli->setHeaders([
    'Host' => "localhost",
    "User-Agent" => 'Chrome/49.0.2587.3',
    'Accept' => 'text/html,application/xhtml+xml,application/xml',
    'Accept-Encoding' => 'gzip',
]);
$cli->set([ 'timeout' => 1]);
$cli->get('/index.php');
echo $cli->body;
$cli->close();
Attribute list

echo socket_strerror($client->errCode);

<?php
$cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$cli->get('/index.php');
echo $cli->body;
$cli->close();

The HTTP status code.

Coroutine\Http\Client->get

function Swoole\Coroutine\Http\Client->get(string $path);

Init the GET request.

Example:

<?php

$cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$cli->setHeaders([
    'Host' => "localhost",
    "User-Agent" => 'Chrome/49.0.2587.3',
    'Accept' => 'text/html,application/xhtml+xml,application/xml',
    'Accept-Encoding' => 'gzip',
]);

$cli->get('/index.php');
echo $cli->body;
$cli->close();

Coroutine\Http\Client->post

function Swoole\Coroutine\Http\Client->post(string $path, mixed $data);

Init the POST request.

<?php
$cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 80); 
$cli->post('/post.php', array("a" => '1234', 'b' => '456'));
echo $cli->body;
$cli->close();

Coroutine\Http\Client->upgrade

function Coroutine\Http\Client->upgrade(string $path);

Upgrade to be websocket connection.

Example:

<?php
go(function () {
    $cli = new Co\http\Client("127.0.0.1", 9501);
    $ret = $cli->upgrade("/");
    if ($ret) {
        while(true) {
            $cli->push("hello");
            var_dump($cli->recv());
            co::sleep(0.1);
        }
    }
});

Coroutine\Http\Client->push

function Coroutine\Http\Client->push(mixed $data, int $opcode = WEBSOCKET_OPCODE_TEXT, bool $finish = true): bool

Push data to the remote websocket server.

Coroutine\Http\Client->recv

function Coroutine\Http\Client->recv(float $timeout = -1);

Receive data from the remote server.

Example:

<?php
go(function () {
    $cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
    $cli->setHeaders([
        'Host' => "localhost",
        "User-Agent" => 'Chrome/49.0.2587.3',
        'Accept' => 'text/html,application/xhtml+xml,application/xml',
        'Accept-Encoding' => 'gzip',
    ]);
    $cli->set([ 'timeout' => 1]);
    $cli->setDefer();
    $cli->get('/');
    co::sleep(1);
    $data = $cli->recv();
});

Websocket example:

<?php
go(function () {
    $cli = new Co\http\Client("127.0.0.1", 9501);
    $ret = $cli->upgrade("/");

    if ($ret) {
        while(true) {
            $cli->push("hello");
            var_dump($cli->recv());
            co::sleep(0.1);
        }
    }
});

Coroutine\Http\Client->addFile

function Coroutine\Http\Client->addFile(string $path, string $name, string $mimeType = null, string $filename = null, int $offset = 0, int $length = 0)

Attach file to the POST request.

Example:

<?php
$cli = new Swoole\Coroutine\Http\Client('httpbin.org', 80);
$cli->setHeaders([
    'Host' => "httpbin.org"
]);
$cli->set(['timeout' => -1]);
$cli->addFile(__FILE__, 'file1', 'text/plain');
$cli->post('/post', ['foo' => 'bar']);
echo $cli->body;
$cli->close();

Coroutine\Http\Client->addData

function Coroutine\Http\Client->addFile(string $data, string $name, string $mimeType = null, string $filename = null)

Generate file from string and attach to the POST request.

<?php
$cli = new Swoole\Coroutine\Http\Client('httpbin.org', 80);
$cli->setHeaders([
    'Host' => "httpbin.org"
]);
$cli->set(['timeout' => -1]);
$cli->addData(Co::readFile(__FILE__), 'file1', 'text/plain');
$cli->post('/post', ['foo' => 'bar']);
echo $cli->body;
$cli->close();

Coroutine\Http\Client->download

function Coroutine\Http\Client->download(string $path, string $filename, int $offset = 0);

Download data from the remote server.

Example:

<?php
$host = 'www.swoole.com';
$cli = new \Swoole\Coroutine\Http\Client($host, 443, true);
$cli->set(['timeout' => -1]);
$cli->setHeaders([
    'Host' => $host,
    "User-Agent" => 'Chrome/49.0.2587.3',
    'Accept' => '*',
    'Accept-Encoding' => 'gzip'
]);
$cli->download('/static/files/swoole-logo.svg', __DIR__ . '/logo.svg');

Coroutine\Http2\Client

Coroutine version HTTP2 Client

Example:

<?php
use Swoole\Coroutine as co;

co::create(function ()
{
    $cli = new co\Http2\Client('127.0.0.1', 9518);
    $cli->set([ 'timeout' => 1]);
    $cli->connect();

    $req = new co\Http2\Request;
    $req->path = "/index.html";
    $req->headers = [
        'host' => "localhost",
        "user-agent" => 'Chrome/49.0.2587.3',
        'accept' => 'text/html,application/xhtml+xml,application/xml',
        'accept-encoding' => 'gzip',
    ];
    $req->cookies = ['name' => 'rango', 'email' => '1234@qq.com'];
    var_dump($cli->send($req));
    $resp = $cli->recv();
    var_dump($resp);

});

Coroutine\Http2\Client->set

function Coroutine\Http2\Client->set(array $options);

Set the variables of the client: timeout.

Coroutine\Http2\Client->connect

function Coroutine\Http2\Client->connect();

Connect to the remote server.

Coroutine\Http2\Client->send

function Coroutine\Http2\Client->send(swoole_http2_request $request) : int | false

Send request to the remote server.

Coroutine\Http2\Client->write

function Coroutine\Http2\Client->write(int $streamId, mixed $data, bool $end = false);

Write data to the remote server.

Example:

<?php
use Swoole\Coroutine as co;

co::create(function () use ($fp)
{
    $cli = new co\Http2\Client('127.0.0.1', 9518);
    $cli->set([ 'timeout' => 1]);
    var_dump($cli->connect());

    $req3 = new co\Http2\Request;
    $req3->path = "/index.php";
    $req3->headers = [
        'host' => "localhost",
        "user-agent" => 'Chrome/49.0.2587.3',
        'accept' => 'text/html,application/xhtml+xml,application/xml',
        'accept-encoding' => 'gzip',
    ];
    $req3->pipeline = true;
    $req3->method = "POST";
    $streamId = $cli->send($req3);
    $cli->write($streamId, ['int' => rand(1000, 9999)]);
    $cli->write($streamId, ['int' => rand(1000, 9999)]);
    //end stream
    $cli->write($streamId, ['int' => rand(1000, 9999), 'end' => true], true);
    var_dump($cli->recv());
    $cli->close();
});

Coroutine\Http2\Client->recv

function Coroutine\Http2\Client->recv(float $timeout) : Http2\Response

Receive data from the remote server.

Coroutine\Http2\Client->close

function Coroutine\Http2\Client->close();

Close the connection.

Coroutine\Redis

Coroutine version Redis client.

Hiredis library is needed:

sudo make
sudo make install
sudo ldconfig

Example:

<?php
$redis = new Swoole\Coroutine\Redis();
$redis->connect('127.0.0.1', 6379);
$val = $redis->get('key');

The methods are same as Redis client.

Coroutine\Socket

Coroutine version socket.

The methods are same as Socket.

Coroutine\MySQL

Coroutine version MySQL client.

Example:

<?php
$swoole_mysql = new Swoole\Coroutine\MySQL();
$swoole_mysql->connect([
    'host' => '127.0.0.1',
    'port' => 3306,
    'user' => 'user',
    'password' => 'pass',
    'database' => 'test',
]);
$res = $swoole_mysql->query('select sleep(1)');

Coroutine\MySQL->connect

bool connect(array $serverInfo)

Establish the connection to MySQL server.

$serverInfo:

<?php
[
    'host' => 'MySQL server IP',
    'user' => 'username',
    'password' => 'password',
    'database' => 'DB name',
    'port'    => 'DB port',
    'timeout' => 'Timeout',
    'charset' => 'charset',
    'strict_type' => false, 
    'fetch_mode' => true,
]

Coroutine\MySQL->query

array|bool query(string $sql, double $timeout = -1)

Execute MySQL query.

Example:

<?php
$swoole_mysql = new Swoole\Coroutine\MySQL();
$swoole_mysql->connect([
    'host' => '127.0.0.1',
    'port' => 3306,
    'user' => 'user',
    'password' => 'pass',
    'database' => 'test',
]);
$res = $swoole_mysql->query('select * from $table');
if($res === false) {
    return;
}
foreach ($res as $value) {
    echo $value['f_filed_name'];
}

Coroutine\MySQL->prepare

function Coroutine\MySQL->prepare(string $sql, float $timeout) : bool

Similar to prepare in MySQL client.

Example:

<?php
use Swoole\Coroutine as co;
co::create(function() {
    $db = new co\MySQL();
    $server = array(
        'host' => '127.0.0.1',
        'user' => 'root',
        'password' => 'root',
        'database' => 'test',
    );

    $ret1 = $db->connect($server);
    $stmt = $db->prepare('SELECT * FROM userinfo WHERE id=?');
    if ($stmt == false)
    {
        var_dump($db->errno, $db->error);
    }
    else
    {
        $ret2 = $stmt->execute(array(10));
        var_dump($ret2);
    }
});

Coroutine\MySQL\Statement->execute

function Coroutine\MySQL\Statement->execute(array $params, float $timeout = -1) : bool

Similar to execute in MySQL client.

<?php
use Swoole\Coroutine as co;
co::create(function() {
    $db = new co\MySQL();
    $server = array(
        'host' => '127.0.0.1',
        'user' => 'root',
        'password' => 'root',
        'database' => 'test',
    );

    $ret1 = $db->connect($server);
    $stmt = $db->prepare('SELECT * FROM userinfo WHERE id=? and name=?');
    if ($stmt == false)
    {
        var_dump($db->errno, $db->error);
    }
    else
    {
        $ret2 = $stmt->execute(array(10, 'rango'));
        var_dump($ret2);

        $ret3 = $stmt->execute(array(13, 'alvin'));
        var_dump($ret3);
    }
});

Coroutine\MySQL\Statement->fetch

function Coroutine\MySQL->fetch() : ?array

Get the next item in result set.

<?php
$stmt = $db->prepare('SELECT * FROM ckl LIMIT 1');
$stmt->execute();
while($ret = $stmt->fetch())
{
    var_dump($ret);
}

Coroutine\MySQL\Statement->fetchAll

function Coroutine\MySQL->fetchAll() : ?array

Get all items in the result set.

Example:

<?php
$stmt = $db->prepare('SELECT * FROM ckl LIMIT 1');
$stmt->execute();
$stmt->fetchAll();

Coroutine\MySQL\Statement->nextResult

function Coroutine\MySQL->nextResult() : ?bool

Get the next result in result set.

Example:

<?php
$stmt = $db->prepare('CALL reply(?)');
$res = $stmt->execute(['hello mysql!']);
do {
    var_dump($res);
} while ($res = $stmt->nextResult());
var_dump($stmt->affected_rows);

Example 2:

<?php
$stmt = $db->prepare('CALL reply(?)');
$stmt->execute(['hello mysql!']);
do {
    $res = $stmt->fetchAll();
    var_dump($res);
} while ($stmt->nextResult());
var_dump($stmt->affected_rows);

Coroutine\PostgreSQL

Coroutine version PostgreSQL client.

Example:

<?php
go(function () {
    $pg = new Swoole\Coroutine\PostgreSQL();
    $conn  = $pg -> connect ("host=127.0.0.1 port=5432 dbname=test user=root password=");
    $result = $pg -> query($conn, 'SELECT * FROM test;');
    $arr = $pg -> fetchAll($result);
    var_dump($arr);
});

The methods are same as PostgreSQL client.

Runtime::enableCoroutine

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

Support libraries:

Not support:

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