Есть код, который срабатывает когда приходит событие по одному из прослушиваемых сокетов.
while (true) {
//формируем массив прослушиваемых сокетов:
$read = $connects;
stream_select($read, $write, $except, null);//ожидаем сокеты доступные для чтения (без таймаута)
...обрабатываем $read
}
Нужно также срабатывание по таймеру 20 раз в секунду.
Если для этого использовать таймаут:
stream_select($read, $write, $except, 0.05));
то процессор постоянно загружен на 100% (о чём и предупреждают на php.net, что stream_select с таймерами работает не эффективно)
Мою задачу можно легко решить используя libevent:
$this->base = event_base_new();
$timer = event_timer_new();
event_timer_set($timer, array($this, '_onTimer'), $timer);
event_base_set($timer, $this->base);
event_timer_add($timer);
Но мне нужно решить задачу без использования libevent.
Сейчас решаю задачу так: создаю парный сокет используя
stream_socket_pair()
, делаю
fork()
и в дочернем процессе в бесконечном цикле записываю данные в парный сокет $parent:
while (true) {
fwrite('ping', $parent);
usleep(50000);
}
В родительском же процессе прослушиваю парный сокет $child, который связан с дочерним:
$read = [$child];
Это позволяет мне добиться нужного эффекта с нулевой загрузкой процессора.
Есть ли какая-то возможность создавать сокеты, которые бы отваливались по таймауту, так чтобы срабатывала функция stream_select с этим событием, чтобы код был аналогично libevent?
Сразу предупрежу, что tick в данном случае не работает, по-тому что пока stream_select ждёт событий по прослушиваемым сокетам - "тиков" не происходит.