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