国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

php毫秒定時器,也支持win

dazhaozhao

學(xué)習(xí)workerman源碼,研究了定時器部分,抄了一個定時器類出來,分享出來,調(diào)用方式一樣。

<?php
class Timer
{

    const EV_TIMER = 1;

    const EV_TIMER_ONCE = 2;

    protected $scheduler = null;

    protected $eventTimer = array();

    public $timerId = 1;

    protected $selectTimeout = 100000000;

    protected $socket = array();

    public function __construct()
    {
        $this->socket    = stream_socket_pair(DIRECTORY_SEPARATOR === '/' ? STREAM_PF_UNIX : STREAM_PF_INET, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
        $this->scheduler = new \SplPriorityQueue();
        $this->scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH);
    }

    public function add($fd, $flag, $func, $args = array())
    {

        $timer_id = $this->timerId++;
        $run_time = microtime(true) + $fd;

        $this->scheduler->insert($timer_id, -$run_time);
        $this->eventTimer = array($func, (array) $args, $flag, $fd);
        $select_timeout              = ($run_time - microtime(true)) * 1000000;
        if ($this->selectTimeout > $select_timeout) {
            $this->selectTimeout = $select_timeout;
        }
        return $timer_id;
    }

    public function loop()
    {
        while (1) {
            $read = $this->socket;
            set_error_handler(function () {});
            $ret = stream_select($read, $write = , $except = , 0, $this->selectTimeout);
            restore_error_handler();

            if (!$this->scheduler->isEmpty()) {
                $this->tick();
            }
        }
    }

    public function getTimerCount()
    {
        return count($this->eventTimer);
    }

    /**
     * Tick for timer.
     *
     * @return void
     */
    protected function tick()
    {
        while (!$this->scheduler->isEmpty()) {
            $scheduler_data      = $this->scheduler->top();
            $timer_id            = $scheduler_data;
            $next_run_time       = -$scheduler_data;
            $time_now            = microtime(true);
            $this->selectTimeout = ($next_run_time - $time_now) * 1000000;
            if ($this->selectTimeout <= 0) {
                $this->scheduler->extract();

                if (!isset($this->eventTimer)) {
                    continue;
                }
                // 
                $task_data = $this->eventTimer;
                if ($task_data === self::EV_TIMER) {
                    $next_run_time = $time_now + $task_data;
                    $this->scheduler->insert($timer_id, -$next_run_time);
                }
                call_user_func_array($task_data, $task_data);
                if (isset($this->eventTimer) && $task_data === self::EV_TIMER_ONCE) {
                    $this->del($timer_id, self::EV_TIMER_ONCE);
                }
                continue;
            }
            return;
        }
        $this->selectTimeout = 100000000;
    }

    /**
     * {@inheritdoc}
     */
    public function del($fd, $flag)
    {
        $fd_key = (int) $fd;
        unset($this->eventTimer);
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function clearAllTimer()
    {
        $this->scheduler = new \SplPriorityQueue();
        $this->scheduler->setExtractFlags(\SplPriorityQueue::EXTR_BOTH);
        $this->eventTimer = array();
    }

}

function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return bcadd($usec, $sec, 3);
}

$timer = new Timer();

$timer->add(1, Timer::EV_TIMER, function () {
    echo microtime_float() . "\n";
});

$timer->add(1, Timer::EV_TIMER_ONCE, function () {
    echo microtime_float() . "once \n";
});

$timer->loop();
3433 4 0
4個回答

法師

牛逼,學(xué)習(xí)了

  • 暫無評論
keytehu

學(xué)習(xí)了

  • 暫無評論
pader

stream_select 在這里的作用我不是很了解,但我看代碼感覺這個本質(zhì)上就是用PHP的優(yōu)先級隊列,不斷循環(huán)檢查最小優(yōu)先級的隊列是否符合時間,這種死循環(huán)的形式,CPU占用應(yīng)該還是比較大的吧,整體上并不是無阻塞的,在要求不高的場景上可以用,但不能堪以大用。跟 Workerman 的定時器還是差很多的。

  • dazhaozhao 2019-08-13

    這個本來就是workerman上抄下來的。
    當(dāng)然workerman不僅僅只是做了這些處理,我只是抄了其中一個,如果有l(wèi)ibevent、event擴(kuò)展,就不會走stream_select了

dazhaozhao

我再解釋下:
1、定時器實現(xiàn),一般可以使時間輪、時間堆,上面就是時間堆機(jī)制
2、php的優(yōu)先級隊列很適合做,就不需要自己寫最小堆了。
3、stream_select超時?,兼容win。

  • a392223903 2020-09-06

    請教一下,如果其中一個定時器出現(xiàn)執(zhí)行阻塞,那這個不就不準(zhǔn)了嗎

  • dazhaozhao 2020-09-16

    對的,定時器只是一個觸發(fā)機(jī)制,定時觸發(fā),簡單的運算,可以,如果是繁重的任務(wù),或者可能出現(xiàn)長時間的阻塞的話,可以先起一些任務(wù)進(jìn)程,定時器觸發(fā)后,發(fā)送異步任務(wù)到任務(wù)進(jìn)程去做,避免阻塞定時器的運行。

年代過于久遠(yuǎn),無法發(fā)表回答
??