[Stackless] tasklet.set_atomic

Kristján Valur Jónsson kristjan at ccpgames.com
Mon Apr 2 12:00:34 CEST 2012


Hi there.
Working on stuff to spawn off work for actual worker threads, I realized that there was no good way to to synchronize between two tasklets on two threads.
That is to say:
When sending data between two tasklet on the same thread, usually it is sufficient to use tasklet.set_atomic() to disable tasklet interrupts (that rarely happen anyway, only when using stackless.run() with non-zero values) to ensure atomicity.
For example, this code from stacklesslib.locks.Event:

def wait(self, timeout=None):
        with atomic():
            if self._is_set:
                return True
            lock_channel_wait(self.chan, timeout)
            return self._is_set

    def set(self):
        with atomic():
            self._is_set = True
            for i in range(-self.chan.balance):
                self.chan.send(None)

the atomic() context manager is used here to ensure consistency of state.

However, I realized that when using the Event to set or wait for events between threads, that is, when one tasklet was waiting and another, on a different thread, was setting the event, this approach doesn't work.  A thread switch can happen anywhere, for example, in wait after the initial _is_set test, but before the wait, causing a lost wakeup bug.

The solution is to make "atomic" also suspend automatic thread switching while in progress.  I've implemented this for our patched CCP version of stackless and wanted to mention this here before rolling it into the distribution.  One thing that only slightly worries me is that this approach assumes a GIL-like implementation.  But stackless being so specialized, we are unlikely to see a non-GIL version any time soon :)

K
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.stackless.com/pipermail/stackless/attachments/20120402/ae1284af/attachment.html>


More information about the Stackless mailing list