Completed
Push — master ( ec8c5b...0b9fa7 )
by Ryosuke
02:59
created

Delayer::add()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 15
ccs 12
cts 12
cp 1
rs 9.2
cc 4
eloc 11
nc 3
nop 2
crap 4
1
<?php
2
3
namespace mpyw\Co\Internal;
4
use mpyw\RuntimePromise\Deferred;
5
6
class Delayer
7
{
8
    /**
9
     * Delays to be ended at.
10
     * @var array
11
     */
12
    private $untils = [];
13
14
    /**
15
     * Deferreds.
16
     * @var Deferred
17
     */
18
    private $deferreds = [];
19
20
    /**
21
     * Add delay.
22
     * @param int      $time
23
     * @param Deferred $deferred
24
     */
25 6
    public function add($time, Deferred $deferred)
26 6
    {
27 6
        $time = filter_var($time, FILTER_VALIDATE_FLOAT);
28 6
        if ($time === false) {
29 1
            throw new \InvalidArgumentException('Delay must be number.');
30
        }
31 5
        if ($time < 0) {
32 1
            throw new \DomainException('Delay must be positive.');
33
        }
34
        do {
35 4
            $id = uniqid();
36 4
        } while (isset($this->untils[$id]));
37 4
        $this->untils[$id] = microtime(true) + $time;
38 4
        $this->deferreds[$id] = $deferred;
39 4
    }
40
41
    /**
42
     * Sleep at least required.
43
     */
44 12
    public function sleep()
45 12
    {
46 12
        $now = microtime(true);
47 12
        $min = null;
48 12
        foreach ($this->untils as $id => $until) {
49 4
            $diff = $until - $now;
50 4
            if ($diff < 0) {
51
                // @codeCoverageIgnoreStart
52
                return;
53
                // @codeCoverageIgnoreEnd
54
            }
55 4
            if ($min !== null && $diff >= $min) {
56 2
                continue;
57
            }
58 4
            $min = $diff;
59
        }
60 12
        $min && usleep($min * 1000000);
61 12
    }
62
63
    /**
64
     * Consume delay queue.
65
     */
66 21
    public function consume()
67 21
    {
68 21
        foreach ($this->untils as $id => $until) {
69 4
            $diff = $until - microtime(true);
70 4
            if ($diff > 0.0 || !isset($this->deferreds[$id])) {
71 2
                continue;
72
            }
73 4
            $deferred = $this->deferreds[$id];
74 4
            unset($this->deferreds[$id], $this->untils[$id]);
75 4
            $deferred->resolve(null);
76
        }
77 21
    }
78
79
    /**
80
     * Is $untils empty?
81
     * @return bool
82
     */
83 17
    public function isEmpty()
84 17
    {
85 17
        return !$this->untils;
86
    }
87
}
88