[Stackless] Invitation to Present at PyCon 2007
Andrew Dalke
dalke at dalkescientific.com
Tue Oct 31 19:04:53 CET 2006
Richard Tew wrote:
> As someone who hasn't used threading much, I find linkage
> between threading and what Stackless has to taint Stackless
> with a feeling of complexity.
Hmm. But as someone who has used threads, all I really use
from them is "make new thread" and Queue.Queue. That is,
tasklet and a channel. Okay, and an occasional lock.
> For me tasklets are just some simple utility which lifts
> functions up a level, enabling cleaner, more readable code
> and in conjunction with channels, less boilerplate. That it
> is a simpler form of threading is something that never
> comes to mind.
Then we have different mental models of threads/stackless. I
don't follow what you mean by "up a level", etc. Do you mean
that functions are more .. hefty? exeuction-oriented? more
like a process? more Erlang like, if I understand Erlang.
What boilerplate is saved?
BTW, here's a quick throw together of the mapping I have in my head
concerning the stackless API. There are differences. Eg, channel
isn't exactly a Queue.Queue. I would need P/V semaphores to get the
counts right for "balance", I need some solution to make things
non-preemptive, handle correct scheduling, and more. But it's
mostly busywork. The result would take a lot more resources and be
a lot slower (stackless does user-space scheduling and is, I think,
quicker at doing the scheduling than a preemptive scheduler.)
# Hack to get some of the Stackless primitives kinda working with
threads
# Not to be used for real code.
import threading
import Queue
_unscheduled_tasks = set()
def schedule(task):
if not task.running:
task.run()
def run():
_unsched = list(_unscheduled_tasks)
_unscheduled_tasks.clear()
for task in _unsched:
task.run()
class tasklet_thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.q = Queue.Queue(1)
def run(self):
x = self.q.get()
if x is None:
return
f, args, kwargs = x
f(*args, **kwargs)
class tasklet(object):
def __init__(self, f=None):
self.thread = tasklet_thread()
self.thread.start()
self.f = f
self.run_args = ((), {})
self.running = False
_unscheduled_tasks.add(self)
def bind(self, f):
self.f = f
def setup(self, *args, **kwargs):
self.run_args = args, kwargs
def __call__(self, *args, **kwargs):
self.run_args = args, kwargs
return self
def run(self):
if self.running:
raise AssertionError("already running")
else:
_unscheduled_tasks.remove(self)
self.running = True
self.thread.q.put( (self.f, self.run_args[0], self.run_args[1])
)
class channel(object):
def __init__(self):
self.q = Queue.Queue(1)
def send(self, x):
self.q.put(x)
def receive(self):
return self.q.get()
####
def aCallable(value):
print "aCallable:", value
task = tasklet(aCallable)
task.setup("Inline using setup")
task.run()
#####
import __main__ as stackless
def Sending(channel):
print "sending"
channel.send("foo")
ch=stackless.channel()
task=stackless.tasklet(Sending)(ch)
stackless.schedule(task)
def Receiving(channel):
print "receiving"
print channel.receive()
task2=stackless.tasklet(Receiving)(ch)
stackless.schedule(task2)
stackless.run()
#print "Channel balance is ",ch.balance
####
the output is the expected
aCallable: Inline using setup
sending
receiving
foo
> But that is probably just me. The abstract sounds great
> and right on target ignoring that (as any sane person
> probably should). Especially given the impending or
> passed deadline :-)
5 hours until localtime midnight. 10 hours or so until US-EST
midnight. Only impending. :)
Andrew
dalke at dalkescientific.com
_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless
More information about the Stackless
mailing list