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