php - Amp PHP - 协作多任务/异步睡眠
问题描述
在单线程 PHP 中,我需要编写一个应用程序:
- a) 充当 HTTP 服务器
- b) 能够发出一些 HTTP 请求
a) 和 b) 必须工作,即使服务器正在等待/服务请求或 HTTP 客户端正在等待回复
我想出了一个使用 PHP Amp 服务器的想法。它工作得很好。
但是对于 HTTP 客户端,我需要使用 PHP curl。
我的代码如下所示:
...
$mh = curl_multi_init();
curl_multi_add_handle($mh, $ch);
do {
AmpLoopHelper::asyncSleep(0.001);
$mrc = curl_multi_exec($mh, $isRunning);
} while ($isRunning && ($mrc == CURLM_CALL_MULTI_PERFORM || $mrc == CURLM_OK));
...
和自定义AmpLoopHelper
类:
<?php
namespace Mvorisek\Dsv;
use Amp\Loop;
use Amp\Loop\Driver;
class AmpLoopHelper {
/** @var int|null */
private static $dummyWatcherId;
/**
* Async sleep and keep processing of Loop tasks.<br>
* Loop\Driver::tick() is always called at least once even if
* the sleep delay is zero or negative.
*
* @param float $sleepSecs
*/
public static function asyncSleep(float $sleepSecs): void {
$t = microtime(true);
// add dummy function to repeat to prevent Loop\Driver::tick() to block
$maxCheckDelayMillis = min(max(1, $sleepSecs * 1000 / 50), 50);
$isNested = static::$dummyWatcherId !== null;
if (!$isNested) {
static::$dummyWatcherId = Loop::repeat($maxCheckDelayMillis, static function() {});
}
try {
do {
if (static::loopDriverIsRunning()) {
static::loopDriverTick();
} else {
usleep(($sleepSecs - (microtime(true) - $t)) * 1e6);
break;
}
usleep(40);
} while(microtime(true) - $t < $sleepSecs);
} finally {
if (!$isNested) {
Loop::cancel(static::$dummyWatcherId);
}
}
}
private static function loopDriverGet(): Driver {
return \Closure::bind(static function() {
return Loop::$driver;
}, null, Loop::class)();
}
private static function loopDriverIsRunning(): bool {
$driver = static::loopDriverGet();
return \Closure::bind(static function() use($driver) {
return $driver->running;
}, null, Driver::class)();
}
private static function loopDriverTick(): void {
$driver = static::loopDriverGet();
\Closure::bind(static function() use($driver) {
$driver->tick();
}, null, Driver::class)();
}
}
但有时无法访问 HTTP 服务器。助手类使用了 Amp 类的一些私有方法。
想法asyncSleep
正确吗?
解决方案
问题是Driver->dispatch()
可以用阻塞标志调用,并且阻塞流没有从我的助手类中更新。
推荐阅读
- android - 为什么 ObjectAnimator 不能在 addOnGlobalLayoutListener 中工作
- database-design - 用于引用两个不同表的架构设计
- python - 提取不同行上的操作
- c++ - 使用随机二分搜索算法有什么好处?
- libgdx - 获取被点击的灯具
- flutter - 没有为“_MyAppState”类型定义方法“getApplicationDocumentsDirectory”
- python - 创建管道(Python)时,“MultiOutputClassifier”对象不可迭代
- swift - 一些 UICollectionViewDropDelegateMethods 未被调用
- javascript - 如何在 webpack treeshaking 中排除自定义构造函数?
- javascript - 从 codecommit 调用 lambda