tagged release 0.6.4
[parrot.git] / docs / pdds / pdd25_concurrency.pod
blob7277be90b3d6cf0c08159775b40df82111ae0a77
1 # Copyright (C) 2001-2007, The Perl Foundation.
2 # $Id$
4 =head1 NAME
6 docs/pdds/draft/pdd25_concurrency.pod - Parrot Concurrency
8 =head1 ABSTRACT
10 This document defines the requirements and implementation strategy for
11 Parrot's concurrency models.
13 =head1 VERSION
15 $Revision$
17 =head1 DESCRIPTION
19 =over 4
21 =item - Parrot supports multiple concurrency models, including POSIX
22 threads, event-based programming, and asynchronous I/O.
24 =item - A concurrency scheduler manages all concurrent tasks
26 =item - Each interpreter has its own concurrency scheduler
28 =item - Concurrency schedulers for different interpreters
29 communicate and can share tasks
31 =item - A concurrency scheduler may link to other schedulers as a
32 parent, a child, or an equal
34 =item - A task is a concurrent unit of work
36 =item - All tasks support a standard interface used by the concurrency
37 scheduler, but otherwise have a great deal of flexibility in their
38 implementation
40 =item - Tasks can share PMC variables
42 =back
44 =head1 DEFINITIONS
46 Concurrency is a parallel execution of units of code (on multiprocessor
47 machines), or a flexible ordering of serial units of code (on single processor
48 machines). For certain problem spaces, concurrency offers significant speed
49 gains by parceling out processor-intensive activity or by ensuring that a wait
50 for input or system resources doesn't hold up the entire application.
52 A task is a unit of code that can be executed concurrently.
54 =head1 IMPLEMENTATION
56 Rather than defining a single canonical threading model, Parrot defines
57 an infrastructure that supports multiple concurrency models and provides
58 for interaction between the various models. Parrot already uses multiple
59 concurrency models for events, threads, async I/O, and exceptions, a
60 trend that will only continue as we support multiple HLLs and external
61 threading libraries like Intel's Threading Building Blocks. Designing
62 for multiple concurrency models also gives Parrot more room to grow as
63 future models are researched and developed.
65 To avoid conflicts between concurrency models, Parrot provides a single
66 central concurrency scheduler for each interpreter instance.  Each
67 concurrency model defines a Task PMC that supports a standard minimal
68 interface. The scheduler can interact with tasks from different models
69 without direct access to the details of each model.
71 On multiprocessor systems, the scheduler is responsible for allocating
72 tasks to processors, or for delegating that allocation to the underlying
73 OS.
75 For the most part, when we talk about concurrency, we mean concurrency
76 across an interpreter pool. An interpreter pool is a set of interpreter
77 instances that share common resources: the memory pools, arenas, and
78 global namespace--pretty much everything except what's in the
79 interpreter structure itself. They're essentially threads in the OS
80 sense. 
82 Another form of concurrency is between completely independent
83 interpreter instances, each with their own memory pools, arenas,
84 namespaces, etc. Independent interpreters may run as separate processes
85 on the same machine, or even as separate processes on different machines
86 (in a clustering environment, for example). The concerns of
87 shared-interpreter concurrency and independent-interpreter concurrency
88 are similar, and in Parrot both use the same central concurrency
89 scheduler. This PDD doesn't directly address independent-interpreter
90 concurrency, but does include occasional notes on how it integrates with
91 shared-interpreter concurrency.
93 =head2 Supported Concurrency Models
95 The following are a few of the concurrency models Parrot intends to
96 support. The biggest differences between them are in how they handle
97 variables shared across concurrent tasks.  But the design is such that
98 each of the different models can run simultaneously, coordinated through the
99 central concurrency scheduler.
101 =head3 Mutex/Lock Concurrency
103 In this model, before performing an operation on a shared variable, you
104 must first acquire a lock on it. Once a lock is acquired, any other
105 concurrent tasks that attempt to acquire a lock on that variable will
106 block until the existing lock is released.
108 A mutex is a thing that can be locked. They are not directly exposed to
109 users. They're non-recursive, non-read/write, exclusive things.  When a
110 concurrent task gets a mutex, any other attempt to get that mutex will
111 block until the owning task releases the mutex. Mutexes are implemented
112 using the platform-native lock construct.
114 The first thing that any vtable function of a shared PMC must do is to
115 acquire the mutex of the PMCs in its parameter list (in ascending
116 address order). In this model only PMCs can be shared.
118 =head3 STM Concurrency
120 Parrot's preferred model of concurrency is based on Software
121 Transactional Memory. In this model, rather than locking a shared
122 variable while performing a series of operations on it, the changes are
123 bundled into a transaction that acts as an atomic unit.
125 Within the transaction, STM creates a "hypothetical" copy of the
126 variable, logs the changes made to that copy, and at the end of the
127 transaction performs some validation steps to decide whether to save the
128 hypothetical value back to the real variable (a commit) or discard the
129 hypothetical value (a roll back). One common validation step is to check
130 whether the value of the real variable was changed during the execution
131 of the transaction (possibly by another concurrent task).
133 STM tasks can read/write shared variables from mutex/lock tasks, as they
134 appear to the mutex/lock task as a single atomic operation. Mutex/lock
135 tasks can read shared variables from STM tasks, but they cannot write
136 them, as the STM tasks will not respect the lock and may commit a new
137 value in the middle of a complex operation that requires the lock. As a
138 safety mode, STM tasks may be configured to fail validation on any
139 transaction attempting to commit to a variable locked by a mutex/lock
140 task.
142 =head3 POSIX Concurrency
144 This is the POSIX "share-everything" style of threading, such as is used
145 in Perl 5's "pthread" model, as well as the thread models for Ruby and
146 Python. [Recommended reading: "Programming with POSIX Threads" by Dave
147 Butenhof.]
149 =head3 Process-type Concurrency
151 This is the Perl 5 "iThreads" threading model. In this model no data is
152 shared implicitly, and all sharing must be done on purpose and
153 explicitly. It resembles the Unix
154 fork-process-with-shared-memory-segment model, not a surprise as it was
155 originally developed with emulation of Unix's fork system in mind. 
157 =head3 Independent Concurrency
159 Independent tasks have no contact with the internal data of any other
160 task in the current process. These are implemented as STM concurrency
161 but only use transactions for the shared interpreter globals.
163 Note that independent tasks may still communicate back and forth by
164 passing either atomic things (ints, floats, and pointers) or static
165 buffers that can become the property of the destination thread.
167 =head3 Intel Threading Building Blocks
169 Threading Building Blocks (TBB) is a library of tools for data-parallel
170 programming, dividing large data sets into small pieces so that
171 operations on those data-sets can be parallelized across multiple
172 processors.
174 Parrot will provide two levels of integration with TBB: an interface for
175 TBB's scheduling to interact with the central concurrency scheduler, and
176 an interface for developers to access the TBB routines from within
177 PIR/PASM.
179 Like Parrot, TBB is task-based. Since TBB performs its own scheduling,
180 TBB tasks in Parrot will be given a lightweight scheduler that only has
181 the responsibility of passing messages, events, etc, back and forth
182 betwen the TBB task and the central scheduler. TBB tasks will not share
183 variables with any other types of concurrent tasks in Parrot.
185 Note that since TBB is a C++ library, it is only available when Parrot
186 is compiled with a C++ compiler.
188 =head2 Concurrrency Scheduler API
190 The concurrency scheduler has two parts, a Scheduler PMC, which has an
191 instance stored in the interpreter struct, and a set of core routines in
192 F<src/scheduler.c>.
194 An instance of the Scheduler PMC has 5 internal attributes, which are:
196 =over 4
198 =item 1
200 An unique ID for the scheduler
202 =item 2
204 The current highest assigned task ID
206 =item 3
208 The task list
210 =item 4
212 The task priority index
214 =item 5
216 The list of handlers
218 =back
220 The unique ID of the scheduler is used by other schedulers to pass messages.
221 With a small set of identifying information (including process ID, interpreter
222 ID, scheduler ID, and possibly a URL/hostname) a scheduler can address other
223 schedulers, both local to the current interpreter and remote.
225 The task list is a simple unordered integer indexed data structure, currently
226 implemented as a hash. Each task in the list has an integer ID assigned when
227 it is first inserted into the list. A task retains the same ID throughout its
228 lifetime, and the ID is not reused once a task is finalized. (The data
229 structure is currently implemented as a hash so that it only takes up the
230 memory required for currently living tasks. A task list for a particular
231 program may use thousands of task IDs, but only need memory allocated for a
232 handful of elements at any given moment.)
234 The task rank index is calculated based on the type, priority rating, age of
235 the tasks in the task list. The index is a simple array, and in general the
236 top (zeroth) element in the array is the next one to receive attention. The
237 index is recalculated regularly as new tasks are inserted into the task list,
238 existing tasks are modified or completed, and as time progresses so the age of
239 some tasks pushes them to a higher priority. Because of the regular
240 recalculation, the rank index may cache some frequently-accessed and rarely
241 changing data from the tasks (though it is not required to do so). (As a later
242 optimization, some data structure other than an array may be used to speed up
243 rank recalculation. For example, with a hash of hashes of arrays keyed on task
244 attributes, the process of inserting new tasks at a relative priority to other
245 existing tasks could be performed without shifting the rank of all lower
246 ranked tasks.)
248 The list of handlers is a simple stack of handler PMCs currently waiting for
249 an appropriate task (event, exception). See PDD 24 on Events for more details
250 on event handlers.
252 =head3 Flags
254 PMC flags 0-7 are reserved for private use by a PMC. The scheduler uses flag 0
255 to indicate whether the priority index is currently valid or needs to be
256 recalculated before the next use.
258 =head3 Vtable Functions
260 =over 4
262 =item push_pmc
264 Add an entry to the task list.
266 =item pop_pmc
268 Pull the next entry (the highest ranked entry in the task priority index) off
269 the task list. If there are no tasks remaining in the task list, return null.
271 =back
273 =head3 Methods
275 =over 4
277 =item add_handler
279     $P1.add_handler($P2)
281 Add an event or exception handler to the scheduler's list of handlers.
283 =item find_handler
285     $P1 = $P2.find_handler($P3)
287 Search for an event or exception handler $P1, in scheduler $P2, for the task
288 $P3. Returns a null PMC if an appropriate handler is not found.
290 =back
292 =head2 Task PMC API
294 The interface of the Task PMC is also the minimum required interface for all
295 subclasses, extensions, and alternate implementations of a task.
297 An instance of the Task PMC has 7 internal attributes, which are:
299 =over 4
301 =item 1
303 The task ID
305 =item 2
307 The type of the task
309 =item 3
311 The subtype of the task
313 =item 4
315 The priority of the task
317 =item 5
319 The birthtime stamp of the task
321 =item 6
323 The status of the task
325 =item 7
327 The code block of the task (optional)
329 =item 8
331 An interpreter structure for the task (optional)
333 =back
335 Types of tasks include 'event', 'exception', 'io', and 'code'. The subtype of
336 a task is used by events and exceptions to identify appropriate handlers.
337 Possible status values for tasks include 'created', 'invoked', 'inprocess',
338 and 'completed'.  The final state of a task is 'destroyed', but is never
339 marked (the task PMC is removed from the task list and at some later point
340 destroyed by GC). The priority of a task is an integer value between 0 and
341 100, with 0 as the lowest priority.
343 The birthtime stamp is the point at which the task was inserted into the task
344 list, and is used for calculating the age of tasks.
346 The code block is optional and only for tasks that are associated with a
347 simple code block. The interpreter structure is also optional and only used
348 for thread-like tasks that maintain their own interpreter state.
350 =head3 Vtable Functions
352 =over 4
354 =item get_attr_str
356 Retrieve an attribute of the task.
358 =item set_attr_str
360 Set an attribute of the task.
362 =back
364 =head2 Opcodes
366 =over 4
368 =item new
370   $P1 = new 'Task'
372 Creates a new task. (The Scheduler PMC is never instantiated directly, it is
373 only used by Parrot internals.)
375 =item schedule
377   $P0 = new 'Task'
378   # set attributes
379   schedule $P0
381 Register a task with the concurrency scheduler. Details about the task are
382 stored within the task PMC.
384 =item join
386   $P0 = new 'Task'
387   # ... schedule the task, etc.
388   join $P0
390 Wait for a particular task to complete.
392 =item kill
394   $P0 = new 'Task'
395   # ... schedule the task, etc.
396   kill $P0
398 Kill a task without waiting for it to complete.
401 =back
403 =head1 ATTACHMENTS
405 None.
407 =head1 FOOTNOTES
409 None.
411 =head1 REFERENCES
413 Dec 2003 - (Dan ponders threads based on POSIX and Perl 5 experience)
414 <http://groups.google.com/group/perl.perl6.internals/browse_frm/thread/e64b22ab7de0a7a6/889b5d8c4cd267b7?lnk=gst&q=threads&rnum=3#889b5d8c4cd267b7>
416 Dec. 2003 - "threads and shared interpreter data structures"
417 <http://groups.google.com/group/perl.perl6.internals/browse_frm/thread/e64ea4ff287e04fd/b71333e282d3d187?lnk=gst&q=threads&rnum=9#b71333e282d3d187>
419 Jan. 2004 - "Threads Design. A Win32 perspective."
420 <http://groups.google.com/group/perl.perl6.internals/browse_frm/thread/3209629b23306029/52ba9d37425ba015?lnk=gst&q=threads&rnum=8#52ba9d37425ba015>
422 Jan. 2004 - "Start of threads proposal"
423 <http://groups.google.com/group/perl.perl6.internals/browse_frm/thread/4c7de440da84d5c6/04cfb70b0d81dfba?tvc=1&q=threads#04cfb70b0d81dfba>
425 Sept. 2005 - "consider using OS threads"
426 <http://groups.google.com/group/perl.perl6.internals/browse_frm/thread/40b50e3aa9255f8e/036a87b5d2b5ed2c?lnk=gst&q=threads&rnum=2#036a87b5d2b5ed2c>
428 Aug. 2007 - "multi-threading a work in progress"
429 <http://perlmonks.org/?node_id=636466>
431 Concurrency as Futures -
432 <http://www.cincomsmalltalk.com/userblogs/mls/blogView?showComments=true&entry=3336838959>
434 Io language - <http://www.iolanguage.com/about/>
436 Java memory and concurrency - http://www.cs.umd.edu/~pugh/java/memoryModel/
438 =cut
440 __END__
441 Local Variables:
442   fill-column:78
443 End: