Lockless implementation of add_callback#1876
Conversation
|
I've stress-tested this PR with the following script: https://gist.github.com/pitrou/6a89c8563599beccb1763f27951af416 |
|
Also see previous discussion in #1875. |
| f.close() | ||
| except IOError: | ||
| # Yield to another thread | ||
| time.sleep(1e-3) |
There was a problem hiding this comment.
Is this long enough to avoid the Beazley Effect in Python 2 on multicore? That is, is there a danger that this same thread will reacquire the GIL without actually letting another thread run?
There was a problem hiding this comment.
Unless many non-Python threads are competing for the CPU, yes. We cannot guarantee this approach will always work, but it reasonably should.
| self._callbacks.append(functools.partial( | ||
| stack_context.wrap(callback), *args, **kwargs)) | ||
| # If we're on the IOLoop's thread, we don't need to wake anyone. | ||
| pass |
There was a problem hiding this comment.
This seems distracting, could you merge this explanation with the previous comment block and delete the "else" branch?
|
I like this a lot and would vote for merging. |
|
LGTM. The main purpose of the lock was to avoid unnecessary calls to the waker, but that predated the introduction of the thread.ident check. This change will make cross-thread add_callbacks slightly slower since every call will need to write to the waker, but that seems like a good tradeoff to get rid of the locking in the single-thread case. |
Fixes #1874.