@@ -27,11 +27,12 @@ final class ExtEventLoop implements LoopInterface
2727 private $ timerCallback ;
2828 private $ timerEvents ;
2929 private $ streamCallback ;
30- private $ streamEvents = [];
31- private $ streamFlags = [];
32- private $ streamRefs = [];
30+ private $ readEvents = [];
31+ private $ writeEvents = [];
3332 private $ readListeners = [];
3433 private $ writeListeners = [];
34+ private $ readRefs = [];
35+ private $ writeRefs = [];
3536 private $ running ;
3637 private $ signals ;
3738 private $ signalEvents = [];
@@ -70,56 +71,65 @@ function ($signal) {
7071 public function addReadStream ($ stream , callable $ listener )
7172 {
7273 $ key = (int ) $ stream ;
74+ if (isset ($ this ->readListeners [$ key ])) {
75+ return ;
76+ }
7377
74- if (!isset ($ this ->readListeners [$ key ])) {
75- $ this ->readListeners [$ key ] = $ listener ;
76- $ this ->subscribeStreamEvent ($ stream , Event::READ );
78+ $ event = new Event ($ this ->eventBase , $ stream , Event::PERSIST | Event::READ , $ this ->streamCallback );
79+ $ event ->add ();
80+ $ this ->readEvents [$ key ] = $ event ;
81+ $ this ->readListeners [$ key ] = $ listener ;
82+
83+ // ext-event does not increase refcount on stream resources for PHP 7+
84+ // manually keep track of stream resource to prevent premature garbage collection
85+ if (PHP_VERSION_ID >= 70000 ) {
86+ $ this ->readRefs [$ key ] = $ stream ;
7787 }
7888 }
7989
8090 public function addWriteStream ($ stream , callable $ listener )
8191 {
8292 $ key = (int ) $ stream ;
83-
84- if (!isset ($ this ->writeListeners [$ key ])) {
85- $ this ->writeListeners [$ key ] = $ listener ;
86- $ this ->subscribeStreamEvent ($ stream , Event::WRITE );
93+ if (isset ($ this ->writeListeners [$ key ])) {
94+ return ;
8795 }
88- }
8996
90- public function removeReadStream ($ stream )
91- {
92- $ key = (int ) $ stream ;
97+ $ event = new Event ($ this ->eventBase , $ stream , Event::PERSIST | Event::WRITE , $ this ->streamCallback );
98+ $ event ->add ();
99+ $ this ->writeEvents [$ key ] = $ event ;
100+ $ this ->writeListeners [$ key ] = $ listener ;
93101
94- if (isset ($ this ->readListeners [$ key ])) {
95- unset($ this ->readListeners [$ key ]);
96- $ this ->unsubscribeStreamEvent ($ stream , Event::READ );
102+ // ext-event does not increase refcount on stream resources for PHP 7+
103+ // manually keep track of stream resource to prevent premature garbage collection
104+ if (PHP_VERSION_ID >= 70000 ) {
105+ $ this ->writeRefs [$ key ] = $ stream ;
97106 }
98107 }
99108
100- public function removeWriteStream ($ stream )
109+ public function removeReadStream ($ stream )
101110 {
102111 $ key = (int ) $ stream ;
103112
104- if (isset ($ this ->writeListeners [$ key ])) {
105- unset($ this ->writeListeners [$ key ]);
106- $ this ->unsubscribeStreamEvent ($ stream , Event::WRITE );
113+ if (isset ($ this ->readEvents [$ key ])) {
114+ $ this ->readEvents [$ key ]->free ();
115+ unset(
116+ $ this ->readEvents [$ key ],
117+ $ this ->readListeners [$ key ],
118+ $ this ->readRefs [$ key ]
119+ );
107120 }
108121 }
109122
110- private function removeStream ($ stream )
123+ public function removeWriteStream ($ stream )
111124 {
112125 $ key = (int ) $ stream ;
113126
114- if (isset ($ this ->streamEvents [$ key ])) {
115- $ this ->streamEvents [$ key ]->free ();
116-
127+ if (isset ($ this ->writeEvents [$ key ])) {
128+ $ this ->writeEvents [$ key ]->free ();
117129 unset(
118- $ this ->streamFlags [$ key ],
119- $ this ->streamEvents [$ key ],
120- $ this ->readListeners [$ key ],
130+ $ this ->writeEvents [$ key ],
121131 $ this ->writeListeners [$ key ],
122- $ this ->streamRefs [$ key ]
132+ $ this ->writeRefs [$ key ]
123133 );
124134 }
125135 }
@@ -175,7 +185,7 @@ public function run()
175185 $ flags = EventBase::LOOP_ONCE ;
176186 if (!$ this ->running || !$ this ->futureTickQueue ->isEmpty ()) {
177187 $ flags |= EventBase::LOOP_NONBLOCK ;
178- } elseif (!$ this ->streamEvents && !$ this ->timerEvents ->count ()) {
188+ } elseif (!$ this ->readEvents && ! $ this -> writeEvents && !$ this ->timerEvents ->count ()) {
179189 break ;
180190 }
181191
@@ -207,64 +217,6 @@ private function scheduleTimer(TimerInterface $timer)
207217 $ event ->add ($ timer ->getInterval ());
208218 }
209219
210- /**
211- * Create a new ext-event Event object, or update the existing one.
212- *
213- * @param resource $stream
214- * @param integer $flag Event::READ or Event::WRITE
215- */
216- private function subscribeStreamEvent ($ stream , $ flag )
217- {
218- $ key = (int ) $ stream ;
219-
220- if (isset ($ this ->streamEvents [$ key ])) {
221- $ event = $ this ->streamEvents [$ key ];
222- $ flags = ($ this ->streamFlags [$ key ] |= $ flag );
223-
224- $ event ->del ();
225- $ event ->set ($ this ->eventBase , $ stream , Event::PERSIST | $ flags , $ this ->streamCallback );
226- } else {
227- $ event = new Event ($ this ->eventBase , $ stream , Event::PERSIST | $ flag , $ this ->streamCallback );
228-
229- $ this ->streamEvents [$ key ] = $ event ;
230- $ this ->streamFlags [$ key ] = $ flag ;
231-
232- // ext-event does not increase refcount on stream resources for PHP 7+
233- // manually keep track of stream resource to prevent premature garbage collection
234- if (PHP_VERSION_ID >= 70000 ) {
235- $ this ->streamRefs [$ key ] = $ stream ;
236- }
237- }
238-
239- $ event ->add ();
240- }
241-
242- /**
243- * Update the ext-event Event object for this stream to stop listening to
244- * the given event type, or remove it entirely if it's no longer needed.
245- *
246- * @param resource $stream
247- * @param integer $flag Event::READ or Event::WRITE
248- */
249- private function unsubscribeStreamEvent ($ stream , $ flag )
250- {
251- $ key = (int ) $ stream ;
252-
253- $ flags = $ this ->streamFlags [$ key ] &= ~$ flag ;
254-
255- if (0 === $ flags ) {
256- $ this ->removeStream ($ stream );
257-
258- return ;
259- }
260-
261- $ event = $ this ->streamEvents [$ key ];
262-
263- $ event ->del ();
264- $ event ->set ($ this ->eventBase , $ stream , Event::PERSIST | $ flags , $ this ->streamCallback );
265- $ event ->add ();
266- }
267-
268220 /**
269221 * Create a callback used as the target of timer events.
270222 *
0 commit comments