Yury Selivanov added the comment:

> Yury, what do you think of this yourself? Maybe you can explain it better
than Ilya?

TBH, I don't fully understand Ilya's case with threads, synchronous coroutines, 
possible deadlocks etc.  So I'll just explain what I would want out of this.

I don't like a few aspects of the current design of 'get_event_loop'.  Mainly 
because it creates an event loop implicitly, or it can just fail with a 
RuntimeError under some conditions.  When one has a few event loops, implicitly 
called 'get_event_loop' from Future and other asyncio functions won't work 
correctly.  IMO, this is something that we at least should try to fix (even 
though it's not an idiomatic use case for asyncio).

I now think that we don't need a new function for getting the currently running 
event loop.  Instead we can try to improve the `get_event_loop()` function a 
little.

The core idea is to add a thread-local object `running_loop`, which will point 
to the currently running event loop in the current thread.  And `Loop._run` 
method will set/reset a reference to the loop to `running_loop`.

`get_event_loop()` will then try to use the `running_loop` object first, and if 
nothing is there, fall back to its current implementation.

Now, this is a point where everything becomes complicated. To quote 
myself,--"Yes, the patch part is easy",--I don't think it is that easy anymore 
;)

Currently, event loops are decoupled from policies.  This means that we can't 
make loops to use some hidden shared thread-local object (`running_loop`) that 
policies and loops will work with.  There has to be another new public policy 
APIs that loops will use, for instance: 'set_running_event_loop()'.  This won't 
be the first case of event loop policy APIs being called from event loops -- 
another example is the `get_child_watcher` method.

With this new method, `Loop._run` will then look like this:

  def _run(self):
      policy = get_event_loop_policy()
      policy.set_running_event_loop(self)
      try:
         ... # current Loop._run implementation
      finally:
          policy.set_running_event_loop(None)

`policy.set_running_event_loop` call would raise a RuntimeError if it's called 
if another event loop is currently running.

And the `get_event_loop()` function will look like this:

  def get_event_loop():
      policy = get_event_loop_policy()
      loop = policy._get_running_event_loop()
      if loop is not None:
          return loop
      # ... current get_event_loop implementation

So it all boils down to:

1. Adding a new policy API 'set_running_event_loop'.

2. Updating 'get_event_loop' to return the currently running event loop if it's 
available, or else resorting to its current behaviour.

With this change it will be completely safe to use "get_event_loop" from 
running coroutines or just about any code that runs in a context of an event 
loop.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue26969>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to