3
3
4
4
from time import ticks_ms as ticks , ticks_diff , ticks_add
5
5
import sys , select
6
+ from select import POLLIN , POLLOUT
6
7
7
8
# Import TaskQueue and Task, preferring built-in C code over Python code
8
9
try :
@@ -54,7 +55,8 @@ def __next__(self):
54
55
# Use a SingletonGenerator to do it without allocating on the heap
55
56
def sleep_ms (t , sgen = SingletonGenerator ()):
56
57
assert sgen .state is None
57
- sgen .state = ticks_add (ticks (), max (0 , t ))
58
+ now = ticks ()
59
+ sgen .state = ticks_add (now , t ) if t > 0 else now
58
60
return sgen
59
61
60
62
@@ -77,13 +79,13 @@ def _enqueue(self, s, idx):
77
79
entry = [None , None , s ]
78
80
entry [idx ] = cur_task
79
81
self .map [id (s )] = entry
80
- self .poller .register (s , select . POLLIN if idx == 0 else select . POLLOUT )
82
+ self .poller .register (s , POLLIN if idx == 0 else POLLOUT )
81
83
else :
82
84
sm = self .map [id (s )]
83
85
assert sm [idx ] is None
84
86
assert sm [1 - idx ] is not None
85
87
sm [idx ] = cur_task
86
- self .poller .modify (s , select . POLLIN | select . POLLOUT )
88
+ self .poller .modify (s , POLLIN | POLLOUT )
87
89
# Link task to this IOQueue so it can be removed if needed
88
90
cur_task .data = self
89
91
@@ -114,20 +116,20 @@ def wait_io_event(self, dt):
114
116
for s , ev in self .poller .ipoll (dt ):
115
117
sm = self .map [id (s )]
116
118
# print('poll', s, sm, ev)
117
- if ev & ~ select . POLLOUT and sm [0 ] is not None :
119
+ if ev & ~ POLLOUT and sm [0 ] is not None :
118
120
# POLLIN or error
119
121
_task_queue .push (sm [0 ])
120
122
sm [0 ] = None
121
- if ev & ~ select . POLLIN and sm [1 ] is not None :
123
+ if ev & ~ POLLIN and sm [1 ] is not None :
122
124
# POLLOUT or error
123
125
_task_queue .push (sm [1 ])
124
126
sm [1 ] = None
125
127
if sm [0 ] is None and sm [1 ] is None :
126
128
self ._dequeue (s )
127
129
elif sm [0 ] is None :
128
- self .poller .modify (s , select . POLLOUT )
130
+ self .poller .modify (s , POLLOUT )
129
131
else :
130
- self .poller .modify (s , select . POLLIN )
132
+ self .poller .modify (s , POLLIN )
131
133
132
134
133
135
################################################################################
@@ -153,24 +155,36 @@ def run_until_complete(main_task=None):
153
155
global cur_task
154
156
excs_all = (CancelledError , Exception ) # To prevent heap allocation in loop
155
157
excs_stop = (CancelledError , StopIteration ) # To prevent heap allocation in loop
158
+ queue_peek = _task_queue .peek
159
+ queue_pop = _task_queue .pop
160
+ wait_io_event = _io_queue .wait_io_event
156
161
while True :
157
- # Wait until the head of _task_queue is ready to run
158
- dt = 1
159
- while dt > 0 :
160
- dt = - 1
161
- t = _task_queue .peek ()
162
- if t :
163
- # A task waiting on _task_queue; "ph_key" is time to schedule task at
164
- dt = max (0 , ticks_diff (t .ph_key , ticks ()))
165
- elif not _io_queue .map :
166
- # No tasks can be woken so finished running
167
- cur_task = None
168
- return
169
- # print('(poll {})'.format(dt), len(_io_queue.map))
170
- _io_queue .wait_io_event (dt )
162
+ try :
163
+ # Wait until the head of _task_queue is ready to run
164
+ dt = 1
165
+ while dt > 0 :
166
+ dt = - 1
167
+ t = queue_peek ()
168
+ if t :
169
+ # A task waiting on _task_queue; "ph_key" is time to schedule task at
170
+ dt = ticks_diff (t .ph_key , ticks ())
171
+ dt = dt if dt > 0 else 0
172
+ elif not _io_queue .map :
173
+ # No tasks can be woken so finished running
174
+ cur_task = None
175
+ return
176
+ # print('(poll {})'.format(dt), len(_io_queue.map))
177
+ wait_io_event (dt )
178
+ except BaseException as exc :
179
+ try :
180
+ if main_task :
181
+ main_task .coro .throw (exc )
182
+ except StopIteration :
183
+ pass
184
+ raise
171
185
172
186
# Get next task to run and continue it
173
- t = _task_queue . pop ()
187
+ t = queue_pop ()
174
188
cur_task = t
175
189
try :
176
190
# Continue running the coroutine, it's responsible for rescheduling itself
0 commit comments