[Python-ideas] The async API of the future: Twisted and Deferreds

Nick Coghlan ncoghlan at gmail.com
Sat Oct 13 17:46:09 CEST 2012

On Sat, Oct 13, 2012 at 8:52 PM, Itamar Turner-Trauring
<itamar at futurefoundries.com> wrote:
>    def addToCounter():
>         counter.value = counter.value + (yield getResult())

This is buggy code for the reasons you state. However, only improperly
*embedded* yields have this problem, yields that are done in a
dedicated assignment statement are fine:

    def addToCounter():
        result = yield getResult()
        # No race condition here, as we only read the counter *after*
receiving the result
        counter.value = counter.value + result

(You can also make sure they're the first thing executed as part of a
larger expression, but a separate assignment statement will almost
always be clearer)

> In a Deferred callback, on the other hand, you know the only things that are
> going to run are functions you call. In so far as it's possible, what
> happens is under control of one function only. Less pretty, but no potential
> race conditions:
>     def add(result):
>         counter.value = counter.value + result
>     getResult().addCallback(add)

This is not the same code you wrote above in the generator version.
The callback equivalent of the code you wrote is this:

    bound_value = counter.value
    def add(result):
        counter.value = bound_value + result

The generator version isn't magic, people still need to know what
they're doing to properly benefit from the cooperative multithreading.


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list