Trying to wrap my head around futures and coroutines

MRAB python at mrabarnett.plus.com
Mon Jan 6 21:22:22 EST 2014


On 2014-01-07 00:56, Skip Montanaro wrote:
> I've been programming for a long while in an event&callback-driven
> world. While I am comfortable enough with the mechanisms available
> (almost 100% of what I do is in a PyGTK world with its signal
> mechanism), it's never been all that satisfying, breaking up my
> calculations into various pieces, and thus having my algorithm scattered
> all over the place.
>
> So, I'm looking for a little guidance. It seems to me that futures,
> coroutines, and/or the new Tulip/asyncio package might be my salvation,
> but I'm having a bit of trouble seeing exactly how that would work. Let
> me outline a simple hypothetical calculation. I'm looking for ways in
> which these new facilities might improve the structure of my code.
>
> Let's say I have a dead simple GUI with two buttons labeled, "Do A" and
> "Do B". Each corresponds to executing a particular activity, A or B,
> which take some non-zero amount of time to complete (as perceived by the
> user) or cancel (as perceived by the state of the running system - not
> safe to run A until B is complete/canceled, and vice versa). The user,
> being the fickle sort that he is, might change his mind while A is
> running, and decide to execute B instead. (The roles can also be
> reversed.) If s/he wants to run task A, task B must be canceled or
> allowed to complete before A can be started. Logically, the code looks
> something like (I fear Gmail is going to destroy my indentation):
>
> def do_A():
> when B is complete, _do_A()
> cancel_B()
>
> def do_B():
> when A is complete, _do_B()
> cancel_A()
>
> def _do_A():
> do the real A work here, we are guaranteed B is no longer running
>
> def _do_B():
> do the real B work here, we are guaranteed A is no longer running
>
> cancel_A and cancel_B might be no-ops, in which case they need to start
> up the other calculation immediately, if one is pending.
>
> This is pretty simple execution, and if my job was this simple, I'd
> probably just keep doing things the way I do now, which is basically to
> catch a "complete" or "canceled" signal from the A and B tasks and
> execute the opposite task if it's pending. But it's not this simple. In
> reality there are lots of, "oh, you want to do X? You need to make sure
> A, B, and C are not active." And other stuff like that.
>
[snip]
Do you really need to use futures, etc?

What you could do is keep track of which tasks are active.

When the user clicks a button to start a task, the task checks whether
it can run. If it can run, it starts the real work. On the other hand,
if it can't run, it's set as the pending task.

When a task completes or is cancelled, if there is a pending task, that
task is unset as the pending task and retried; it'll then either start
the real work or be set as the pending task again.




More information about the Python-list mailing list