I have some parsing application and it basically do the following
- Adds
start()
method to the IOLoop as a callback to call on the next iteration start()
calls another function, let's call itget_input()
get_input()
is a coroutine which fetches some data over the net, then schedules another coroutine,process_input()
, by adding it asstart()
was added in the first step.get_input()
also checks some condition which depends on fetched data and may schedule itself with adjusted arguments
Now, after this condition renders False
I know that there won't be any new input items to process.
But how do I know that there are no Futures of get_input()
and process_input()
which are still unresolved?
I suppose this could be solved by implementing a kind of counter, which is incremented every time process_input()
is called and decrementing after it is resolved
But if there is a chain of different coroutines? How can I track their state so that if I stop IOLoop, no tasks will die before they get resolved?
Maybe, there should be some kind of hierarchical counting...
edit:
2 @dano
OK, I see now... I was inattentive. You really do not block as its own call is inside this list
But!
- Such organization reqires that only
yield
construction must be used, noadd_callback
as otherwise we lose "waiting" concept - The recursion level grows.. Mmm, dunno if it's too bad
What I came up with today is "metafuture"
I create a bare Future()
object.
I decorate every @coroutine
-enabled method with my decorator, which increments counter field in "metafuture" and adds a custom done callback to their futures, that should decrement it.
When it reaches zero, "metafuture" resolves by calling set_result(None)
THere is also a IOLoop callback that yields exactly that metafuture:
@coroutine
def wait_for_complete(self):
yield self._input_data_collected
yield self._all_futures_resolved
self.complete()
So after that we know no futures are pending. THat's a hard way like manually implementing refcounting but it covers IOLoop.add_callback()
way of adding tasks as well
IOLoop.stop()
with some futures still unresolved, they won't be processed. So I assume that I should manually track the moment when all processing is done and thenstop()
it – OjomioIOLoop.stop()
won't wait for outstanding work to finish. However, you its possible you can organize your application so that it automatically exits once it's done doing its work. It's hard to say without actually being able to see how your program is structured, though. – dano