协程取消 API 的示例代码

2021-06-25 15:48:54 浏览数 (1)

  1. socket
  2. AsyncIO (fread, gethostbyname ...)
  3. sleep
  4. waitSignal
  5. wait/waitpid
  6. waitEvent
  7. Co::suspend/Co::yield
  8. channel
  9. native curl (SWOOLE_HOOK_NATIVE_CURL)

socket

代码语言:javascript复制
use SwooleCoroutine;
use SwooleCoroutineSocket;
use function SwooleCoroutinerun;
use function SwooleCoroutinego;

run(function() {
    $socket = new Socket(AF_INET, SOCK_DGRAM, 0);
    $socket->bind('127.0.0.1', 9601);

    // server
    $cid = go(function () use ($socket) {
        while (true) {
            $peer = null;
            $data = $socket->recvfrom($peer);
            assert(empty($data) === true);
            assert(($socket->errCode == SOCKET_ECANCELED) === true);
            break;
        }
    });

    // client
    Coroutine::sleep(0.1);
    assert(Coroutine::cancel($cid) === true);
});

AsyncIO

代码语言:javascript复制
use SwooleCoroutine;
use SwooleEvent;
use SwooleCoroutineSystem;
use function SwooleCoroutinerun;

run(function () {
    $cid = Coroutine::getCid();
    Event::defer(function () use ($cid) {
        assert(Coroutine::cancel($cid) === true);
    });
    $retval = System::gethostbyname('www.baidu.com');
    echo "Donen";
    assert($retval === false);
    assert(swoole_last_error() === SWOOLE_ERROR_AIO_CANCELED);
});

sleep

代码语言:javascript复制
use SwooleCoroutine;
use SwooleCoroutineSystem;
use function SwooleCoroutinerun;
use function SwooleCoroutinego;

run(function () {
    $cid = Coroutine::getCid();
    go(function () use ($cid) {
        System::sleep(0.002);
        assert(Coroutine::cancel($cid) === true);
        assert(Coroutine::isCanceled() === false);
    });
    $retval = System::sleep(10000);
    echo "Donen";
    assert($retval === false);
    assert(Coroutine::isCanceled() === true);
    assert(swoole_last_error() === SWOOLE_ERROR_CO_CANCELED);
});

waitSignal

代码语言:javascript复制
use SwooleCoroutine;
use SwooleCoroutineSystem;
use function SwooleCoroutinerun;
use function SwooleCoroutinego;

run(function () {
    $cid = Coroutine::getCid();
    go(function () use ($cid) {
        System::sleep(0.002);
        assert(Coroutine::cancel($cid) === true);
    });
    $retval = System::waitSignal(SIGTERM);
    echo "Donen";
    assert($retval === false);
    assert(swoole_last_error() === SWOOLE_ERROR_CO_CANCELED);
});

wait/waitpid

代码语言:javascript复制
use SwooleCoroutine;
use SwooleCoroutineSystem;
use function SwooleCoroutinerun;
use function SwooleCoroutinego;

run(function () {
    $cid = Coroutine::getCid();
    go(function () use ($cid) {
        System::sleep(0.002);
        assert(Coroutine::cancel($cid) === true);
    });
    $retval = System::wait();
    echo "Donen";
    assert($retval === false);
    assert(swoole_last_error() === SWOOLE_ERROR_CO_CANCELED);
});

waitEvent

代码语言:javascript复制
use SwooleCoroutine;
use SwooleCoroutineSystem;
use function SwooleCoroutinerun;
use function SwooleCoroutinego;

run(function () {
    $fp = stream_socket_client('tcp://www.baidu.com:80/', $errno, $errmsg, 1);
    var_dump($fp);

    $cid = Coroutine::getCid();
    go(function () use ($cid) {
        System::sleep(0.002);
        assert(Coroutine::cancel($cid) === true);
    });

    $retval = System::waitEvent($fp);
    echo "Donen";
    assert($retval === false);
    assert(swoole_last_error() === SWOOLE_ERROR_CO_CANCELED);
});

Co::suspend/Co::yield

Co::yield 用于手动让出当前协程的执行权。此方法拥有另外一个别名:Co::suspend()

代码语言:javascript复制
use SwooleCoroutine;
use SwooleCoroutineSystem;
use function SwooleCoroutinerun;
use function SwooleCoroutinego;

run(function () {
    $cid = Coroutine::getCid();
    go(function () use ($cid) {
        System::sleep(0.002);
        assert(Coroutine::cancel($cid) === true);
    });
    $retval = Coroutine::suspend();
    echo "Donen";
    assert($retval === false);
    assert(swoole_last_error() === SWOOLE_ERROR_CO_CANCELED);
});

channel

代码语言:javascript复制
use SwooleCoroutine;
use SwooleCoroutineSystem;
use function SwooleCoroutinerun;
use function SwooleCoroutinego;

run(function () {
    $chan = new CoroutineChannel(1);
    $cid = Coroutine::getCid();
    go(function () use ($cid) {
        System::sleep(0.002);
        assert(Coroutine::cancel($cid) === true);
    });

    assert($chan->push("hello world [1]", 100) === true);
    assert(Coroutine::isCanceled() === false);
    assert($chan->errCode === SWOOLE_CHANNEL_OK);

    assert($chan->push("hello world [2]", 100) === false);
    assert(Coroutine::isCanceled() === true);
    assert($chan->errCode === SWOOLE_CHANNEL_CANCELED);

    echo "Donen";
});

native curl(SWOOLE_HOOK_NATIVE_CURL)

代码语言:javascript复制
use SwooleCoroutine;
use SwooleCoroutineSystem;
use SwooleRuntime;
use function SwooleCoroutinerun;
use function SwooleCoroutinego;

Runtime::enableCoroutine(SWOOLE_HOOK_NATIVE_CURL);
run(function () {
    $ch = curl_init();
    $code = uniqid('swoole_');
    $url = "http://httpbin.org/get?code=".urlencode($code);

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);

    $cid = Coroutine::getCid();
    go(function () use ($cid) {
        System::sleep(0.01);
        assert(Coroutine::cancel($cid) === true);
        assert(Coroutine::isCanceled() === false);
    });

    $output = curl_exec($ch);
    assert(empty($output) === true);
    assert(swoole_last_error() === SWOOLE_ERROR_CO_CANCELED);
    assert(curl_errno($ch) === CURLE_ABORTED_BY_CALLBACK);
    assert(curl_error($ch) === 'Operation was aborted by an application callback');
    curl_close($ch);
});

0 人点赞