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