I've spent the last 3 years programming WindowsNT threads in MSVC++,
and I *really* like it. I want similar capabilities in Perl6.

1 The C++ thread model
Here is the thread model that I have in C++. It is a starting
point for thinking about what I want in Perl.

Every thread sees 
- the same code
- the same globals
- the same heap

Each thread has its own stack.

Threads can obtain thread-local global storage. I've never needed to
do this.

For synchronization, I have 
- critical sections
- mutexes
- semaphores
- events
- timers
- timeouts
- select
- wait for thread termination
- wait for all
- wait for any


2. A Perl6 thread model
Here is the model that I want in Perl6

Every thread sees
- the same global stash
- the same code

Every thread has 
- its own subroutine stack
- its own copy of all its lexicals

Each thread gets a thread-local global stash. $main::foo names a
variable in the global stash; by analogy, $thread::foo could name a
variable in the thread-local stash. $foo means $main::foo, just like
in Perl5. If you want $thread::foo, you have to write $thread::foo.

The language provides all the synchronization primitives listed above.
 

3. Modules and re-entrancy
RFC1v2 objects to this model on the grounds that modules won't be
reentrant if they see the same globals in different threads. I think
this is the tail wagging the dog.

3.1 Programs need globals
The reason I like threads is that I can write some code, spin off some
threads, and then share data between them. If every thread sees a
different copy of the globals, then I might as well fork processes.

3.2 Modules shouldn't use globals
If you want your modules to be reentrant, then you have to write them
that way. Rule 1 is *no globals*. The most common use of modules is to
implement an object, and the object should get everything it needs from
its instance data. This isn't just a threading issue: it is basic OO
practice, going all the way back to perlobj.pod in 1995.

Existing Perl5 modules may well turn out not to be reentrant. The
solution to that is to rewrite the modules, not contort Perl6 to
accommodate them. 

4. use foo
RFC1v2 has some discussion of how a thread can use a module. If all
threads share the global stash, then this problem goes away. A use
statement compiles a module and installs its symbols in the global
stash at compile time. Threaded code finds its global symbols
(primarily subroutine names) in the global stash, just like
non-threaded code. 

The only way that a thread can execute a use statement is with eval;
writing

        eval "use foo";

inside a thread is liable to redefine subroutines in the global stash.
Avoiding race conditions when this happens is a user-level
synchronization problem.


- SWM

Reply via email to