Re: New stackless proposal

Lenard Lindstrom <[email protected]>
Newsgroups gmane.comp.lang.prothon.user
Message-ID <Mahogany-0.66.0-4294528931-20040710-135441.00@pop3.norton.antivirus>
On Thu, 8 Jul 2004 15:03:08 -0700 Mark Hahn <[email protected]> wrote:

> http://prothon.org/wiki?pagename=StacklessLanguageFeatures
> 
If a prothon thread must be declared using a "defInit" or "after" section
of a function definition then there is no need for an "thread" keyword.
Prothon thread declarations will likely outnumber OS thread declarations,
especially when generators are prothon threads. So a "thread" statement
that creates OS thread objects is not much of a convenience.

The yield statement/function need not be a direct ThreadMgr method
invocation. Simply define a built-in function as follows:

def yield(value=None, to=otherThread):   # what is otherThread?
    return curThreadMgr.yield(value, to)

Having yield somehow know that it is on the right of an assignement is
quirky given this feature shows up nowhere else in the language. Instead
I using the "to" parameter to determine whether of not a yield is a send
or receive. Define yield's paramenters as follows:

(value=None, to=None)

When "to" is specified then the yield is a send; when to is
None, the default, the yield is a receive. If it is desired
to use a thread manager as a pool of server threads then a
ThreadMgr.AnyThread() method can be used as the yield's "to"
argument to allow a message to be sent to the next free
thread in the pool, or a randomly chosen thread for a simulation.

I do not know about the empty yield case. Usually this is handled
with a sleep(0) in other languages. Or the ThreadMgr prototype can
have a special method for this case. It will not occur often.

Summing up, an OS thread declaration:

def thread1(seconds):
    defInit: thread1 = OSThread(thread1)
    print("thread1 is running")
    Sleep(seconds * 1.0)
    print("thread1 is stopping")

A prothon thread:

def thread1(seconds):
    defInit: thread1 = Thread(thread1)
    print("thread1 is running")
    Sleep(seconds * 1.0)
    print("thread1 is stopping")

A generator:

def genOdd(n):
    defInit: genOdd = Thread(genOdd)
    for i in n:
        if i % 2:
            yield(i)

Finally, this is how I defined a Tasklet generator class in Stackless
Python along with an example usage. Note that special care was taken to
handle the case where the generator function never does a yield:

import stackless

class Iterator(object):

    def __init__(self, *args, **kwds):
        self.isfinished = False
        self.nextitem = stackless.channel()
        def taskbody(*args, **kwds):
            self.body(*args, **kwds)
            self.nextitem.send_exception(StopIteration)
        self.task = stackless.tasklet(taskbody)
        self.task.setup(*args, **kwds)
        self.task.run()

    def body(self, *args, **kwds):
        return

    def Yield(self, value):
        self.nextitem.send(value)

    def __iter__(self):
        return self

    def next(self):
        if self.isfinished:
            raise StopIteration
        try:
            return self.nextitem.receive()
        except StopIteration:
            self.isfinished = True
            raise

class Fib(Iterator):
    def body(self, n):
        sum, prev = 1, 0
        for i in range(n):
            self.Yield(sum)
            sum, prev = sum + prev, sum

if __name__ == '__main__':
    # Does at least 1 yield
    for f in Fib(7):
        print f
    # Special case: no yield
    for f in Fib(0):
        print f


Lenard Lindstrom
<[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.