<?php

/**
* SIGALRM信号处理器注册成功后,在什么情况下进程会收到该信号呢?
*
* 在Linux系统下,每个进程都有惟一的一个定时器,该定时器提供了以秒为单位的定时功能。在定时器设置的超时时间到达后,调用alarm的进程将收到SIGALRM信号。
*/ /**
* 启动信号处理器
*/
\MySignalClazz::init(); /**
* 信号处理器
* @author Administrator
*
*/
class MySignalClazz { /**
* Tasks that based on ALARM signal.
* [
* run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
* run_time => [[$func, $args, $persistent, time_interval],[$func, $args, $persistent, time_interval],..]],
* ..
* ]
*
* @var array
*/
protected static $_tasks = array(); /**
* 注册信号处理器
*/
public static function init()
{
pcntl_signal(SIGALRM, array('\MySignalClazz', 'signalHandle'), false);
} /**
* 信号处理器
* ALARM signal handler.
* @return void
*/
public static function signalHandle(){
pcntl_alarm(1); // 创建一个计时器,在1秒后向进程发送一个SIGALRM信号
self::tick();
} /**
* Add a timer.
*
* @param int $time_interval
* @param callback $func
* @param mixed $args
* @param bool $persistent
* @return bool
*/
public static function add($time_interval, $func, $args = array(), $persistent = true)
{
if ($time_interval <= 0) {
echo new Exception("bad time_interval");
return false;
} if (!is_callable($func)) {
echo new Exception("not callable");
return false;
} if (empty(self::$_tasks)) {
pcntl_alarm(1); // 重新启动定时器,实现1秒定时
} $time_now = time();
$run_time = $time_now + $time_interval; // 计算执行时间
if (!isset(self::$_tasks[$run_time])) {
self::$_tasks[$run_time] = array();
}
self::$_tasks[$run_time][] = array($func, (array)$args, $persistent, $time_interval);
return true;
} /**
* 单次执行函数
*/
public static function tick()
{
if (empty(self::$_tasks)) {
pcntl_alarm(0); // 不在创建新的信号
return;
} $time_now = time();
foreach (self::$_tasks as $run_time => $task_data) {
if ($time_now >= $run_time) { // 到达执行时间
foreach ($task_data as $index => $one_task) {
$task_func = $one_task[0];
$task_args = $one_task[1];
$persistent = $one_task[2];
$time_interval = $one_task[3];
try {
call_user_func_array($task_func, $task_args); // 执行注册的函数
} catch (\Exception $e) {
echo $e;
}
if ($persistent) {
self::add($time_interval, $task_func, $task_args); // 重新计算下次执行时间,添加进去
}
}
unset(self::$_tasks[$run_time]); // 执行完就删除掉
}
}
}
}

