I've been thinking about closures, continuations, and coroutines, and
one of the interfering points has been threads.
What's the P6 thread model going to be?
As I see it, parrot gives us the opportunity to implement preemptive
threading at the VM level, even if it's not available via the OS.
Thinking about coroutines and continuations leads to the conclusion
that you need a segmented stack (duh). But it also makes you wonder
about how that stack interoperates with the threading subsystem. If
there's one stack per thread (obvious) then you're committing to an
"overt threading" model (user declares threads).
If the stacks are allowed to fork (which they must, to support even
Damian's generator-style coroutines) then there's the possibility of
supporting a "single, unified stack-tree" which means that generators
might contain their state across threads, and full coroutines may run
Anyway, I though the list was too quiet...
It has major disadvantages:
I must write my code so each operation only takes a small fraction of time
or I must try to predict when an operation will take a long time and yield
Worse, I must trust that everyone else has written their code to the above
spec and has accurately predicted when their code will take a long time.
Cooperative multitasking is essentially syntax sugar for an event loop. We
already have those (POE, Event, MultiFinder). They're nice when you don't
have real, good preemptive threads, but cannot replace them. It is a great
leap forward to 1987.
The simple reason is that with preemptive threads I don't have to worry
about how long an operation is going to take and tailor my code to it,
the interpreter will take care of it for me. All the other problems with
preemptive threads aside, that's the killer app.
We need preemptive threads. We need good support at the very core of the
langauge for preemptive threads. perl5 has shown what happens when you
bolt them on both internally and externally. It is not something we can
leave for later.
Cooperative multitasking, if you really want it, can be bolted on later or
provided as an alternative backend to a real threading system.
I'm spanking my yacht.
And one disadvantage:
Dan doesn't like it. :)
Well, there are actually a lot of disadvantages, but that's the only
important one, so it's probably not worth much thought over alternate
threading schemes for Parrot at least--it's going with an OS-level
preemptive threading model.
No, this isn't negotiable.
--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk
More information please.
Really.. why? When you still have computation to be done before you can
produce your output, why yield? There are certainly scenarios where you'd
want each thread to get a "fair share" of computation time, but if the
output from all threads is desired, whoever is waiting for them probably
won't care who gets to do computation first.
>Worse, I must trust that everyone else has written their code to the above
>spec and has accurately predicted when their code will take a long time.
Both this and the above can be easily solved by a timer event that forces
a yield. Most synchronization issues this would introduce can probably be
avoided by deferring the yield until the next "checkpoint" determined by
the compiler (say, the loop iteration)
I think this is a minor problem compared to the hurdles (and overhead!) of
>Cooperative multitasking is essentially syntax sugar for an event loop.
No, since all thread state is saved. In syntax and semantics they're much
closer to preemptive threads than to event loops.
>We need good support at the very core of the langauge for preemptive
>threads. perl5 has shown what happens when you bolt them on both
>internally and externally. It is not something we can leave for later.
I think perl 6 will actually make it rather easy to bolt it on later. You
can use fork(), let the OS handle the details, and use tied variable for
sharing. I believe something already exists for this in p5 and is apparently
faster than ithreads. I haven't dug into that thing though, maybe it has
other problems again. No doubt you'll point 'em out for me ;-)
>Cooperative multitasking, if you really want it, can be bolted on later or
>provided as an alternative backend to a real threading system.
I agree it can be bolted on later, but so can preemptive threads probable.
As Simon pointed out, optimizing for the common case means skipping threads
altogether for now.
And I resent how you talk about non-preemptive threading as not being "real"
threading. Most embedded systems use tasking/threading models without
round-robin scheduling, and people who try to move applications that perform
real-time tasks from MacOS 9 to MacOS X curse the preemptive multitasking
the latter has.
Matthijs van Duin -- May the Forth be with you!
If you can ensure me that the hooks will be available in critical routines
(blocking operations) to allow proper implementation of cooperative threads
in a perl module, then that's all the support from the parrot VM I need :-)
I just hope you won't make my non-preemptive-threaded applications slower
with your built-in support for preemptive threads :-)
It's very easy to automatically translate threads at the language
level into cooperative instructions at the VM level. I proposed it to
perl5-porters in February 1997, and I proposed it to perl6-language in
At the language level, cooperative multitasking would look and feel
like plain threads. I think this would allow the language to
reconcile threading and callback-based I/O, but I agree it would add
weight to the VM that most people don't want.
> The simple reason is that with preemptive threads I don't have to worry
> about how long an operation is going to take and tailor my code to it,
> the interpreter will take care of it for me. All the other problems with
> preemptive threads aside, that's the killer app.
Cooperative threads at the VM level don't preclude support for true
threads. For example, it should be possible create a fixed number of
threads that act as execution pipelines for a cooperative VM.
Divorcing the system threads from the language threads gives you a
couple interesting possibilities.
It's possible to tune the number of system threads Perl uses. Threads
tend to scale poorly after they run out of CPUs. Developers can take
this into consideration and limit the number of threads a program
Programs are still free to spawn as many "threads" as they want, even
if they request more threads than the operating system can provide.
> We need preemptive threads. We need good support at the very core of the
> langauge for preemptive threads. perl5 has shown what happens when you
> bolt them on both internally and externally. It is not something we can
> leave for later.
> Cooperative multitasking, if you really want it, can be bolted on later or
> provided as an alternative backend to a real threading system.
Disagreement, but I've grown accustomed to it. Carry on.
On-list since this is relevant for others participating in the discussion
>Classic scenario for threading: GUI. GUI uses my module which hasn't been
>carefully written to be cooperative. The entire GUI pauses while it waits
>for my code to do its thing. No window updates, no button pushes, no
>way to *cancel the operation that's taking too long*.
OK, very true, I was more thinking of something like a server that uses
a thread for each connection.
Luckily I already mentioned that automatic yielding is not too hard. A
timed that sets a "yield asap" flag that's tested iteration of a loop
should work - maybe something with even less overhead can be cooked up.
>I hope this is not a serious suggestion to implement preemptive threads
>using fork() and tied vars. That way ithreads lie.
Actually, ithreads are slower because they don't do copy-on-write while
the OS usually does.
fork() moves the problem to the OS, where bright people have already spent
a lot of time optimizing things, I hope at least ;)
I suppose how much faster it is to do things within the VM rather than
using forked processes depends on how much IPC happens. In your GUI
example, the answer is: very little, only status updates.
>The existing system you probably mean is POE
No, I wasn't. I looked it up, it's called "forks".
>Besides, it would be silly as Dan has already said Parrot will support
>preemptive multitasking and that's half the hard work done. The other
>half is designing a good language gestalt around them.
OK, as long as it doesn't hurt performance of non-threaded apps I
obviously have no problem with *supporting* preemptive threading, since
they're certainly useful for some applications. But coop threads are
more useful in the general case - especially since they're simpler to use
thanks to the near-lack of synchronization problems. Simplicity is good,
especially in a language like perl.
>> And I resent how you talk about non-preemptive threading as not being
>> "real" threading.
>My biases come from being a MacOS user since System 6. MultiFinder
Valid point (I'm also a long-time MacOS user), but cooperative multitasking
isn't the same as cooperative threading. We're talking about the scheduling
between threads inside one process; and we can avoid the lockup problem in
the VM with automatic yielding.
This makes most of the problems of cooperative threading disappear, while
leaving the advantages intact.
>If we want to support real-time programming in Perl
No, I was merely pointing out that it's not always a step "forward" for all
applications. Some people made good use with the ability to grab all the
CPU time you need on old MacOS.
>None of this precludes having a cooperative threading system, but we
>*must* have a preemptive one.
"must" is a big word; people happily used computers a long time before any
threading was used ;-)
It looks like we could use both very well though
Well, I almost would agree with you since cooperative threading can almost
entirely be done in perl code, since they are built in continuations. I
actually gave an example of that earlier.
The only thing is that blocking system operations like file-descriptor
operations need some fiddling. (first try it non-blocking fd operation, if
that fails block the thread and yield to another; if all threads are
blocked, so a select() or kqueue() or something similar over all fds on
which threads are waiting)
If the hooks exist to handle this in a perl module, then I think we can
skip the issue mostly, except maybe the question what to include with perl
in the default installation.
At a language level this has very little to do with whether treads are
implemented preemptively or not. The basic philosophical difference
between the pthreads and ithreads models is in whether global variables
are shared by default or not. The general consensus up till now is
that having variables unshared by default is the cleaner approach,
though it does cost more to spawn threads that way, at least the way
Perl 5 implements it. The benefit of ithreads over pthreads may be
somewhat lessened in Perl 6. There may well be intermediate models in
which some kinds of variables are shared by default and others are not.
We don't know how that will work--we haven't run the experiment yet.
For anything other than existential issues, I believe that most
arguments about the future containing the words "either", "or",
"both", or "neither" are likely to be wrong. In particular, human
psychology is rarely about the extremes of binary logic. As creatures
we are more interested in balance than in certainty, all the while
proclaiming our certainty that we've achieved the correct balance.
In short, I think both the pthreads and ithreads models are wrong
to some extent.
<soapbox sincerity=high relevance=low>
And this is why I believe it's best to have a philosopher guiding the
design, as long as he's been properly indoctrinated into the issues
surrounding the relevant mechanics. ;o]
Do you Yahoo!?
Yahoo! Tax Center - File online, calculators, forms, and more
Sorry, I haven't been following this too closely - but is it the intention
to support the 5.005, or the ithreads model (or both? or neither?).
To collect all the latest movies, simply place an unprotected ftp server
on the Internet, and wait for the disk to fill....
The fact that perl5 uses ithreads is IMHO a implmentation detail and is
only relevant to preemtive threads in that it is the only sane way
to do preemtive threads in perl5 since mixing reference counting with
threads means mutex hell. A problem I think we are not going to have
in perl6 with the gc and PMC vtables.
The speed problem of cloning the threads in perl5 is also
an implmentation detail that could be fixed if the interest existed,
sadly the interest in threads from the qualified hackers seem
extremely low, I wonder if that means something.