Coroutine Channel

Latest version: pecl install openswoole-22.1.2 | composer require openswoole/core:22.1.5

What is a channel?

Channels are one of the most important concepts in Open Swoole and coroutines.

A channel is a non-blocking primitive for communication between two or more coroutines, you can use a channel to communicate between different coroutines and manage data between them.

Because coroutines have access to the same memory space, they can conflict with modifying memory which could be dependant by another coroutine as they are running within user space, on the same thread.

That is why we can solve memory access conflicts and race conditions with the help of channels. It is similar to chan in Golang.

You can think of a channel like a PHP array but has support for working within inside a coroutine and will not block as all operations are done within memory.

The short name \chan is the alias of OpenSwoole\Coroutine\Channel.

You can also use WaitGroup or batch, Barrier to sync coroutines.

Methods

Channel Class Properties

  • OpenSwoole\Coroutine\Channel->$capacity: The queue capacity of the channel, set within the constructor when creating a new channel. Needs to be more than or equal to 1.

  • OpenSwoole\Coroutine\Channel->$errCode: Get the error code status of the channel.

Return ValueConstantDescription
0OpenSwoole\Coroutine\Channel::CHANNEL_OKDefault success, everything is working correctly, no errors
-1OpenSwoole\Coroutine\Channel::CHANNEL_TIMEOUTTimeout when pop fails (timeout)
-2OpenSwoole\Coroutine\Channel::CHANNEL_CLOSEDThe channel is closed

Quick Start Example

Here we show an example of a channel with a capacity of 1, pushing to the channel and waiting for the second coroutine to remove (pop) the data from the channel.

<?php

co::run(function () {

    $chan = new OpenSwoole\Coroutine\Channel(1);
    go(function() use ($chan) {
        $cid = OpenSwoole\Coroutine::getCid();
        $i = 0;
        while (1) {
            co::sleep(1);
            $chan->push(['rand' => rand(1000, 9999), 'index' => $i]);
            echo "[coroutine $cid] - $i\n";
            $i++;
        }

    });

    go(function() use ($chan) {
        $cid = OpenSwoole\Coroutine::getCid();
        while(1) {
            $data = $chan->pop();
            echo "[coroutine $cid]\n";
            var_dump($data);
        }
    });
});

Below is an example which shows how a channel works in a simple manner, we create a channel and set the max capacity to 1, push the $data to the channel and then remove (pop) from the channel to receive the data we initially put in.

Just make sure to pass your channels to each coroutine that needs access to it.

<?php

co::run(function() {

    $data = 'Hello World!';

    $chan = new chan(1);
    $chan->push($data);
    $pop = $chan->pop();

    var_dump($pop);

});
Last updated on September 19, 2022