Skip to content

Instantly share code, notes, and snippets.

@xx10n31y
Created July 29, 2021 06:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xx10n31y/c947e03f935e75ad318c3dc8a05f35ef to your computer and use it in GitHub Desktop.
Save xx10n31y/c947e03f935e75ad318c3dc8a05f35ef to your computer and use it in GitHub Desktop.
PHP PCNTL Alarm Simple Demo
<?php
/**
* @references
* https://www.php.cn/php-weizijiaocheng-432036.html
* https://www.jianshu.com/p/139b0e43ef3f
* https://zhuanlan.zhihu.com/p/217622103
* https://segmentfault.com/q/1010000000751497
*/
# 规定每执行一条低级语句就触发ticks信号
declare(ticks=1);
# 实际应用产品调用类
class ResolveTimeout
{
public $flag = false;
# 相同功能方法1
public function method1()
{
echo 'method1' . PHP_EOL;
$rand = rand(1, 3);
echo 'method1_rand_sec:' . $rand . PHP_EOL;
sleep($rand);
echo 'method1_after_sleep' . PHP_EOL;
$this->finished();
}
# 相同功能方法2
public function method2()
{
echo 'method2' . PHP_EOL;
$rand = rand(1, 4);
echo 'method2_rand_sec:' . $rand . PHP_EOL;
sleep($rand);
echo 'method2_after_sleep' . PHP_EOL;
$this->finished();
}
# 相同功能方法3
public function method3()
{
echo 'method3' . PHP_EOL;
$rand = rand(3, 5);
echo 'method3_rand_sec:' . $rand . PHP_EOL;
sleep($rand);
echo 'method3_after_sleep' . PHP_EOL;
$this->finished();
}
# 标识功能完全被调用
private function finished()
{
$this->flag = true;
}
}
# 注册触发ticks时被调用的函数
// register_tick_function(function(){
// echo 'asd';
// },true);
$resolver = new ResolveTimeout();
# 获取一个随机的可调用方法
[$method, $rand] = getCallMethod();
# 开始一个无限循环 直到flag为true(方法执行完毕)
while (true) {
try {
# 创建一个计时器, 在指定秒数后向进程发送一个SIGALRM信号
pcntl_alarm(2);
# 监听SIGALRM信号, 使用匿名函数对超过计时器秒数作出处理
pcntl_signal(SIGALRM, function () {
throw new Exception;
});
# 实际方法调用
$resolver->{$method}();
# 清楚计时器
pcntl_alarm(0);
} catch (Exception $exception) {
# 进入到catch模块, 代表上一个功能方法执行超时
# 重新获取可执行功能方法
[$method, $rand] = getCallMethod($rand);
echo "timeout" . PHP_EOL;
}
# 当flag为true时代表所调用的功能方法已完成操作且未超时
# 跳出无限循环
if ($resolver->flag === true) {
break;
}
}
# 返回一个非previous使用的方法
function getCallMethod($previous=9999)
{
$methods = [
'method1',
'method2',
'method3'
];
$rand = rand(0, count($methods)-1);
if ($rand == $previous) {
getCallMethod($previous);
}
return [$methods[$rand], $rand];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment