使用类静态变量/全局变量保存上下文

多个协程是并发执行的,因此不能使用类静态变量/全局变量保存协程上下文内容。使用局部变量是安全的,因为局部变量的值会自动保存在协程栈中,其他协程访问不到协程的局部变量。

实例

错误的代码

$_array = [];
$serv->on("Request", function ($req, $resp){
	global $_array;
	//请求 /a(协程 1 )
	if ($request->server['request_uri'] == '/a') {
		$_array['name'] = 'a';
		co::sleep(1.0);
		echo $_array['name'];
		$resp->end($_array['name']);
	}
	//请求 /b(协程 2 )
	else {
		$_array['name'] = 'b';
		$resp->end();
	}
});

发起2个并发请求。

curl http://127.0.0.1:9501/a
curl http://127.0.0.1:9501/b

使用 Context 管理上下文

Context

use Swoole\Coroutine;

class Context
{
    protected static $pool = [];

    static function get($key)
    {
        $cid = Coroutine::getuid();
        if ($cid < 0)
        {
            return null;
        }
        if(isset(self::$pool[$cid][$key])){
            return self::$pool[$cid][$key];
        }
        return null;
    }

    static function put($key, $item)
    {
        $cid = Coroutine::getuid();
        if ($cid > 0)
        {
            self::$pool[$cid][$key] = $item;
        }

    }

    static function delete($key = null)
    {
        $cid = Coroutine::getuid();
        if ($cid > 0)
        {
            if($key){
                unset(self::$pool[$cid][$key]);
            }else{
                unset(self::$pool[$cid]);
            }
        }
    }
}

正确的代码

$serv->on("Request", function ($req, $resp) {
	if ($request->server['request_uri'] == '/a') {
		Context::put('name', 'a');
		co::sleep(1.0);
		echo Context::get('name');
		$resp->end(Context::get('name'));
		//退出协程时清理
		Context::delete('name');
	} else {
		Context::put('name', 'b');
		$resp->end();
		//退出协程时清理
		Context::delete();
	}
});