walkor 9 роки тому
батько
коміт
e98e906560
2 змінених файлів з 201 додано та 13 видалено
  1. 165 0
      Events/Ev.php
  2. 36 13
      Worker.php

+ 165 - 0
Events/Ev.php

@@ -0,0 +1,165 @@
+<?php
+/**
+ * This file is part of workerman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link http://www.workerman.net/
+ * @license http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Workerman\Events;
+
+/**
+ * ev eventloop
+ */
+class Ev implements EventInterface
+{
+    /**
+     * eventBase
+     * @var object
+     */
+    protected $_eventBase = null;
+
+    /**
+     * 所有的事件
+     * @var array
+     */
+    protected $_allEvents = array();
+
+    /**
+     * 所有的信号事件
+     * @var array
+     */
+    protected $_eventSignal = array();
+
+    /**
+     * 所有的定时事件
+     * [func, args, event, flag, time_interval]
+     * @var array
+     */
+    protected $_eventTimer = array();
+
+    /**
+     * 定时器id
+     */
+    protected static $_timerId = 1;
+
+    /**
+     * 添加事件
+     * @see EventInterface::add()
+     */
+    public function add($fd, $flag, $func, $args=null)
+    {
+        $callback = function($event,$socket)use($fd,$func)
+        {
+            call_user_func($func,$fd);
+        };
+
+        switch($flag)
+        {
+            case self::EV_SIGNAL:
+                $event = new \EvSignal($fd,$callback);
+                $this->_eventSignal[$fd] = $event;
+                return true;
+            case self::EV_TIMER:
+            case self::EV_TIMER_ONCE:
+                $repeat = $flag==self::EV_TIMER_ONCE ? 0 : $fd;
+                $param = array($func, (array)$args, $flag, $time_interval, self::$_timerId);
+                $event = new \EvTimer($fd, $repeat, array($this, 'timerCallback'),$param);
+                $this->_eventTimer[self::$_timerId] = $event;
+                return self::$_timerId++;
+            default :
+                $fd_key = (int)$fd;
+                $real_flag = $flag === self::EV_READ ? \Ev::READ : \Ev::WRITE;
+                $event = new \EvIo($fd, $real_flag, $callback);
+                $this->_allEvents[$fd_key][$flag] = $event;
+                return true;
+        }
+
+    }
+
+    /**
+     * 删除事件
+     * @see Events\EventInterface::del()
+     */
+    public function del($fd ,$flag)
+    {
+        switch($flag)
+        {
+            case self::EV_READ:
+            case self::EV_WRITE:
+                $fd_key = (int)$fd;
+                if(isset($this->_allEvents[$fd_key][$flag]))
+                {
+                    $this->_allEvents[$fd_key][$flag]->stop();
+                    unset($this->_allEvents[$fd_key][$flag]);
+                }
+                if(empty($this->_allEvents[$fd_key]))
+                {
+                    unset($this->_allEvents[$fd_key]);
+                }
+                break;
+            case  self::EV_SIGNAL:
+                $fd_key = (int)$fd;
+                if(isset($this->_eventSignal[$fd_key]))
+                {
+                    $this->_allEvents[$fd_key][$flag]->stop();
+                    unset($this->_eventSignal[$fd_key]);
+                }
+                break;
+            case self::EV_TIMER:
+            case self::EV_TIMER_ONCE:
+                if(isset($this->_eventTimer[$fd]))
+                {
+                    $this->_eventTimer[$fd]->stop();
+                    unset($this->_eventTimer[$fd]);
+                }
+                break;
+        }
+        return true;
+    }
+
+    /**
+     * 定时器回调
+     * @param event $event
+     */
+    public function timerCallback($event)
+    {
+        $param = $event->data;
+        $timer_id = $param[4];
+        if($param[2] === self::EV_TIMER_ONCE)
+        {
+            $this->_eventTimer[$timer_id]->stop();
+            unset($this->_eventTimer[$timer_id]);
+        }
+        call_user_func_array($param[0],$param[1]);
+    }
+
+    /**
+     * 删除所有定时器
+     * @return void
+     */
+    public function clearAllTimer()
+    {
+        foreach($this->_eventTimer as $event)
+        {
+            $event->stop();
+        }
+        $this->_eventTimer = array();
+    }
+
+    /**
+     * 事件循环
+     * @see EventInterface::loop()
+     */
+    public function loop()
+    {
+        \Ev::run();
+    }
+}
+
+

