2
2
3
3
namespace React \EventLoop \Timer ;
4
4
5
+ use SplObjectStorage ;
6
+ use SplPriorityQueue ;
7
+ use InvalidArgumentException ;
5
8
use React \EventLoop \LoopInterface ;
6
9
7
10
class Timers
8
11
{
9
12
const MIN_RESOLUTION = 0.001 ;
10
13
11
- private $ loop ;
12
14
private $ time ;
13
- private $ active = array ();
14
15
private $ timers ;
16
+ private $ scheduler ;
15
17
16
- public function __construct (LoopInterface $ loop )
18
+ public function __construct ()
17
19
{
18
- $ this ->loop = $ loop ;
19
- $ this ->timers = new \ SplPriorityQueue ();
20
+ $ this ->timers = new SplObjectStorage () ;
21
+ $ this ->scheduler = new SplPriorityQueue ();
20
22
}
21
23
22
24
public function updateTime ()
@@ -29,68 +31,69 @@ public function getTime()
29
31
return $ this ->time ?: $ this ->updateTime ();
30
32
}
31
33
32
- public function add ($ interval , $ callback , $ periodic = false )
34
+ public function add (TimerInterface $ timer )
33
35
{
34
- if ($ interval < self ::MIN_RESOLUTION ) {
35
- throw new \InvalidArgumentException ('Timer events do not support sub-millisecond timeouts. ' );
36
- }
36
+ $ interval = $ timer ->getInterval ();
37
37
38
- if (! is_callable ( $ callback ) ) {
39
- throw new \ InvalidArgumentException ('The callback must be a callable object . ' );
38
+ if ($ interval < self :: MIN_RESOLUTION ) {
39
+ throw new InvalidArgumentException ('Timer events do not support sub-millisecond timeouts . ' );
40
40
}
41
41
42
- $ interval = ( float ) $ interval ;
42
+ $ scheduledAt = $ interval + $ this -> getTime () ;
43
43
44
- $ timer = (object ) array (
45
- 'interval ' => $ interval ,
46
- 'callback ' => $ callback ,
47
- 'periodic ' => $ periodic ,
48
- 'scheduled ' => $ interval + $ this ->getTime (),
49
- );
50
-
51
- $ timer ->signature = spl_object_hash ($ timer );
52
- $ this ->timers ->insert ($ timer , -$ timer ->scheduled );
53
- $ this ->active [$ timer ->signature ] = $ timer ;
54
-
55
- return $ timer ->signature ;
44
+ $ this ->timers ->attach ($ timer , $ scheduledAt );
45
+ $ this ->scheduler ->insert ($ timer , -$ scheduledAt );
56
46
}
57
47
58
- public function cancel ($ signature )
48
+ public function cancel (TimerInterface $ timer )
59
49
{
60
- unset( $ this ->active [ $ signature ] );
50
+ $ this ->timers -> detach ( $ timer );
61
51
}
62
52
63
53
public function getFirst ()
64
54
{
65
- if ($ this ->timers ->isEmpty ()) {
55
+ if ($ this ->scheduler ->isEmpty ()) {
66
56
return null ;
67
57
}
68
58
69
- return $ this ->timers ->top ()->scheduled ;
59
+ $ scheduledAt = $ this ->timers [$ this ->scheduler ->top ()];
60
+
61
+ return $ scheduledAt ;
70
62
}
71
63
72
64
public function isEmpty ()
73
65
{
74
- return ! $ this ->active ;
66
+ return count ( $ this ->timers ) === 0 ;
75
67
}
76
68
77
69
public function tick ()
78
70
{
79
71
$ time = $ this ->updateTime ();
80
72
$ timers = $ this ->timers ;
73
+ $ scheduler = $ this ->scheduler ;
81
74
82
- while (!$ timers ->isEmpty () && $ timers ->top ()->scheduled < $ time ) {
83
- $ timer = $ timers ->extract ();
75
+ while ($ scheduler ->isEmpty () === false ) {
76
+ $ timer = $ scheduler ->top ();
77
+
78
+ if (isset ($ timers [$ timer ]) === false ) {
79
+ $ scheduler ->extract ();
80
+ $ timers ->detach ($ timer );
81
+
82
+ continue ;
83
+ }
84
+
85
+ if ($ timers [$ timer ] >= $ time ) {
86
+ break ;
87
+ }
84
88
85
- if ( isset ( $ this -> active [ $ timer -> signature ])) {
86
- call_user_func ($ timer ->callback , $ timer-> signature , $ this -> loop );
89
+ $ scheduler -> extract ();
90
+ call_user_func ($ timer ->getCallback () , $ timer );
87
91
88
- if ($ timer ->periodic === true ) {
89
- $ timer ->scheduled = $ timer ->interval + $ time ;
90
- $ timers ->insert ($ timer , -$ timer ->scheduled );
91
- } else {
92
- unset($ this ->active [$ timer ->signature ]);
93
- }
92
+ if ($ timer ->isPeriodic () && isset ($ timers [$ timer ])) {
93
+ $ timers [$ timer ] = $ scheduledAt = $ timer ->getInterval () + $ time ;
94
+ $ scheduler ->insert ($ timer , -$ scheduledAt );
95
+ } else {
96
+ $ timers ->detach ($ timer );
94
97
}
95
98
}
96
99
}
0 commit comments