RFC 178 (v5) Lightweight Threads
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Lightweight Threads =head1 VERSION Maintainer: Steven McDougall [EMAIL PROTECTED] Date: 30 Aug 2000 Last Modified: 26 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 178 Version: 5 Status: Frozen =head1 ABSTRACT A lightweight thread model for Perl. =over 4 =item * All threads see the same compiled subroutines =item * All threads share the same global variables =item * Threads can create thread-local storage by Clocalizing global variables =item * All threads share the same file-scoped lexicals =item * Each thread gets its own copy of block-scoped lexicals upon execution of Cmy =item * Threads can share block-scoped lexicals by passing a reference to a lexical into a thread, by declaring one subroutine within the scope of another, or with closures. =item * Open code can only be executed by a thread that compiles it =item * The language guarantees atomic data access. Everything else is the user's problem. =back =over 4 =item Perl Swiss-army chain saw =item Perl with threads juggling chain saws =back =head1 CHANGES =head2 v5 Frozen =head2 v4 =over 4 =item * Traded in data coherence for LAtomic data access. Added examples 16 and 17. =item * Traded in Primitive operations for LLocking =item * Dropped L/local section =item * Revised L/Performance section =back =head2 v3 =over 4 =item * Simplified example 9 =item * Added L/Performance section =back =head2 v2 =over 4 =item * Added section on sharing block-scoped lexicals between threads =item * Added examples 9, 10, and 11. (N.B. renumbered following examples) =item * Fixed some typos =back =head1 FROZEN There was substantial--if somewhat disjointed--discussion of thread models on perl6-internals. The consensus among those with internals experience is that this RFC shares too much data between threads, and that the CPU cost of acquiring a lock for every variable access will be prohibitive. Dan Sugalski discussed some of the tradeoffs and sketched an alternate threading model at http://www.mail-archive.com/perl6-internals%40perl.org/msg01272.html however, this has not been submitted as an RFC. =head1 DESCRIPTION The overriding design principle in this model is that there is one program executing in multiple threads. One body of code; one set of global variables; many threads of execution. I like this model because =over 4 =item * I understand it =item * It does what I want =item * I think it can be implemented =back =head2 Notation =over 4 =item Imain and Ispawned threads We'll call the first thread that executes in a program the Imain thread. It isn't distinguished in any other way. All other threads are called Ispawned threads. =item Iopen code Code that isn't contained in a BLOCK. =back Examples are written in Perl5, and use the thread programming model documented in CThread.pm. Discussions of performance and implementation is based on the Perl5 internals; obviously, these are subject to change. =head2 All threads see the same compiled subroutines Subroutines are typically defined during the initial compilation of a program. Cuse, Crequire, Cdo, and Ceval can later define additional subroutines or redefine existing ones. Regardless, at any point in its execution, a program has one and only one collection of defined subroutines, and all threads see this collection. Example 1 sub foo { print 1 } sub hack_foo { eval 'sub foo { print 2 }' } foo(); Thread-new(\hack_foo)-join; foo(); Output: 12. The main thread executes Cfoo; the spawned thread redefines Cfoo; the main thread executes the redefined subroutine. Example 2 sub foo { print 1 } sub hack_foo { eval 'sub foo { print 2 }' } foo(); Thread-new(\hack_foo); foo(); Output: 11 or 12, according as the main thread does or does not make the second call to Cfoo() before the spawned thread redefines it. If the user cares which happens first, then they are responsible for doing their own synchronization, for example, with Cjoin, as shown in Example 1. Code refs (like all Perl data objects) are reference counted. Threads increment the reference count upon entry to a subroutine, and decrement it upon exit. This ensures that the op tree won't be garbage collected while the thread is executing it. =head2 All threads share the same global variables Example 3 #!/my/path/to/perl $a = 1; Thread-new(\foo)-join; print $a; sub foo { $a++ } Output: 2. C$a is a global, and it is the Isame global in both the main thread and the spawned thread. =head2 Threads can create thread-local storage by Clocalizing global variables Example 4 #!/my/path/to/perl $a = 1; Thread-new(\foo); print $a; sub foo { local $a = 2 } Output: 1. The spawned thread gets it's own copy of C$a. The copy of C$a in the main thread is unaffected. It
RFC 185 (v3) Thread Programming Model
This and other RFCs are available on the web at http://dev.perl.org/rfc/ =head1 TITLE Thread Programming Model =head1 VERSION Maintainer: Steven McDougall [EMAIL PROTECTED] Date: 31 Aug 2000 Last Modified: 26 Sep 2000 Mailing List: [EMAIL PROTECTED] Number: 185 Version: 3 Status: Frozen =head1 ABSTRACT This RFC describes the programming interface to Perl6 threads. It documents the function calls, operators, classes, methods, or whatever else the language provides for programming with threads. =head1 CHANGES =head2 v3 Frozen =head2 v2 =over 4 =item * Added SYNOPSIS, and wrote a proper ABSTRACT =item * Detailed Casync =item * Detailed sharing of lexicals between threads =item * Traded Mutexes back for Clock, Ctry, and Cunlock =item * Pushed CSemaphore, CEvent, and CTimer down into CThread:: =item * Specified readable, writable and failure to return Events =item * Reworked the wait functions =item * Added CQueue =back =head1 FREEZE There was little, if any, further discussion after version 2. =head1 SYNOPSIS use Thread; $sub = sub { ... }; $thread = new Thread \func , @args; $thread = new Thread $sub, @args; $thread = new Thread sub { ... }, @args; async { ... }; $result = join $thread; $thread = this Thread; @threads = all Thread; $thread1 == $thread2 and ... Thread::yield(); critical { ... }; # one thread at a time in this block lock $scalar; lock @array lock %hash; lock sub; $ok = try $scalar; $ok = try @array $ok = try %hash; $ok = try sub; unlock $scalar; unlock @array unlock %hash; unlock sub; $event = auto Thread::Event; $event = manual Thread::Event; set$event; reset $event; wait $event; $semaphore = new Thread::Semaphore $initial; $ok= $semaphore-up($n); $semaphore-down; $count = $semaphore-count; $timer = Thread::Timer-delay($seconds); $timer = Thread::Timer-alarm($time); $timer-wait; $event = $fh-readable $event = $fh-writable $event = $fh-failure $ok = wait_all(@references); $i = wait_any(@references); $queue = new Thread::Queue $queue-enqueue($a); $a = $queue-dequeue; $empty = $queue-empty; =head1 DESCRIPTION =head2 Thread =over 4 =item I$thread = Cnew CThread \Ifunc, I@args Executes Ifunc(I@args) in a separate thread. The return value is a reference to the CThread object that manages the thread. The subroutine executes in its enclosing lexical context. This means that lexical variables declared in that context may be shared between threads. See RFC 178 for examples. =item I$thread = Cnew CThread I$sub, I@args =item I$thread = Cnew CThread Csub { ... }, I@args Executes an anonymous subroutine in a separate thread, passing it I@args. The return value is a reference to the CThread object that manages the thread. The subroutine is a closure. References to variables in its lexical context are bound when the Csub operator executes. See RFC 178 for examples. =item Casync BLOCK Executes BLOCK in a separate thread. Syntactically, Casync BLOCK works like Cdo BLOCK. Casync creates a CThread object to manage the thread, but it does not return a reference to it. If you want the CThread object, use one of the Cnew CThread forms shown above. The BLOCK executes in its enclosing lexical context. This means that lexical variables declared in that context may be shared between threads. =item I$thread = Cthis CThread Returns a reference to the CThread object that manages the current thread. =item I@threads = Call CThread Returns a list of references to all existing CThread objects in the program. This includes CThread objects created for Casync blocks. =item I$result = Cjoin I$thread =item I@result = Cjoin I$thread Blocks until I$thread terminates. May be called repeatedly, by any number of threads. Returns the last expression evaluated in I$thread. This expression is evaluated in list context inside the thread. If Cjoin is called in list context, it returns the entire list; if Cjoin is called in scalar context, it returns the first element of the list. =item I$thread1 == I$thread2 Evaluates to true iff I$thread1 and I$thread2 reference the same CThread object. =item CThread::yield() Gives the interpreter an opportunity to switch to another thread. The interpreter is not obligated to take this opportunity, and the calling thread may regain control after an arbitrarily short period of time. =back =head2 Critical section Ccritical is a new keyword. Syntactically, it works like Cdo. critical { ... }; The interpreter guarantees that only one thread at a time can execute a Ccritical block. =head2 Lock =over 4 =item Clock I$scalar =item Clock I@array =item Clock I%hash =item Clock Isub Applies a lock to a variable. If there are no locks applied to