Skip to content

Commit 0432809

Browse files
author
taras
committed
Experimental Future.eager_set_result
1 parent 837166f commit 0432809

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

Lib/asyncio/futures.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class Future:
7272

7373
__log_traceback = False
7474

75+
_eager_result = False
76+
7577
def __init__(self, *, loop=None):
7678
"""Initialize the future.
7779
@@ -168,6 +170,30 @@ def cancel(self, msg=None):
168170
self.__schedule_callbacks()
169171
return True
170172

173+
def __execute_callbacks(self):
174+
callbacks = self._callbacks[:]
175+
if not callbacks:
176+
return
177+
178+
self._callbacks[:] = []
179+
for callback, ctx in callbacks:
180+
# TODO: run_in_context
181+
try:
182+
callback(self)
183+
except BaseException as exc:
184+
cb = format_helpers._format_callback_source(
185+
callback, (self,),
186+
debug=self._loop.get_debug())
187+
msg = f'Exception in callback {cb}'
188+
context = {
189+
'message': msg,
190+
'exception': exc,
191+
'handle': self,
192+
}
193+
if self._source_traceback:
194+
context['source_traceback'] = self._source_traceback
195+
self._loop.call_exception_handler(context)
196+
171197
def __schedule_callbacks(self):
172198
"""Internal: Ask the event loop to call all callbacks.
173199
@@ -270,6 +296,19 @@ def set_result(self, result):
270296
self._state = _FINISHED
271297
self.__schedule_callbacks()
272298

299+
def eager_set_result(self, result):
300+
"""Mark the future done and set its result.
301+
302+
If the future is already done when this method is called, raises
303+
InvalidStateError.
304+
"""
305+
if self._state != _PENDING:
306+
raise exceptions.InvalidStateError(f'{self._state}: {self!r}')
307+
self._result = result
308+
self._state = _FINISHED
309+
self._eager_result = True
310+
self.__execute_callbacks()
311+
273312
def set_exception(self, exception):
274313
"""Mark the future done and set an exception.
275314

Lib/asyncio/tasks.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,10 @@ def __wakeup(self, future):
370370
# Python eval loop would use `.send(value)` method call,
371371
# instead of `__next__()`, which is slower for futures
372372
# that return non-generator iterators from their `__iter__`.
373-
self.__step()
373+
if future._eager_result:
374+
self.__eager_start()
375+
else:
376+
self.__step()
374377
self = None # Needed to break cycles when an exception occurs.
375378

376379

0 commit comments

Comments
 (0)