@@ -145,81 +145,88 @@ def create_task(coro):
145
145
_task_queue .push (t )
146
146
return t
147
147
148
-
149
148
# Keep scheduling tasks until there are none left to schedule
150
149
def run_until_complete (main_task = None ):
151
150
global cur_task
152
151
excs_all = (CancelledError , Exception ) # To prevent heap allocation in loop
153
152
excs_stop = (CancelledError , StopIteration ) # To prevent heap allocation in loop
154
- while True :
155
- # Wait until the head of _task_queue is ready to run
156
- dt = 1
157
- while dt > 0 :
158
- dt = - 1
153
+ try :
154
+ _io_queue .wait_io_event (0 )
155
+ while True :
156
+ # Wait until the head of _task_queue is ready to run
159
157
t = _task_queue .peek ()
160
158
if t :
161
159
# A task waiting on _task_queue; "ph_key" is time to schedule task at
162
- dt = max (0 , ticks_diff (t .ph_key , ticks ()))
160
+ dt = ticks_diff (t .ph_key , ticks ())
161
+ if dt > 0 :
162
+ _io_queue .wait_io_event (dt )
163
163
elif not _io_queue .map :
164
164
# No tasks can be woken so finished running
165
165
return
166
- # print('(poll {})'.format(dt), len(_io_queue.map))
167
- _io_queue .wait_io_event (dt )
168
-
169
- # Get next task to run and continue it
170
- t = _task_queue .pop ()
171
- cur_task = t
172
- try :
173
- # Continue running the coroutine, it's responsible for rescheduling itself
174
- exc = t .data
175
- if not exc :
176
- t .coro .send (None )
177
166
else :
178
- # If the task is finished and on the run queue and gets here, then it
179
- # had an exception and was not await'ed on. Throwing into it now will
180
- # raise StopIteration and the code below will catch this and run the
181
- # call_exception_handler function.
182
- t .data = None
183
- t .coro .throw (exc )
184
- except excs_all as er :
185
- # Check the task is not on any event queue
186
- assert t .data is None
187
- # This task is done, check if it's the main task and then loop should stop
188
- if t is main_task :
189
- if isinstance (er , StopIteration ):
190
- return er .value
191
- raise er
192
- if t .state :
193
- # Task was running but is now finished.
194
- waiting = False
195
- if t .state is True :
196
- # "None" indicates that the task is complete and not await'ed on (yet).
197
- t .state = None
198
- elif callable (t .state ):
199
- # The task has a callback registered to be called on completion.
200
- t .state (t , er )
201
- t .state = False
202
- waiting = True
167
+ _io_queue .wait_io_event (- 1 )
168
+
169
+ # Get next task to run and continue it
170
+ t = _task_queue .pop ()
171
+ cur_task = t
172
+ try :
173
+ # Continue running the coroutine, it's responsible for rescheduling itself
174
+ exc = t .data
175
+ if not exc :
176
+ t .coro .send (None )
203
177
else :
204
- # Schedule any other tasks waiting on the completion of this task.
205
- while t .state .peek ():
206
- _task_queue .push (t .state .pop ())
178
+ # If the task is finished and on the run queue and gets here, then it
179
+ # had an exception and was not await'ed on. Throwing into it now will
180
+ # raise StopIteration and the code below will catch this and run the
181
+ # call_exception_handler function.
182
+ t .data = None
183
+ t .coro .throw (exc )
184
+ except excs_all as er :
185
+ # Check the task is not on any event queue
186
+ assert t .data is None
187
+ # This task is done, check if it's the main task and then loop should stop
188
+ if t is main_task :
189
+ if isinstance (er , StopIteration ):
190
+ return er .value
191
+ raise er
192
+ if t .state :
193
+ # Task was running but is now finished.
194
+ waiting = False
195
+ if t .state is True :
196
+ # "None" indicates that the task is complete and not await'ed on (yet).
197
+ t .state = None
198
+ elif callable (t .state ):
199
+ # The task has a callback registered to be called on completion.
200
+ t .state (t , er )
201
+ t .state = False
207
202
waiting = True
208
- # "False" indicates that the task is complete and has been await'ed on.
209
- t .state = False
210
- if not waiting and not isinstance (er , excs_stop ):
211
- # An exception ended this detached task, so queue it for later
212
- # execution to handle the uncaught exception if no other task retrieves
213
- # the exception in the meantime (this is handled by Task.throw).
214
- _task_queue .push (t )
215
- # Save return value of coro to pass up to caller.
216
- t .data = er
217
- elif t .state is None :
218
- # Task is already finished and nothing await'ed on the task,
219
- # so call the exception handler.
220
- _exc_context ["exception" ] = exc
221
- _exc_context ["future" ] = t
222
- Loop .call_exception_handler (_exc_context )
203
+ else :
204
+ # Schedule any other tasks waiting on the completion of this task.
205
+ while t .state .peek ():
206
+ _task_queue .push (t .state .pop ())
207
+ waiting = True
208
+ # "False" indicates that the task is complete and has been await'ed on.
209
+ t .state = False
210
+ if not waiting and not isinstance (er , excs_stop ):
211
+ # An exception ended this detached task, so queue it for later
212
+ # execution to handle the uncaught exception if no other task retrieves
213
+ # the exception in the meantime (this is handled by Task.throw).
214
+ _task_queue .push (t )
215
+ # Save return value of coro to pass up to caller.
216
+ t .data = er
217
+ elif t .state is None :
218
+ # Task is already finished and nothing await'ed on the task,
219
+ # so call the exception handler.
220
+ _exc_context ["exception" ] = exc
221
+ _exc_context ["future" ] = t
222
+ Loop .call_exception_handler (_exc_context )
223
+ except BaseException as exc :
224
+ try :
225
+ if main_task :
226
+ main_task .coro .throw (exc )
227
+ except StopIteration :
228
+ pass
229
+ raise
223
230
224
231
225
232
# Create a new task from a coroutine and run it until it finishes
0 commit comments