stackless proposal (from WIKI)

"Mark Hahn" <[email protected]>
Newsgroups gmane.comp.lang.prothon.user
Message-ID <[email protected]>
This is the stackless proposal as it is on the wiki.  I will try to
summarize it on the wiki to something more succinct.  I might also add some
ideas to it.  If I do I will announce it as new here.
-------------------------------------

Mark Hahn Wrote:

I'll start the discussion by giving some links to previous messages
containing my proposal, Christian's comments when he first joined our list,
and Paul's thread about continuations.  Read these over and give your ideas
for implementing stackless features in Prothon.

* This is the last actual stackless proposal (before Christian joined us):
http://www.prothon.org/pipermail/prothon-user/2004-June/002124.html

* This is a thread-kill proposal.  Later I found out that Ada works the same
way so I assume this will be approved by everyone without argument:
http://www.prothon.org/pipermail/prothon-user/2004-June/002125.html

* This is the thread when Christian first joined our list.  It covers
several topics but it discusses stackless also.
http://www.prothon.org/pipermail/prothon-user/2004-June/002146.html

<continuation section snipped>

----
Lenard Lindstrom Wrote:

This is very tentative:

Declaring a thread or generator:

thread <name> (arg, ...):
    <body>

An enhanced yield statement can return a value.

A generator example:

<verbatim>
thread fib(n):
    """Return first n Fibonacci numbers"""
    sum, prev = 1, 0
    for i in n:
        yield sum
        sum, prev = sum + prev, sum

iter = fib(5)
for i in iter:
    print(i)
</verbatim>

In this case thread just replaces the gen keyword.

A more general example:

<verbatim>
thread handlerA(obj):
    print(yield obj)
    print(rval)

thread handlerB(obj):
    print(A(obj))

A = handlerA.thread()
A.start(1)            # Enters wait state on yield
B = handlerB.thread()
B.start(2)
#    May print
# 1
# 2
#    or
# 2
# 1
</verbatim>

Explicit calls on active thread objects take precidence over yield
to avoid deadlocks.
----
Mark Hahn Wrote:

> thread <name> (arg, ...):
>     <body>

I like this for replacing the OS thread statement and specifying the new
soft threads.  I hated the params argument in the old OS hard thread
constructor.  I'm not sure how we can specify what type of thread we are
making though.  Maybe we can have two different keywords.

> In this case thread just replaces the gen keyword.

Cool idea.  You've accomplished what you said you wanted to do about merging
gen and threads.  I will give some thought to see if there is any problem
with such a simple idea.

How about an OSThread (osThread?) keyword and a thread keyword.  It would be
weird to have a camelcase keyword but I cannot think of any other.

I've been thinking lately about the name for the gate (my old name) aka
channel (Christian's name).  Christian pointed out the ideal-meaning but
impractical name rendezvous.  I would like to suggest "coupler" since this
is an object that maintains a queue of threads waiting for a mate to be
coupled with and then it pairs them off.  You can thank my wife for this
obscene idea.

I think the coupler should just be constructed with a normal call_ and
init_.  Any fine-tuning of the scheduling would be done by setting
attributes of the coupler.
----
Laurent Dube Wrote:

 > Lenard Lindstrom wrote:
 > ...
 > > In this case thread just replaces the gen keyword.
 >
 > Cool idea.  You've accomplished what you said you wanted to do about
merging
 > gen and threads.  I will give some thought to see if there is any problem
 > with such a simple idea.

I like this. Do you remember my late-night take on simulation two weeks ago,
when I was making a case for

 > One object, one thread. Autonomous objects, you could say.
----
Lenard:
> I think the coupler should just be constructed with a normal call_ and
> init_.  Any fine-tuning of the scheduling would be done by setting
> attributes of the coupler.

Sure. If there were some way to tie this "coupler" into a generator then
the "yield" keyword can go away. Maybe creating a generator instance
causes a "yield" coupler object to be created that is accessed through
the call stack:

<verbatim>
thread fib(n):
    sum, prev = 1, 0
    for i in n:
        caller.yield.send(sum)
        sum, prev = sum + prev, sum
</verbatim>
----
Mark:
The purpose of a coupler is to allow one thread to switch to another thread
by connecting them together, but a generator only involves one thread
calling another in a restartable way. I don't think a coupler would be
involved with a generator.  The yield operation is specific to a generator
and I don't see any problem keeping it the way it is.
----
Lenard:
!Clarification and minor changes to my original suggestion

Calling a _thread_ object returns a thread object instance, which is in a
ready state. Calling method _start_ on the instance causes it to free run.
Calling _next_ will make it proceed to the next _yield_ statement and stop.
So now the same object can be both a generator and a thread, depending on
which methods are called.

<verbatim>
thread threadFunction(param):     # I am a thread function definition
    ...

t = threadFunction(arg)           # I am an unstarted instance.
t.start(<optional OS thread id>)  # I am a running thread.
</verbatim>
----
Mark:
Also don't forget the important distinction that _next_ is a blocking call
and _start_ is non-blocking.  _next_ waits and returns the yield value and
_starts_ spawns an independent free-running thread.  Yield will throw an
exception if the thread wasn't started with a _next_.
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.