> miguel sofer wrote:>> The same tech makes possible a new command [yieldTo]: essentially >> [tailcall] but yielding instead of returning - that is, saving the state >> of the current coro, so that it can be reawakened later on. I am >> planning to put this into ::tcl::unsupported.
Donal K. Fellows wrote:
> For unsupported? No need. For supported? It would be good to see what > you propose in that case. Off-the-wall suggestion: maybe a "-target" > option to normal [yield] would be better...?
Not a formal TIP, but I was talking with Miguel about this, and I
*think* I understand what he's proposing. The idea is that [yieldto]
will accept a complete Tcl command as its arguments. This command is
not evaluated in the coroutine; rather, it is evaluated in the
coroutine's *caller*. The command will usually be an invocation of
another coroutine, but the last is not a requirement.
As an example:
proc pro {file} {
yield
while {1} {
set result {[gets $file $line]}
yieldto consumer [list $result $line]
if {$result < 0} { return }
}
}
proc con {} {
while {1} {
lassign [yieldto producer] result line
if {$result < 0} {
return
}
puts $line
}
}
set file [open "myfile.txt" r]
coroutine producer pro $file
coroutine consumer con
producer; # invoke one last time to shut it down.
close $file
Here we have created two coroutines, [producer] and [consumer].
[producer] initially yieds back to the main routine, while [consumer]
starts running immediately.
The first action that [consumer] takes is [yieldto producer]. The
[consumer] coroutine's state is frozen, and control returns to the
main coroutine, which immediately invokes [producer]. The [producer]
coroutine reads the first line of the file, and calls [yieldto]
giving it [producer {$result $line}].
The two ping-pong back and forth, each specifying the next action,
until finally [producer] sends over the -1 result at end of file.
At that point [consumer] returns to the main routine, and one
last call to [producer] causes it to hit its [return]; now everything
is shut down cleanly.
Closing the file is all that remains.
I don't claim fully to understand the implications of permitting
an arbitrary command, rather than just a coroutine, as an
argument to [yieldto]. But it's fairly obvious from my discussion
with Miguel that having [yieldto] accept an arbitrary command is
by far the easiest way to implement this beast. Since using an
arbitrary command is more general, why not?
This might be a nice structure for implementing things like
compilers (the lexer yields to the parser; parser yields to
lexer and semantic engine; semantic engine yields to parser),
or other things that follow the "pipes and filters" pattern.
I think that for ordinary "green threads" I'd avoid yieldto in
favour of a scheduler in the main routine - the way coronet
does it.
This idea looks sound as far as it goes; I'm musing on how many
more iterations it'll take us to get to first-class continuations,
which is where this road seems to be heading.
--
73 de ke9tv/2, Kevin
------------------------------------------------------------------------------
Join us December 9, 2009 for the Red Hat Virtual Experience,
a free event focused on virtualization and cloud computing.
Attend in-depth sessions from your desk. Your couch. Anywhere.
http://p.sf.net/sfu/redhat-sfdev2dev
_______________________________________________
Tcl-Core mailing list
Tcl-...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tcl-core