Parrot Virtual Machine/Multithreading and Concurrency

Multithreading Requirements
Multithreading is an area where interpreted languages such as Perl 5 have had some problems in the past. Perl 5, as a prime example, had a very buggy and non-robust implementation of threads that was not scalable.

In contrast to Perl 5, Perl 6 is including advanced multithreading and concurrency features in the core language. To support all these advanced features of the Perl 6 language, Parrot must provide those same features as well.

Coroutines
While not technically "multithreading", coroutines represent a simple form of concurrency that will find many interesting uses as they catch on with mainstream programmers. Coroutines are like subroutines which use a yield statement instead of a return statement. The  statement causes the coroutine to return a value to the caller. However,  does not cause the coroutine to exit, disappear, or lose its current state. The next time the caller calls the coroutine, the coroutine will pick up where it left off the last time. Here is an example:

.sub 'MyCoroutine' .yield(1) .yield(2) .return(3) .end

.sub 'MyCaller' $I0 = 'MyCoroutine' say($I0) $I0 = 'MyCoroutine' say($I0) $I0 = 'MyCoroutine' say($I0) .return

The output of the function  will be:

1 2 3

Coroutines are immediately useful in places where a persistent state needs to be maintained, but where it might be difficult to coordinate that state between multiple callers, or multiple threads. One such example is in file or database access where a coroutine can serialize accesses, and maintain persistent state information about the size of the file and locations of certain features in the file.

Coroutines are also called "continuations" in other places, or even "continuation sandwich" in others.

Coroutine Parameters
Parameters to a coroutine are only passed the first time the coroutine is called, or any time the coroutine is called after having a  statement. Here is an example:

.sub 'MyCoroutine' .param int a   .yield(a) .yield(a) .yield(a) .return(a) .end .sub 'main' :main $I0 = 'MyCoroutine'(1) # the "call" say $I0 $I0 = 'MyCoroutine'(2) # "continuation" say $I0 $I0 = 'MyCoroutine'(3) # "continuation" say $I0 $I0 = 'MyCoroutine'(4) # "continuation" say $I0 .end

This code will print the following result, even though the parameter to the  function changes with each call:

1 1 1 1

This is because only the first call to  is actually a function call that creates the local parameters. The other calls to  are simply continuations, not calls. A continuation does not create new parameter variables.

Returning and Yielding
A return call in a coroutine causes it to return a value to the caller and to destroy its current lexical scope, as usual. A yield call, however, will return a value without destroying the current lexical scope. Yielding then will allow the coroutine to maintain its current state and resume its execution the next time it is called.

Continuation and Coroutine PMCs
This is where the heart of the coroutine system is located, the coroutine PMC. The coroutine PMC is an object that stores the state of the coroutine so that it can be called multiple times in a row. A continuation PMC, which is a superclass of the coroutine, is a stored interpreter state. The coroutine operates by storing a continuation when a  directive is called, and invoking that continuation when the coroutine is called again.

Threads
Internally, Parrot supports multiple different methods to perform threading. Luckily, all of these different methods are abstracted and the details are hidden from the HLL programmer. Parrot's concurrency system is modular, so new multithreading technologies can be added to Parrot later, and HLL programmers will be able to benefit from these changes and additions without having to make any changes to their code.

Managing Threads
There are four basic operations that can be used to create and manage a new thread. In Parrot, threads are all abstracted in the Task PMC. To create a new thread, you first create a new Task PMC, and then you add it to the scheduler.

Resources

 * http://www.parrotcode.org/docs/pdd/pdd25_concurrency.html
 * Synopsis 17