Skip to content

Instantly share code, notes, and snippets.

@sina42048
Last active October 27, 2021 09:04
Show Gist options
  • Save sina42048/4f62caa95103435cba67ea90c07f8c92 to your computer and use it in GitHub Desktop.
Save sina42048/4f62caa95103435cba67ea90c07f8c92 to your computer and use it in GitHub Desktop.
<?php
$timers = [];
$futureTicks = [];
function setTimeout($callback, $delay)
{
global $timers;
$delay = $delay === 0 ? 1 : $delay;
$timers[] = [
'type' => 'timeout',
'time' => hrtime(true) + ($delay * 1000000),
'callback' => $callback,
'happend' => false
];
return array_key_last($timers);
}
function setInterval($callback, $delay)
{
global $timers;
$delay = $delay === 0 ? 1 : $delay;
$timers[] = [
'type' => 'interval',
'delay' => ($delay * 1000000),
'time' => hrtime(true) + ($delay * 1000000),
'callback' => $callback,
'happend' => false // never change
];
return array_key_last($timers);
}
function setImmediate($callback)
{
global $futureTicks;
$futureTicks[] = [
'callback' => $callback
];
}
function clearTimeout($id)
{
global $timers;
unset($timers[$id]);
}
function clearInterval($id)
{
global $timers;
unset($timers[$id]);
}
// **** USAGE ****
function exactDelay()
{
$id = setTimeout(function () use (&$id) {
exactDelay();
echo 'exact' . PHP_EOL;
clearTimeout($id);
}, 0);
}
setImmediate(function () {
echo 'immediate' . PHP_EOL;
});
$timeout1 = setTimeout(function () {
echo 'timeout' . PHP_EOL;
}, 3000);
$interval1 = setInterval(function () {
echo 'interval' . PHP_EOL;
}, 2000);
setTimeout(function () use ($interval1) {
clearInterval($interval1);
}, 8100);
exactDelay();
while (true) {
$currentTime = hrtime(true);
$delayNextLoop = null;
foreach ($timers as $key => &$timer) {
if ($timer['happend'] === false) {
if ($delayNextLoop === null) {
$delayNextLoop = $timer['time'] - $currentTime < 0 ? 0 : $timer['time'] - $currentTime;
}
$delayNextLoop = ($timer['time'] - $currentTime) < $delayNextLoop ? (($timer['time'] - $currentTime) < 0 ? 0 : $timer['time'] - $currentTime) : $delayNextLoop;
}
if ($timer['time'] <= hrtime(true) && $timer['happend'] === false) {
switch ($timer['type']) {
case 'interval':
$timer['time'] = hrtime(true) + $timer['delay'];
call_user_func($timer['callback']);
break;
case 'timeout':
$timer['happend'] = true;
call_user_func($timer['callback']);
break;
}
}
}
foreach ($futureTicks as $key => &$future) {
call_user_func($future['callback']);
unset($futureTicks[$key]);
}
$second = $delayNextLoop > 999999999 ? (round($delayNextLoop / 1000000000) == 0 ? 1 : round($delayNextLoop / 1000000000)) : 0;
$nanoSecond = $delayNextLoop > 999999999 ? 0 : $delayNextLoop;
time_nanosleep($second, $nanoSecond);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment