[Stackless] Santa concurrency problem

Brian Zimmer bzimmer at ziclix.com
Tue Mar 27 03:56:42 CEST 2007


I just want to make sure I understand the ramifications of adding 
sleep() to the main thread.  If I have the following code I will be 
forced to wait until I come out of the time.sleep regardless of 
activity on the channel.  This sleep implementation works only because 
of the particular use case of the Santa problem, correct?  I can type 
all day long into stdin but the tasklet is only going to display a 
character every five seconds.

Is there a tasklet-safe sleep that the default scheduler can handle 
appropriately?  Also, is mixing threads and tasklets this way meant to 
be avoided?

thanks for answering, brian

-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

import sys
import time
import thread
import stackless

class Sleep:
   def __init__(self):
     self.sleepingTasklets = []
     stackless.tasklet(self.ManageSleepingTasklets)()

   def Sleep(self, secondsToWait):
     channel = stackless.channel()
     endTime = time.time() + secondsToWait
     self.sleepingTasklets.append((endTime, channel))
     self.sleepingTasklets.sort()
     # Block until we get sent an awakening notification.
     channel.receive()

   def ManageSleepingTasklets(self):
     while True:
       if len(self.sleepingTasklets):
         endTime = self.sleepingTasklets[0][0]
         if endTime <= time.time():
           channel = self.sleepingTasklets[0][1]
           del self.sleepingTasklets[0]
           # We have to send something, but it doesn't matter what as it 
is not used.
           channel.send(None)
         elif stackless.runcount == 1:
           # We are the only tasklet running, the rest are blocked on 
channels sleeping.
           # We can call time.sleep until the first awakens to avoid a 
busy wait.
           delay = endTime - time.time()
           #print "wait delay", delay
           time.sleep(delay)
       stackless.schedule()

sleep = Sleep()

def ReadOne(ch):
   while True:
     n = sys.stdin.read(1)
     if n == "\n": continue
     print "got '%s'" % (n)
     ch.send(n)

def ListenOne(ch):
   while True:
     sleep.Sleep(5)
     c = ch.receive()
     print "received '%s'" % (c)

channel = stackless.channel()
stackless.tasklet(ListenOne)(channel)

thread.start_new_thread(ReadOne, (channel,))
stackless.run()

-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

On Mar 26, 2007, at 02:25 PM, Carlos Eduardo de Paula wrote:

> I noticed it too when updating the project examples, they have been
> updated in examples project repository, the Santa one has been added
> and the prod-con ones uses the new ManageSleepTasklets function.
>
> Carlos
>
> Visit Stackless Examples Project
> http://code.google.com/p/stacklessexamples/
> Stackless Python - www.stackless.com
>
>
> On 3/26/07, Santiago Gala <sgala at apache.org> wrote:
>> El lun, 26-03-2007 a las 20:20 +0000, Richard Tew escribió:
>>> On 3/26/07, Carlos Eduardo de Paula <carlosedp at gmail.com> wrote:
>>>> What is taking a hit on CPU is the ManageSleepingTasklets tasklet, 
>>>> it
>>>> gets that usage in its loop.
>>>>
>>>> What I can do for throttling the cpu usage is put a 
>>>> time.sleep(0.001)
>>>> inside the while loop, with it we can have a decent precision on 
>>>> time
>>>> (1 milisecond) and having the CPU at low usage...
>>>>
>>>> Maybe Richard can help us out about a cleaner solution on this...
>>>
>>> The Sleep code here is copied from the simple example I wrote.
>>> Unfortunately like most low level Stackless examples it only
>>> really serves to demonstrate what you can do, now how you should
>>> do it in all cases.  In the case here, since it is responsible for
>>> awakening tasklets and if it knows none are waking anytime
>>> soon, it is safe to avoid a busy wait by adapting the code to
>>> use time.sleep for the interim.
>>>
>>
>> Cool, this code makes it work with unnoticeable load, while remaining
>> performant (depending on the sleep time of the workers).
>>
>> The only minor nit: I found delay can be negative, so I got an
>> exception. Using max(delay,0) solved it.
>>
>> Regards
>> Santiago
>>
>>>   def ManageSleepingTasklets(self):
>>>     while True:
>>>       if len(self.sleepingTasklets):
>>>         endTime = self.sleepingTasklets[0][0]
>>>         if endTime <= time.time():
>>>           channel = self.sleepingTasklets[0][1]
>>>           del self.sleepingTasklets[0]
>>>           # We have to send something, but it doesn't matter what as
>>> it is not used.
>>>           channel.send(None)
>>>         elif stackless.runcount == 1:
>>>           # We are the only tasklet running, the rest are blocked on
>>> channels sleeping.
>>>           # We can call time.sleep until the first awakens to avoid 
>>> a busy wait.
>>>           delay = endTime - time.time()
>>>           print "wait delay", delay
>>>           time.sleep(delay)
>>>       stackless.schedule()
>>>
>>> Cheers,
>>> Richard.
>>>
>>> _______________________________________________
>>> Stackless mailing list
>>> Stackless at stackless.com
>>> http://www.stackless.com/mailman/listinfo/stackless
>>
>>
>> _______________________________________________
>> Stackless mailing list
>> Stackless at stackless.com
>> http://www.stackless.com/mailman/listinfo/stackless
>
> _______________________________________________
> Stackless mailing list
> Stackless at stackless.com
> http://www.stackless.com/mailman/listinfo/stackless
>


_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless



More information about the Stackless mailing list