Commit | Line | Data |
---|---|---|
a0e07ba4 NJ |
1 | @page |
2 | @node Scheduling | |
3 | @chapter Threads, Mutexes, Asyncs and Dynamic Roots | |
4 | ||
5 | [FIXME: This is pasted in from Tom Lord's original guile.texi chapter | |
6 | plus the Cygnus programmer's manual; it should be *very* carefully | |
7 | reviewed and largely reorganized.] | |
8 | ||
9 | @menu | |
10 | * Arbiters:: Synchronization primitives. | |
11 | * Asyncs:: Asynchronous procedure invocation. | |
12 | * Dynamic Roots:: Root frames of execution. | |
13 | * Threads:: Multiple threads of execution. | |
14 | * Fluids:: Dynamically scoped variables. | |
15 | @end menu | |
16 | ||
17 | ||
18 | @node Arbiters | |
19 | @section Arbiters | |
20 | ||
21 | @cindex arbiters | |
22 | ||
23 | @c FIXME::martin: Review me! | |
24 | ||
25 | Arbiters are synchronization objects. They are created with | |
26 | @code{make-arbiter}. Two or more threads can synchronize on an arbiter | |
27 | by trying to lock it using @code{try-arbiter}. This call will succeed | |
28 | if no other thread has called @code{try-arbiter} on the arbiter yet, | |
29 | otherwise it will fail and return @code{#f}. Once an arbiter is | |
30 | successfully locked, it cannot be locked by another thread until the | |
31 | thread holding the arbiter calls @code{release-arbiter} to unlock it. | |
32 | ||
33 | @deffn primitive make-arbiter name | |
34 | Return an object of type arbiter and name @var{name}. Its | |
35 | state is initially unlocked. Arbiters are a way to achieve | |
36 | process synchronization. | |
37 | @end deffn | |
38 | ||
39 | @deffn primitive try-arbiter arb | |
40 | Return @code{#t} and lock the arbiter @var{arb} if the arbiter | |
41 | was unlocked. Otherwise, return @code{#f}. | |
42 | @end deffn | |
43 | ||
44 | @deffn primitive release-arbiter arb | |
45 | Return @code{#t} and unlock the arbiter @var{arb} if the | |
46 | arbiter was locked. Otherwise, return @code{#f}. | |
47 | @end deffn | |
48 | ||
49 | ||
50 | @node Asyncs | |
51 | @section Asyncs | |
52 | ||
53 | @cindex asyncs | |
54 | @cindex system asyncs | |
55 | ||
56 | @c FIXME::martin: Review me! | |
57 | ||
58 | An async is a pair of one thunk (a parameterless procedure) and a mark. | |
59 | Setting the mark on an async guarantees that the thunk will be executed | |
60 | somewhen in the future (@dfn{asynchronously}). Setting the mark more | |
61 | than once is satisfied by one execution of the thunk. | |
62 | ||
63 | Guile supports two types of asyncs: Normal asyncs and system asyncs. | |
64 | They differ in that marked system asyncs are executed implicitly as soon | |
65 | as possible, whereas normal asyncs have to be invoked explicitly. | |
66 | System asyncs are held in an internal data structure and are maintained | |
67 | by Guile. | |
68 | ||
69 | Normal asyncs are created with @code{async}, system asyncs with | |
70 | @code{system-async}. They are marked with @code{async-mark} or | |
71 | @code{system-async-mark}, respectively. | |
72 | ||
73 | @deffn primitive async thunk | |
74 | Create a new async for the procedure @var{thunk}. | |
75 | @end deffn | |
76 | ||
77 | @deffn primitive system-async thunk | |
78 | Create a new async for the procedure @var{thunk}. Also | |
79 | add it to the system's list of active async objects. | |
80 | @end deffn | |
81 | ||
82 | @deffn primitive async-mark a | |
83 | Mark the async @var{a} for future execution. | |
84 | @end deffn | |
85 | ||
86 | @deffn primitive system-async-mark a | |
87 | Mark the async @var{a} for future execution. | |
88 | @end deffn | |
89 | ||
90 | As already mentioned above, system asyncs are executed automatically. | |
91 | Normal asyncs have to be explicitly invoked by storing one or more of | |
92 | them into a list and passing them to @code{run-asyncs}. | |
93 | ||
94 | @deffn primitive run-asyncs list_of_a | |
95 | Execute all thunks from the asyncs of the list @var{list_of_a}. | |
96 | @end deffn | |
97 | ||
98 | Automatic invocation of system asyncs can be temporarily disabled by | |
99 | calling @code{mask-signals} and @code{unmask-signals}. Setting the mark | |
100 | while async execution is disabled will nevertheless cause the async to | |
101 | run once execution is enabled again. Please note that calls to these | |
102 | procedures should always be paired, and they must not be nested, e.g. no | |
103 | @code{mask-signals} is allowed if another one is still active. | |
104 | ||
105 | @deffn primitive mask-signals | |
106 | Mask signals. The returned value is not specified. | |
107 | @end deffn | |
108 | ||
109 | @deffn primitive unmask-signals | |
110 | Unmask signals. The returned value is not specified. | |
111 | @end deffn | |
112 | ||
113 | @c FIXME::martin: Find an example for usage of `noop'. What is that | |
114 | @c procedure for anyway? | |
115 | ||
116 | @deffn primitive noop . args | |
117 | Do nothing. When called without arguments, return @code{#f}, | |
118 | otherwise return the first argument. | |
119 | @end deffn | |
120 | ||
121 | ||
122 | @node Dynamic Roots | |
123 | @section Dynamic Roots | |
124 | @cindex dynamic roots | |
125 | ||
126 | A @dfn{dynamic root} is a root frame of Scheme evaluation. | |
127 | The top-level repl, for example, is an instance of a dynamic root. | |
128 | ||
129 | Each dynamic root has its own chain of dynamic-wind information. Each | |
130 | has its own set of continuations, jump-buffers, and pending CATCH | |
131 | statements which are inaccessible from the dynamic scope of any | |
132 | other dynamic root. | |
133 | ||
134 | In a thread-based system, each thread has its own dynamic root. Therefore, | |
135 | continuations created by one thread may not be invoked by another. | |
136 | ||
137 | Even in a single-threaded system, it is sometimes useful to create a new | |
138 | dynamic root. For example, if you want to apply a procedure, but to | |
139 | not allow that procedure to capture the current continuation, calling | |
140 | the procedure under a new dynamic root will do the job. | |
141 | ||
142 | @deffn primitive call-with-dynamic-root thunk handler | |
143 | Evaluate @code{(thunk)} in a new dynamic context, returning its value. | |
144 | ||
145 | If an error occurs during evaluation, apply @var{handler} to the | |
146 | arguments to the throw, just as @code{throw} would. If this happens, | |
147 | @var{handler} is called outside the scope of the new root -- it is | |
148 | called in the same dynamic context in which | |
149 | @code{call-with-dynamic-root} was evaluated. | |
150 | ||
151 | If @var{thunk} captures a continuation, the continuation is rooted at | |
152 | the call to @var{thunk}. In particular, the call to | |
153 | @code{call-with-dynamic-root} is not captured. Therefore, | |
154 | @code{call-with-dynamic-root} always returns at most one time. | |
155 | ||
156 | Before calling @var{thunk}, the dynamic-wind chain is un-wound back to | |
157 | the root and a new chain started for @var{thunk}. Therefore, this call | |
158 | may not do what you expect: | |
159 | ||
160 | @lisp | |
161 | ;; Almost certainly a bug: | |
162 | (with-output-to-port | |
163 | some-port | |
164 | ||
165 | (lambda () | |
166 | (call-with-dynamic-root | |
167 | (lambda () | |
168 | (display 'fnord) | |
169 | (newline)) | |
170 | (lambda (errcode) errcode)))) | |
171 | @end lisp | |
172 | ||
173 | The problem is, on what port will @samp{fnord} be displayed? You | |
174 | might expect that because of the @code{with-output-to-port} that | |
175 | it will be displayed on the port bound to @code{some-port}. But it | |
176 | probably won't -- before evaluating the thunk, dynamic winds are | |
177 | unwound, including those created by @code{with-output-to-port}. | |
178 | So, the standard output port will have been re-set to its default value | |
179 | before @code{display} is evaluated. | |
180 | ||
181 | (This function was added to Guile mostly to help calls to functions in C | |
182 | libraries that can not tolerate non-local exits or calls that return | |
183 | multiple times. If such functions call back to the interpreter, it should | |
184 | be under a new dynamic root.) | |
185 | @end deffn | |
186 | ||
187 | ||
188 | @deffn primitive dynamic-root | |
189 | Return an object representing the current dynamic root. | |
190 | ||
191 | These objects are only useful for comparison using @code{eq?}. | |
192 | They are currently represented as numbers, but your code should | |
193 | in no way depend on this. | |
194 | @end deffn | |
195 | ||
196 | @c begin (scm-doc-string "boot-9.scm" "quit") | |
197 | @deffn procedure quit [exit_val] | |
198 | Throw back to the error handler of the current dynamic root. | |
199 | ||
200 | If integer @var{exit_val} is specified and if Guile is being used | |
201 | stand-alone and if quit is called from the initial dynamic-root, | |
202 | @var{exit_val} becomes the exit status of the Guile process and the | |
203 | process exits. | |
204 | @end deffn | |
205 | ||
206 | When Guile is run interactively, errors are caught from within the | |
207 | read-eval-print loop. An error message will be printed and @code{abort} | |
208 | called. A default set of signal handlers is installed, e.g., to allow | |
209 | user interrupt of the interpreter. | |
210 | ||
211 | It is possible to switch to a "batch mode", in which the interpreter | |
212 | will terminate after an error and in which all signals cause their | |
213 | default actions. Switching to batch mode causes any handlers installed | |
214 | from Scheme code to be removed. An example of where this is useful is | |
215 | after forking a new process intended to run non-interactively. | |
216 | ||
217 | @c begin (scm-doc-string "boot-9.scm" "batch-mode?") | |
218 | @deffn procedure batch-mode? | |
219 | Returns a boolean indicating whether the interpreter is in batch mode. | |
220 | @end deffn | |
221 | ||
222 | @c begin (scm-doc-string "boot-9.scm" "set-batch-mode?!") | |
223 | @deffn procedure set-batch-mode?! arg | |
224 | If @var{arg} is true, switches the interpreter to batch mode. | |
225 | The @code{#f} case has not been implemented. | |
226 | @end deffn | |
227 | ||
228 | @node Threads | |
229 | @section Threads | |
230 | @cindex threads | |
231 | @cindex Guile threads | |
232 | ||
233 | @strong{[NOTE: this chapter was written for Cygnus Guile and has not yet | |
234 | been updated for the Guile 1.x release.]} | |
235 | ||
236 | Here is a the reference for Guile's threads. In this chapter I simply | |
237 | quote verbatim Tom Lord's description of the low-level primitives | |
238 | written in C (basically an interface to the POSIX threads library) and | |
239 | Anthony Green's description of the higher-level thread procedures | |
240 | written in scheme. | |
241 | @cindex posix threads | |
242 | @cindex Lord, Tom | |
243 | @cindex Green, Anthony | |
244 | ||
245 | When using Guile threads, keep in mind that each guile thread is | |
246 | executed in a new dynamic root. | |
247 | ||
248 | @menu | |
249 | * Low level thread primitives:: | |
250 | * Higher level thread procedures:: | |
251 | @end menu | |
252 | ||
253 | ||
254 | @node Low level thread primitives | |
255 | @subsection Low level thread primitives | |
256 | ||
257 | @c NJFIXME no current mechanism for making sure that these docstrings | |
258 | @c are in sync. | |
259 | ||
260 | @c begin (texi-doc-string "guile" "call-with-new-thread") | |
261 | @deffn primitive call-with-new-thread thunk error-handler | |
262 | Evaluate @code{(thunk)} in a new thread, and new dynamic context, | |
263 | returning a new thread object representing the thread. | |
264 | ||
265 | If an error occurs during evaluation, call error-handler, passing it an | |
266 | error code describing the condition. [Error codes are currently | |
267 | meaningless integers. In the future, real values will be specified.] | |
268 | If this happens, the error-handler is called outside the scope of the new | |
269 | root -- it is called in the same dynamic context in which | |
270 | with-new-thread was evaluated, but not in the caller's thread. | |
271 | ||
272 | All the evaluation rules for dynamic roots apply to threads. | |
273 | @end deffn | |
274 | ||
275 | @c begin (texi-doc-string "guile" "join-thread") | |
276 | @deffn primitive join-thread thread | |
277 | Suspend execution of the calling thread until the target @var{thread} | |
278 | terminates, unless the target @var{thread} has already terminated. | |
279 | @end deffn | |
280 | ||
281 | @c begin (texi-doc-string "guile" "yield") | |
282 | @deffn primitive yield | |
283 | If one or more threads are waiting to execute, calling yield forces an | |
284 | immediate context switch to one of them. Otherwise, yield has no effect. | |
285 | @end deffn | |
286 | ||
287 | @c begin (texi-doc-string "guile" "make-mutex") | |
288 | @deffn primitive make-mutex | |
289 | Create a new mutex object. | |
290 | @end deffn | |
291 | ||
292 | @c begin (texi-doc-string "guile" "lock-mutex") | |
293 | @deffn primitive lock-mutex mutex | |
294 | Lock @var{mutex}. If the mutex is already locked, the calling thread | |
295 | blocks until the mutex becomes available. The function returns when | |
296 | the calling thread owns the lock on @var{mutex}. | |
297 | @end deffn | |
298 | ||
299 | @c begin (texi-doc-string "guile" "unlock-mutex") | |
300 | @deffn primitive unlock-mutex mutex | |
301 | Unlocks @var{mutex} if the calling thread owns the lock on @var{mutex}. | |
302 | Calling unlock-mutex on a mutex not owned by the current thread results | |
303 | in undefined behaviour. Once a mutex has been unlocked, one thread | |
304 | blocked on @var{mutex} is awakened and grabs the mutex lock. | |
305 | @end deffn | |
306 | ||
307 | @c begin (texi-doc-string "guile" "make-condition-variable") | |
308 | @deffn primitive make-condition-variable | |
309 | @end deffn | |
310 | ||
311 | @c begin (texi-doc-string "guile" "wait-condition-variable") | |
312 | @deffn primitive wait-condition-variable cond-var mutex | |
313 | @end deffn | |
314 | ||
315 | @c begin (texi-doc-string "guile" "signal-condition-variable") | |
316 | @deffn primitive signal-condition-variable cond-var | |
317 | @end deffn | |
318 | ||
319 | ||
320 | @node Higher level thread procedures | |
321 | @subsection Higher level thread procedures | |
322 | ||
323 | @c new by ttn, needs review | |
324 | ||
325 | Higher level thread procedures are available by loading the | |
326 | @code{(ice-9 threads)} module. These provide standardized | |
327 | thread creation and mutex interaction. | |
328 | ||
329 | @deffn primitive %thread-handler tag args@dots{} | |
330 | ||
331 | This procedure is specified as the standard error-handler for | |
332 | @code{make-thread} and @code{begin-thread}. If the number of @var{args} | |
333 | is three or more, use @code{display-error}, otherwise display a message | |
334 | "uncaught throw to @var{tag}". All output is sent to the port specified | |
335 | by @code{current-error-port}. | |
336 | ||
337 | Before display, global var @code{the-last-stack} is set to @code{#f} | |
338 | and signals are unmasked with @code{unmask-signals}. | |
339 | ||
340 | [FIXME: Why distinguish based on number of args?! Cue voodoo music here.] | |
341 | @end deffn | |
342 | ||
343 | @deffn macro make-thread proc [args@dots{}] | |
344 | Apply @var{proc} to @var{args} in a new thread formed by | |
345 | @code{call-with-new-thread} using @code{%thread-handler} as the error | |
346 | handler. | |
347 | @end deffn | |
348 | ||
349 | @deffn macro begin-thread first [rest@dots{}] | |
350 | Evaluate forms @var{first} and @var{rest} in a new thread formed by | |
351 | @code{call-with-new-thread} using @code{%thread-handler} as the error | |
352 | handler. | |
353 | @end deffn | |
354 | ||
355 | @deffn macro with-mutex m [body@dots{}] | |
356 | Lock mutex @var{m}, evaluate @var{body}, and then unlock @var{m}. | |
357 | These sub-operations form the branches of a @code{dynamic-wind}. | |
358 | @end deffn | |
359 | ||
360 | @deffn macro monitor first [rest@dots{}] | |
361 | Evaluate forms @var{first} and @var{rest} under a newly created | |
362 | anonymous mutex, using @code{with-mutex}. | |
363 | ||
364 | [FIXME: Is there any way to access the mutex?] | |
365 | @end deffn | |
366 | ||
367 | ||
368 | @node Fluids | |
369 | @section Fluids | |
370 | ||
371 | @cindex fluids | |
372 | ||
373 | @c FIXME::martin: Review me! | |
374 | ||
375 | Fluids are objects to store values in. They have a few properties which | |
376 | make them useful in certain situations: Fluids can have one value per | |
377 | dynamic root (@pxref{Dynamic Roots}), so that changes to the value in a | |
378 | fluid are only visible in the same dynamic root. Since threads are | |
379 | executed in separate dynamic roots, fluids can be used for thread local | |
380 | storage (@pxref{Threads}). | |
381 | ||
382 | Fluids can be used to simulate dynamically scoped variables. These are | |
383 | used in several (especially in older) dialects of lisp, such as in Emacs | |
384 | Lisp, and they work a bit like global variables in that they can be | |
385 | modified by the caller of a procedure, and the called procedure will see | |
386 | the changes. With lexically scoped variables---which are normally used | |
387 | in Scheme---this cannot happen. See the description of | |
388 | @code{with-fluids*} below for details. | |
389 | ||
390 | New fluids are created with @code{make-fluid} and @code{fluid?} is used | |
391 | for testing whether an object is actually a fluid. | |
392 | ||
393 | @deffn primitive make-fluid | |
394 | Return a newly created fluid. | |
395 | Fluids are objects of a certain type (a smob) that can hold one SCM | |
396 | value per dynamic root. That is, modifications to this value are | |
397 | only visible to code that executes within the same dynamic root as | |
398 | the modifying code. When a new dynamic root is constructed, it | |
399 | inherits the values from its parent. Because each thread executes | |
400 | in its own dynamic root, you can use fluids for thread local storage. | |
401 | @end deffn | |
402 | ||
403 | @deffn primitive fluid? obj | |
404 | Return @code{#t} iff @var{obj} is a fluid; otherwise, return | |
405 | @code{#f}. | |
406 | @end deffn | |
407 | ||
408 | The values stored in a fluid can be accessed with @code{fluid-ref} and | |
409 | @code{fluid-set!}. | |
410 | ||
411 | @deffn primitive fluid-ref fluid | |
412 | Return the value associated with @var{fluid} in the current | |
413 | dynamic root. If @var{fluid} has not been set, then return | |
414 | @code{#f}. | |
415 | @end deffn | |
416 | ||
417 | @deffn primitive fluid-set! fluid value | |
418 | Set the value associated with @var{fluid} in the current dynamic root. | |
419 | @end deffn | |
420 | ||
421 | @code{with-fluids*} temporarily changes the values of one or more fluids, | |
422 | so that the given procedure and each procedure called by it access the | |
423 | given values. After the procedure returns, the old values are restored. | |
424 | ||
425 | @deffn primitive with-fluids* fluids values thunk | |
426 | Set @var{fluids} to @var{values} temporary, and call @var{thunk}. | |
427 | @var{fluids} must be a list of fluids and @var{values} must be the same | |
428 | number of their values to be applied. Each substitution is done | |
429 | one after another. @var{thunk} must be a procedure with no argument. | |
430 | @end deffn | |
431 | ||
432 | ||
433 | @c Local Variables: | |
434 | @c TeX-master: "guile.texi" | |
435 | @c End: |