+ 36 - 13
Worker.php

@@ -15,8 +15,6 @@ namespace Workerman;
 
 require_once __DIR__.'/Lib/Constants.php';
 
-use \Workerman\Events\Libevent;
-use \Workerman\Events\Select;
 use \Workerman\Events\EventInterface;
 use \Workerman\Connection\ConnectionInterface;
 use \Workerman\Connection\TcpConnection;
@@ -34,7 +32,7 @@ class Worker
      * 版本号
      * @var string
      */
-    const VERSION = '3.2.7';
+    const VERSION = '3.2.8';
     
     /**
      * 状态 启动中
@@ -235,7 +233,7 @@ class Worker
     
     /**
      * 全局事件轮询库,用于监听所有资源的可读可写事件
-     * @var Select/Libevent
+     * @var Select/Libevent/Ev
      */
     public static $globalEvent = null;
     
@@ -337,6 +335,20 @@ class Worker
         'start_timestamp' => 0,
         'worker_exit_info' => array()
     );
+    
+    /**
+     * 可用的事件轮询库
+     * @var array
+     */
+    protected static $_availableEventLoops = array(
+        'libevent', 'ev'
+    );
+    
+    /**
+     * 当前eventLoop使用的是哪个
+     * @var string
+     */
+    protected static $_eventLoopName = 'select';
 
     /**
      * php内置协议
@@ -786,6 +798,23 @@ class Worker
     }
     
     /**
+     * 获取LoopName
+     * @return string
+     */
+    protected static function getEventLoopName()
+    {
+        foreach(self::$_availableEventLoops as $name)
+        {
+            if(extension_loaded($name))
+            {
+                self::$_eventLoopName = $name;
+                break;
+            }
+        }
+        return self::$_eventLoopName;
+    }
+    
+    /**
      * 获得所有子进程的pid
      * @return array
      */
@@ -1168,7 +1197,7 @@ class Worker
             file_put_contents(self::$_statisticsFile, 'Workerman version:' . Worker::VERSION . "          PHP version:".PHP_VERSION."\n", FILE_APPEND);
             file_put_contents(self::$_statisticsFile, 'start time:'. date('Y-m-d H:i:s', self::$_globalStatistics['start_timestamp']).'   run ' . floor((time()-self::$_globalStatistics['start_timestamp'])/(24*60*60)). ' days ' . floor(((time()-self::$_globalStatistics['start_timestamp'])%(24*60*60))/(60*60)) . " hours   \n", FILE_APPEND);
             $load_str = 'load average: ' . implode(", ", $loadavg);
-            file_put_contents(self::$_statisticsFile, str_pad($load_str, 33) . 'event-loop:'.(extension_loaded('libevent') ? 'libevent' : 'select')."\n", FILE_APPEND);
+            file_put_contents(self::$_statisticsFile, str_pad($load_str, 33) . 'event-loop:'.self::getEventLoopName()."\n", FILE_APPEND);
             file_put_contents(self::$_statisticsFile,  count(self::$_pidMap) . ' workers       ' . count(self::getAllWorkerPids())." processes\n", FILE_APPEND);
             file_put_contents(self::$_statisticsFile, str_pad('worker_name', self::$_maxWorkerNameLength) . " exit_status     exit_count\n", FILE_APPEND);
             foreach(self::$_pidMap as $worker_id =>$worker_pid_array)
@@ -1430,14 +1459,8 @@ class Worker
         // 如果没有全局事件轮询,则创建一个
         if(!self::$globalEvent)
         {
-            if(extension_loaded('libevent'))
-            {
-                self::$globalEvent = new Libevent();
-            }
-            else
-            {
-                self::$globalEvent = new Select();
-            }
+            $eventLoopClass = "\\Workerman\\Events\\". ucfirst(self::getEventLoopName());
+            self::$globalEvent = new $eventLoopClass;
             // 监听_mainSocket上的可读事件(客户端连接事件)
             if($this->_socketName)
             {