workman源代码阅读 - 使用信号处理器实现定时器的更多相关文章

  1. [转]madwifi无线网卡源代码阅读

    转自:http://xiyong8260.blog.163.com/blog/static/66514621200892465922669/ 在我的Doctor课题研究中,基于ARF协议设计了一个改进 ...

  2. 非常好!!!Linux源代码阅读——内核引导【转】

    Linux源代码阅读——内核引导 转自:http://home.ustc.edu.cn/~boj/courses/linux_kernel/1_boot.html 目录 Linux 引导过程综述 BI ...

  3. 非常好!!!Linux源代码阅读——中断【转】

    Linux源代码阅读——中断 转自:http://home.ustc.edu.cn/~boj/courses/linux_kernel/2_int.html 目录 为什么要有中断 中断的作用 中断的处 ...

  4. Mongodb源代码阅读笔记:Journal机制

    Mongodb源代码阅读笔记:Journal机制 Mongodb源代码阅读笔记:Journal机制 涉及的文件 一些说明 PREPLOGBUFFER WRITETOJOURNAL WRITETODAT ...

  5. 【转】Tomcat总体结构(Tomcat源代码阅读系列之二)

    本文是Tomcat源代码阅读系列的第二篇文章,我们在本系列的第一篇文章:在IntelliJ IDEA 和 Eclipse运行tomcat 7源代码一文中介绍了如何在intelliJ IDEA 和 Ec ...

  6. 利用doxygen提高源代码阅读效率

    阅读开源项目的源代码是提高自己编程能力的好方法,而有一个好的源代码阅读工具无疑能够让你在阅读源代码时事半功倍.之前找过不少源代码阅读工具,像SourceInsight.sourcenav.scitoo ...

  7. CI框架源代码阅读笔记5 基准測试 BenchMark.php

    上一篇博客(CI框架源代码阅读笔记4 引导文件CodeIgniter.php)中.我们已经看到:CI中核心流程的核心功能都是由不同的组件来完毕的.这些组件类似于一个一个单独的模块,不同的模块完毕不同的 ...

  8. 淘宝数据库OceanBase SQL编译器部分 源代码阅读--Schema模式

    淘宝数据库OceanBase SQL编译器部分 源代码阅读--Schema模式 什么是Database,什么是Schema,什么是Table,什么是列,什么是行,什么是User?我们能够能够把Data ...

  9. CI框架源代码阅读笔记3 全局函数Common.php

    从本篇開始.将深入CI框架的内部.一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说.全局函数具有最高的载入优先权.因此大多数的框架中BootStrap ...

随机推荐

  1. Got the Best Employee of the year 2015 Star Award

    Got "The Best Employee of the year 2015 Star Award" from the company, thanks to all that h ...

  2. Generate input file for OVITO

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...

  3. Fig 应用编排

    Fig是Docker的应用编排工具,主要用来跟 Docker 一起来构建基于 Docker 的复杂应用,Fig 通过一个配置文件来管理多个Docker容器,非常适合组合使用多个容器进行开发的场景. 说 ...

  4. Android开发学习之路-RecyclerView使用初探

    在进行一些MaterialDesign规范开发的时候,比如之前说到的CoordinateLayout实现的向上折叠效果的时候,如果依然使用ListView,那么这种效果是做不出来的,因为ListVie ...

  5. AngularJS 源码分析2

    上一篇地址 本文主要分析RootScopeProvider和ParseProvider RootScopeProvider简介 今天这个rootscope可是angularjs里面比较活跃的一个pro ...

  6. 深入理解滚动scroll

    前面的话 前面两篇博文分别介绍过偏移大小.客户区大小.本文介绍元素尺寸中内容最多的一部分——滚动scroll 滚动宽高 scrollHeight scrollHeight表示元素的总高度,包括由于溢出 ...

  7. 白话贝叶斯理论及在足球比赛结果预测中的应用和C#实现

    离去年“马尔可夫链进行彩票预测”已经一年了,同时我也计划了一个彩票数据框架的搭建,分析和预测的框架,会在今年逐步发表,拟定了一个目录,大家有什么样的意见和和问题,可以看看,留言我会在后面的文章中逐步改 ...

  8. 如何利用Oracle外部表导入文本文件的数据

    同事最近在忙数据一致性比对工作,需要对不同文本文件中的数据进行比对,有的文件较大,记录较多,如果用普通的文本编辑器打开的话,很显然,会很卡,甚至打不开. 基于此,可将该文本文件的数据导入到数据库中,在 ...

  9. Windows 使用 Yeoman generators 创建 ASP.NET 应用程序

    上一篇:<Windows 搭建 .NET 跨平台环境并运行应用程序> 阅读目录: Install Node.js Install yeoman-generators Create ASP. ...

  10. 改用C++生成自动化数据表

    改用C++生成自动化数据表 前面的文章中,我们讨论了使用一个基于.NET的第三方程序库来从程序中来生成数据表.在我看来,这整个思路是非常有用的,例如为显示测试结果.我经常会自己在博客中尝试各种像这样的 ...