decentfox / tulipcore

An alternative Gevent core loop implementation with asyncio
Other
134 stars 12 forks source link

watcher.ref simulation is incomplete when mixing with asyncio code #5

Open fantix opened 10 years ago

fantix commented 10 years ago

Original Gevent core loop is made of libev, whose event loop will automatically stop when a reference count reaches zero (normally means there's no active/pending watchers, check for ev_ref), some Gevent API depends on this feature, e.g. gevent.wait().

tulipcore simulated this behavor, but it caused some side effects when normal asyncio code is mixed in - they are not aware of the tulipcore-only reference count thing and therefore receives unexpected loop exits. For example:

@asyncio.coroutine
def test():
    yield from asyncio.sleep(2)
    print("this line should be printed")
    loop.stop()
asyncio.tasks.async(test())

gevent.spawn(gevent.sleep, 1)
try:
    gevent.get_hub().switch()
except gevent.hub.LoopExit:
    pass

but the line is never printed.

It is reasonable to turn off the reference counting if the client code never uses those refcount-triggered APIs. Or client code may choose to manually increase and decrease the refcount at gevent.get_hub().loop by calling loop.increase_ref() or loop.decrease_ref().