Libevent超时循环退出
我在让 PHP libevent 扩展在超时时打破循环时遇到一些困难。以下是到目前为止我根据 PHP.net 文档页面上的演示得到的信息:
// From here: http://www.php.net/manual/en/libevent.examples.php
function print_line($fd, $events, $arg) {
static $max_requests = 0;
$max_requests++;
printf("Received event: %s after %s\n%s", implode(getEventFlags($events)), getTimer(), fgets($fd));
if ($max_requests == 10) {
// exit loop after 3 writes
echo " [EXIT]\n";
event_base_loopexit($arg[1]);
}
}
// create base and event
$base = event_base_new();
$event = event_new();
getTimer(); // Initialise time
$fd = STDIN;
event_set($event, $fd, EV_READ | EV_PERSIST, "print_line", array($event, $base));
event_base_set($event, $base);
event_add($event, 2000000);
event_base_loop($base);
// extract flags from bitmask
function getEventFlags ($ebm) {
$expFlags = array('EV_TIMEOUT', 'EV_SIGNAL', 'EV_READ', 'EV_WRITE', 'EV_PERSIST');
$ret = array();
foreach ($expFlags as $exf) {
if ($ebm & constant($exf)) {
$ret[] = $exf;
}
}
return $ret;
}
// Used to track time!
function getTimer () {
static $ts;
if (is_null($ts)) {
$ts = microtime(true);
return "Timer initialised";
}
$newts = microtime(true);
$r = sprintf("Delta: %.3f", $newts - $ts);
$ts = $newts;
return $r;
}
我可以看到传递给 event_add
的超时值会影响传递给 print_line() 的事件,如果这些事件是如果间隔超过 2 秒,我会收到 EV_TIMEOUT
而不是 EV_READ
。然而,我想要的是 libevent 在达到超时后立即调用 print_line
而不是等待下一个事件来给我超时。
我尝试过使用 event_base_loopexit($base, 2000000)
,这会导致事件循环立即退出,而不会阻塞事件。我还尝试将 EV_TIMEOUT
传递给 event_set
,这似乎根本没有效果。
以前有人设法让这个工作吗?我知道 event_buffer_* 的东西可以处理超时,但是我想使用标准的 event_base 函数。 PECL bug 之一谈论了 event_timer_* 函数,这些函数确实存在于我的系统,但是它们根本没有记录。
I'm having some difficulties getting the PHP libevent extension to break out of a loop on a timeout. Here's what I've got so far based on the demos on the PHP.net docs pages:
// From here: http://www.php.net/manual/en/libevent.examples.php
function print_line($fd, $events, $arg) {
static $max_requests = 0;
$max_requests++;
printf("Received event: %s after %s\n%s", implode(getEventFlags($events)), getTimer(), fgets($fd));
if ($max_requests == 10) {
// exit loop after 3 writes
echo " [EXIT]\n";
event_base_loopexit($arg[1]);
}
}
// create base and event
$base = event_base_new();
$event = event_new();
getTimer(); // Initialise time
$fd = STDIN;
event_set($event, $fd, EV_READ | EV_PERSIST, "print_line", array($event, $base));
event_base_set($event, $base);
event_add($event, 2000000);
event_base_loop($base);
// extract flags from bitmask
function getEventFlags ($ebm) {
$expFlags = array('EV_TIMEOUT', 'EV_SIGNAL', 'EV_READ', 'EV_WRITE', 'EV_PERSIST');
$ret = array();
foreach ($expFlags as $exf) {
if ($ebm & constant($exf)) {
$ret[] = $exf;
}
}
return $ret;
}
// Used to track time!
function getTimer () {
static $ts;
if (is_null($ts)) {
$ts = microtime(true);
return "Timer initialised";
}
$newts = microtime(true);
$r = sprintf("Delta: %.3f", $newts - $ts);
$ts = $newts;
return $r;
}
I can see that the timeout value passed to event_add
effects the events passed to print_line(), if these events are any more than 2 seconds apart I get an EV_TIMEOUT
instead of an EV_READ
. What I want however is for libevent to call print_line
as soon as the timeout is reached rather than waiting for the next event in order to give me the timeout.
I've tried using event_base_loopexit($base, 2000000)
, this causes the event loop to exit immediately without blocking for events. I've also tried passing EV_TIMEOUT
to event_set
, this seems to have no effect at all.
Has anyone managed to get this working before? I know that the event_buffer_* stuff works with timeouts, however I want to use the standard event_base
functions. One of the PECL bugs talks about event_timer_* functions and these functions do exist on my system, however they're not documented at all.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题出在 fgets() 中:
这会阻止处理并等待来自 STDIN 的数据(但没有超时)
更改为类似的内容:
Problem is in fgets() in:
This blocks processing and waits for data from STDIN (but there are none on timeout)
Change to something like that: