agronholm / pythonfutures

Backport of the concurrent.futures package to Python 2.6 and 2.7
Other
232 stars 51 forks source link

Each time set_result/set_exception/set_exception_info is invoked, done callbacks are executed repeatedly #86

Closed tim-chow closed 5 years ago

tim-chow commented 5 years ago

below is an example:

from concurrent.futures import Future

def done_callback(f):
    print("done callback is invoked")

f = Future()
f.add_done_callback(done_callback)
f.set_result('first set')
f.set_result('second set')

the output is:

done callback is invoked
done callback is invoked

I think that future can only be set once, it's better. and in this case, done callbacks will be invoked only once.

class Future(object):
    ...
    def set_result(self, result):
        """Sets the return value of work associated with the future.
        Should only be used by Executor implementations and unit tests.
        """
        with self._condition:
            if self.done():
                return
            ...

    def set_exception_info(self, exception, traceback):
        """Sets the result of the future as being the given exception
        and traceback.
        Should only be used by Executor implementations and unit tests.
        """
        with self._condition:
            if self.done():
                return
            ...
agronholm commented 5 years ago

This is how it works in the upstream implementation (even in 3.7). This is just a backport so I'm not going to do anything about this.