diff options
author | Marius Vollmer <mvo@zagadka.de> | 2004-08-02 12:29:00 +0000 |
---|---|---|
committer | Marius Vollmer <mvo@zagadka.de> | 2004-08-02 12:29:00 +0000 |
commit | 07d83abe7b8b617e4bb70a08efc0c0f6999fa0cc (patch) | |
tree | 34c8a7b9d98000169379038be8551ed44c0bdb83 /doc/ref/api-scheduling.texi | |
parent | 237be238424f1b6d130799ad931ba6fa8504a97c (diff) | |
download | guile-07d83abe7b8b617e4bb70a08efc0c0f6999fa0cc.tar.gz |
* scheme-binding.texi: Renamed to api-binding.texi.
* scheme-compound.texi: Renamed to api-compound.texi.
* scheme-control.texi: Renamed to api-control.texi.
* scheme-data.texi: Renamed to api-data.texi.
* scheme-debug.texi: Renamed to api-debug.texi.
* deprecated.texi: Renamed to api-deprecated.texi.
* scheme-evaluation.texi: Renamed to api-evaluation.texi.
* ref-init.texi: Renamed to api-init.texi.
* scheme-io.texi: Renamed to api-io.texi.
* scheme-memory.texi: Renamed to api-memory.texi.
* scheme-modules.texi: Renamed to api-modules.texi.
* scheme-options.texi: Renamed to api-options.texi.
* scm.texi: Renamed to api-overview.texi.
* scheme-procedures.texi: Renamed to api-procedures.texi.
* scheme-scheduling.texi: Renamed to api-scheduling.texi.
* scheme-scm.texi: Renamed to api-scm.texi.
* scheme-smobs.texi: Renamed to api-smobs.texi.
* scheme-snarf.texi: Renamed to api-snarf.texi.
* scheme-translation.texi: Renamed to api-translation.texi.
* scheme-utility.texi: Renamed to api-utility.texi.
* debugging.texi: Renamed to scheme-debugging.texi.
* scripts.texi: Renamed to scheme-scripts.texi.
* program.texi: Renamed to libguile-program.texi.
Diffstat (limited to 'doc/ref/api-scheduling.texi')
-rw-r--r-- | doc/ref/api-scheduling.texi | 863 |
1 files changed, 863 insertions, 0 deletions
diff --git a/doc/ref/api-scheduling.texi b/doc/ref/api-scheduling.texi new file mode 100644 index 000000000..c5e652030 --- /dev/null +++ b/doc/ref/api-scheduling.texi @@ -0,0 +1,863 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@page +@node Scheduling +@section Threads, Mutexes, Asyncs and Dynamic Roots + +[FIXME: This is pasted in from Tom Lord's original guile.texi chapter +plus the Cygnus programmer's manual; it should be *very* carefully +reviewed and largely reorganized.] + +@menu +* Arbiters:: Synchronization primitives. +* Asyncs:: Asynchronous procedure invocation. +* Dynamic Roots:: Root frames of execution. +* Threads:: Multiple threads of execution. +* Fluids:: Thread-local variables. +* Futures:: Delayed execution in new threads. +* Parallel Forms:: Parallel execution of forms. +@end menu + + +@node Arbiters +@subsection Arbiters + +@cindex arbiters + +@c FIXME::martin: Review me! + +Arbiters are synchronization objects. They are created with +@code{make-arbiter}. Two or more threads can synchronize on an arbiter +by trying to lock it using @code{try-arbiter}. This call will succeed +if no other thread has called @code{try-arbiter} on the arbiter yet, +otherwise it will fail and return @code{#f}. Once an arbiter is +successfully locked, it cannot be locked by another thread until the +thread holding the arbiter calls @code{release-arbiter} to unlock it. + +@deffn {Scheme Procedure} make-arbiter name +@deffnx {C Function} scm_make_arbiter (name) +Return an object of type arbiter and name @var{name}. Its +state is initially unlocked. Arbiters are a way to achieve +process synchronization. +@end deffn + +@deffn {Scheme Procedure} try-arbiter arb +@deffnx {C Function} scm_try_arbiter (arb) +Return @code{#t} and lock the arbiter @var{arb} if the arbiter +was unlocked. Otherwise, return @code{#f}. +@end deffn + +@deffn {Scheme Procedure} release-arbiter arb +@deffnx {C Function} scm_release_arbiter (arb) +Return @code{#t} and unlock the arbiter @var{arb} if the +arbiter was locked. Otherwise, return @code{#f}. +@end deffn + + +@node Asyncs +@subsection Asyncs + +@cindex asyncs +@cindex user asyncs +@cindex system asyncs + +Asyncs are a means of deferring the excution of Scheme code until it is +safe to do so. + +Guile provides two kinds of asyncs that share the basic concept but are +otherwise quite different: system asyncs and user asyncs. System asyncs +are integrated into the core of Guile and are executed automatically +when the system is in a state to allow the execution of Scheme code. +For example, it is not possible to execute Scheme code in a POSIX signal +handler, but such a signal handler can queue a system async to be +executed in the near future, when it is safe to do so. + +System asyncs can also be queued for threads other than the current one. +This way, you can cause threads to asynchronously execute arbitrary +code. + +User asyncs offer a convenient means of queueing procedures for future +execution and triggering this execution. They will not be executed +automatically. + +@menu +* System asyncs:: +* User asyncs:: +@end menu + +@node System asyncs +@subsubsection System asyncs + +To cause the future asynchronous execution of a procedure in a given +thread, use @code{system-async-mark}. + +Automatic invocation of system asyncs can be temporarily disabled by +calling @code{call-with-blocked-asyncs}. This function works by +temporarily increasing the @emph{async blocking level} of the current +thread while a given procedure is running. The blocking level starts +out at zero, and whenever a safe point is reached, a blocking level +greater than zero will prevent the execution of queued asyncs. + +Analogously, the procedure @code{call-with-unblocked-asyncs} will +temporarily decrease the blocking level of the current thread. You +can use it when you want to disable asyncs by default and only allow +them temporarily. + +In addition to the C versions of @code{call-with-blocked-asyncs} and +@code{call-with-unblocked-asyncs}, C code can use +@code{scm_with_blocked_asyncs} and @code{scm_with_unblocked_asyncs} +inside a @dfn{frame} (@pxref{Frames}) to block or unblock system asyncs +temporarily. + +@deffn {Scheme Procedure} system-async-mark proc [thread] +@deffnx {C Function} scm_system_async_mark (proc) +@deffnx {C Function} scm_system_async_mark_for_thread (proc, thread) +Mark @var{proc} (a procedure with zero arguments) for future execution +in @var{thread}. When @var{proc} has already been marked for +@var{thread} but has not been executed yet, this call has no effect. +When @var{thread} is omitted, the thread that called +@code{system-async-mark} is used. + +This procedure is not safe to be called from signal handlers. Use +@code{scm_sigaction} or @code{scm_sigaction_for_thread} to install +signal handlers. +@end deffn + +@c FIXME: The use of @deffnx for scm_c_call_with_blocked_asyncs and +@c scm_c_call_with_unblocked_asyncs puts "void" into the function +@c index. Would prefer to use @deftypefnx if makeinfo allowed that, +@c or a @deftypefn with an empty return type argument if it didn't +@c introduce an extra space. + +@deffn {Scheme Procedure} call-with-blocked-asyncs proc +@deffnx {C Function} scm_call_with_blocked_asyncs (proc) +@deffnx {C Function} void *scm_c_call_with_blocked_asyncs (void * (*proc) (void *data), void *data) +@findex scm_c_call_with_blocked_asyncs +Call @var{proc} and block the execution of system asyncs by one level +for the current thread while it is running. Return the value returned +by @var{proc}. For the first two variants, call @var{proc} with no +arguments; for the third, call it with @var{data}. +@end deffn + +@deffn {Scheme Procedure} call-with-unblocked-asyncs proc +@deffnx {C Function} scm_call_with_unblocked_asyncs (proc) +@deffnx {C Function} void *scm_c_call_with_unblocked_asyncs (void *(*p) (void *d), void *d) +@findex scm_c_call_with_unblocked_asyncs +Call @var{proc} and unblock the execution of system asyncs by one +level for the current thread while it is running. Return the value +returned by @var{proc}. For the first two variants, call @var{proc} +with no arguments; for the third, call it with @var{data}. +@end deffn + +@deftypefn {C Function} void scm_frame_block_asyncs () +This function must be used inside a pair of calls to +@code{scm_frame_begin} and @code{scm_frame_end} (@pxref{Frames}). +During the dynamic extent of the frame, asyncs are blocked by one level. +@end deftypefn + +@deftypefn {C Function} void scm_frame_unblock_asyncs () +This function must be used inside a pair of calls to +@code{scm_frame_begin} and @code{scm_frame_end} (@pxref{Frames}). +During the dynamic extent of the frame, asyncs are unblocked by one +level. +@end deftypefn + +@node User asyncs +@subsubsection User asyncs + +A user async is a pair of a thunk (a parameterless procedure) and a +mark. Setting the mark on a user async will cause the thunk to be +executed when the user async is passed to @code{run-asyncs}. Setting +the mark more than once is satisfied by one execution of the thunk. + +User asyncs are created with @code{async}. They are marked with +@code{async-mark}. + +@deffn {Scheme Procedure} async thunk +@deffnx {C Function} scm_async (thunk) +Create a new user async for the procedure @var{thunk}. +@end deffn + +@deffn {Scheme Procedure} async-mark a +@deffnx {C Function} scm_async_mark (a) +Mark the user async @var{a} for future execution. +@end deffn + +@deffn {Scheme Procedure} run-asyncs list_of_a +@deffnx {C Function} scm_run_asyncs (list_of_a) +Execute all thunks from the marked asyncs of the list @var{list_of_a}. +@end deffn + + +@node Dynamic Roots +@subsection Dynamic Roots +@cindex dynamic roots + +A @dfn{dynamic root} is a root frame of Scheme evaluation. +The top-level repl, for example, is an instance of a dynamic root. + +Each dynamic root has its own chain of dynamic-wind information. Each +has its own set of continuations, jump-buffers, and pending CATCH +statements which are inaccessible from the dynamic scope of any +other dynamic root. + +In a thread-based system, each thread has its own dynamic root. Therefore, +continuations created by one thread may not be invoked by another. + +Even in a single-threaded system, it is sometimes useful to create a new +dynamic root. For example, if you want to apply a procedure, but to +not allow that procedure to capture the current continuation, calling +the procedure under a new dynamic root will do the job. + +@deffn {Scheme Procedure} call-with-dynamic-root thunk handler +@deffnx {C Function} scm_call_with_dynamic_root (thunk, handler) +Evaluate @code{(thunk)} in a new dynamic context, returning its value. + +If an error occurs during evaluation, apply @var{handler} to the +arguments to the throw, just as @code{throw} would. If this happens, +@var{handler} is called outside the scope of the new root -- it is +called in the same dynamic context in which +@code{call-with-dynamic-root} was evaluated. + +If @var{thunk} captures a continuation, the continuation is rooted at +the call to @var{thunk}. In particular, the call to +@code{call-with-dynamic-root} is not captured. Therefore, +@code{call-with-dynamic-root} always returns at most one time. + +Before calling @var{thunk}, the dynamic-wind chain is un-wound back to +the root and a new chain started for @var{thunk}. Therefore, this call +may not do what you expect: + +@lisp +;; Almost certainly a bug: +(with-output-to-port + some-port + + (lambda () + (call-with-dynamic-root + (lambda () + (display 'fnord) + (newline)) + (lambda (errcode) errcode)))) +@end lisp + +The problem is, on what port will @samp{fnord} be displayed? You +might expect that because of the @code{with-output-to-port} that +it will be displayed on the port bound to @code{some-port}. But it +probably won't -- before evaluating the thunk, dynamic winds are +unwound, including those created by @code{with-output-to-port}. +So, the standard output port will have been re-set to its default value +before @code{display} is evaluated. + +(This function was added to Guile mostly to help calls to functions in C +libraries that can not tolerate non-local exits or calls that return +multiple times. If such functions call back to the interpreter, it should +be under a new dynamic root.) +@end deffn + + +@deffn {Scheme Procedure} dynamic-root +@deffnx {C Function} scm_dynamic_root () +Return an object representing the current dynamic root. + +These objects are only useful for comparison using @code{eq?}. +They are currently represented as numbers, but your code should +in no way depend on this. +@end deffn + +@c begin (scm-doc-string "boot-9.scm" "quit") +@deffn {Scheme Procedure} quit [exit_val] +Throw back to the error handler of the current dynamic root. + +If integer @var{exit_val} is specified and if Guile is being used +stand-alone and if quit is called from the initial dynamic-root, +@var{exit_val} becomes the exit status of the Guile process and the +process exits. +@end deffn + +When Guile is run interactively, errors are caught from within the +read-eval-print loop. An error message will be printed and @code{abort} +called. A default set of signal handlers is installed, e.g., to allow +user interrupt of the interpreter. + +It is possible to switch to a "batch mode", in which the interpreter +will terminate after an error and in which all signals cause their +default actions. Switching to batch mode causes any handlers installed +from Scheme code to be removed. An example of where this is useful is +after forking a new process intended to run non-interactively. + +@c begin (scm-doc-string "boot-9.scm" "batch-mode?") +@deffn {Scheme Procedure} batch-mode? +Returns a boolean indicating whether the interpreter is in batch mode. +@end deffn + +@c begin (scm-doc-string "boot-9.scm" "set-batch-mode?!") +@deffn {Scheme Procedure} set-batch-mode?! arg +If @var{arg} is true, switches the interpreter to batch mode. +The @code{#f} case has not been implemented. +@end deffn + +@node Threads +@subsection Threads +@cindex threads +@cindex Guile threads +@cindex POSIX threads + +Guile threads are implemented using POSIX threads, they run +pre-emptively and concurrently through both Scheme code and system +calls. The only exception is for garbage collection, where all +threads must rendezvous. + +@menu +* Low level thread primitives:: +* Higher level thread procedures:: +* C level thread interface:: +@end menu + + +@node Low level thread primitives +@subsubsection Low level thread primitives + +@c NJFIXME no current mechanism for making sure that these docstrings +@c are in sync. + +@c begin (texi-doc-string "guile" "call-with-new-thread") +@deffn {Scheme Procedure} call-with-new-thread thunk error-handler +Evaluate @code{(thunk)} in a new thread, and new dynamic context, +returning a new thread object representing the thread. + +If an error occurs during evaluation, call error-handler, passing it +an error code. If this happens, the error-handler is called outside +the scope of the new root -- it is called in the same dynamic context +in which with-new-thread was evaluated, but not in the caller's +thread. + +All the evaluation rules for dynamic roots apply to threads. +@end deffn + +@c begin (texi-doc-string "guile" "join-thread") +@deffn {Scheme Procedure} join-thread thread +Suspend execution of the calling thread until the target @var{thread} +terminates, unless the target @var{thread} has already terminated. +@end deffn + +@c begin (texi-doc-string "guile" "yield") +@deffn {Scheme Procedure} yield +If one or more threads are waiting to execute, calling yield forces an +immediate context switch to one of them. Otherwise, yield has no effect. +@end deffn + +@c begin (texi-doc-string "guile" "make-mutex") +@deffn {Scheme Procedure} make-mutex +Create a new mutex object. +@end deffn + +@c begin (texi-doc-string "guile" "lock-mutex") +@deffn {Scheme Procedure} lock-mutex mutex +Lock @var{mutex}. If the mutex is already locked, the calling thread +blocks until the mutex becomes available. The function returns when +the calling thread owns the lock on @var{mutex}. Locking a mutex that +a thread already owns will succeed right away and will not block the +thread. That is, Guile's mutexes are @emph{recursive}. + +When a system async is activated for a thread that is blocked in a +call to @code{lock-mutex}, the waiting is interrupted and the async is +executed. When the async returns, the waiting is resumed. +@end deffn + +@deffn {Scheme Procedure} try-mutex mutex +Try to lock @var{mutex}. If the mutex is already locked by someone +else, return @code{#f}. Else lock the mutex and return @code{#t}. +@end deffn + +@c begin (texi-doc-string "guile" "unlock-mutex") +@deffn {Scheme Procedure} unlock-mutex mutex +Unlocks @var{mutex} if the calling thread owns the lock on +@var{mutex}. Calling unlock-mutex on a mutex not owned by the current +thread results in undefined behaviour. Once a mutex has been unlocked, +one thread blocked on @var{mutex} is awakened and grabs the mutex +lock. Every call to @code{lock-mutex} by this thread must be matched +with a call to @code{unlock-mutex}. Only the last call to +@code{unlock-mutex} will actually unlock the mutex. +@end deffn + +@c begin (texi-doc-string "guile" "make-condition-variable") +@deffn {Scheme Procedure} make-condition-variable +Make a new condition variable. +@end deffn + +@c begin (texi-doc-string "guile" "wait-condition-variable") +@deffn {Scheme Procedure} wait-condition-variable cond-var mutex [time] +Wait until @var{cond-var} has been signalled. While waiting, +@var{mutex} is atomically unlocked (as with @code{unlock-mutex}) and +is locked again when this function returns. When @var{time} is given, +it specifies a point in time where the waiting should be aborted. It +can be either a integer as returned by @code{current-time} or a pair +as returned by @code{gettimeofday}. When the waiting is aborted, +@code{#f} is returned. When the condition variable has in fact been +signalled, @code{#t} is returned. The mutex is re-locked in any case +before @code{wait-condition-variable} returns. + +When a system async is activated for a thread that is blocked in a +call to @code{wait-condition-variable}, the waiting is interrupted, +the mutex is locked, and the async is executed. When the async +returns, the mutex is unlocked again and the waiting is resumed. +@end deffn + +@c begin (texi-doc-string "guile" "signal-condition-variable") +@deffn {Scheme Procedure} signal-condition-variable cond-var +Wake up one thread that is waiting for @var{cv}. +@end deffn + +@c begin (texi-doc-string "guile" "broadcast-condition-variable") +@deffn {Scheme Procedure} broadcast-condition-variable cond-var +Wake up all threads that are waiting for @var{cv}. +@end deffn + +@node Higher level thread procedures +@subsubsection Higher level thread procedures + +@c new by ttn, needs review + +Higher level thread procedures are available by loading the +@code{(ice-9 threads)} module. These provide standardized +thread creation and mutex interaction. + +@deffn macro make-thread proc [args@dots{}] +Apply @var{proc} to @var{args} in a new thread formed by +@code{call-with-new-thread} using a default error handler that display +the error to the current error port. +@end deffn + +@deffn macro begin-thread first [rest@dots{}] +Evaluate forms @var{first} and @var{rest} in a new thread formed by +@code{call-with-new-thread} using a default error handler that display +the error to the current error port. +@end deffn + +@deffn macro with-mutex m [body@dots{}] +Lock mutex @var{m}, evaluate @var{body}, and then unlock @var{m}. +These sub-operations form the branches of a @code{dynamic-wind}. +@end deffn + +@deffn macro monitor body@dots{} +Evaluate @var{body}, with a mutex locked so only one thread can +execute that code at any one time. Each @code{monitor} form has its +own private mutex and the locking is done as per @code{with-mutex} +above. The return value is the return from the last form in +@var{body}. + +The term ``monitor'' comes from operating system theory, where it +means a particular bit of code managing access to some resource and +which only ever executes on behalf of one process at any one time. +@end deffn + +@node C level thread interface +@subsubsection C level thread interface + +You can create and manage threads, mutexes, and condition variables +with the C versions of the primitives above. For example, you can +create a mutex with @code{scm_make_mutex} and lock it with +@code{scm_lock_mutex}. In addition to these primitives there is also +a second set of primitives for threading related things. These +functions and data types are only available from C and can not be +mixed with the first set from above. However, they might be more +efficient and can be used in situations where Scheme data types are +not allowed or are inconvenient to use. + +Furthermore, they are the primitives that Guile relies on for its own +higher level threads. By reimplementing them, you can adapt Guile to +different low-level thread implementations. + +C code in a thread must call a libguile function periodically. When +one thread finds garbage collection is required, it waits for all +threads to rendezvous before doing that GC. Such a rendezvous is +checked within libguile functions. If C code wants to sleep or block +in a thread it should use one of the libguile functions provided. + +Only threads created by Guile can use the libguile functions. Threads +created directly with say @code{pthread_create} are unknown to Guile +and they cannot call libguile. The stack in such foreign threads is +not scanned during GC, so @code{SCM} values generally cannot be held +there. + +@c FIXME: +@c +@c Describe SCM_TICK which can be called if no other libguile +@c function is being used by a C function. +@c +@c Describe "Guile mode", which a thread can enter and exit. There +@c are no functions for doing this yet. +@c +@c When in guile mode a thread can call libguile, is subject to the +@c tick rule, and its stack is scanned. When not in guile mode it +@c cannot call libguile, it doesn't have to tick, and its stack is +@c not scanned. The strange guile control flow things like +@c exceptions, continuations and asyncs only occur when in guile +@c mode. +@c +@c When guile mode is exited, the portion of the stack allocated +@c while it was in guile mode is still scanned. This portion may not +@c be modified when outside guile mode. The stack ends up +@c partitioned into alternating guile and non-guile regions. +@c +@c Leaving guile mode is convenient when running an extended +@c calculation not involving guile, since one doesn't need to worry +@c about SCM_TICK calls. + + +@deftp {C Data Type} scm_t_thread +This data type represents a thread, to be used with scm_thread_create, +etc. +@end deftp + +@deftypefn {C Function} int scm_thread_create (scm_t_thread *t, void (*proc)(void *), void *data) +Create a new thread that will start by calling @var{proc}, passing it +@var{data}. A handle for the new thread is stored in @var{t}, which +must be non-NULL. The thread terminated when @var{proc} returns. +When the thread has not been detached, its handle remains valid after +is has terminated so that it can be used with @var{scm_thread_join}, +for example. When it has been detached, the handle becomes invalid as +soon as the thread terminates. +@end deftypefn + +@deftypefn {C Function} void scm_thread_detach (scm_t_thread t) +Detach the thread @var{t}. See @code{scm_thread_create}. +@end deftypefn + +@deftypefn {C Function} void scm_thread_join (scm_t_thread t) +Wait for thread @var{t} to terminate. The thread must not have been +detached at the time that @code{scm_thread_join} is called, but it +might have been detached by the time it terminates. +@end deftypefn + +@deftypefn {C Function} scm_t_thread scm_thread_self () +Return the handle of the calling thread. +@end deftypefn + +@deftp {C Data Type} scm_t_mutex +This data type represents a mutex, to be used with scm_mutex_init, +etc. +@end deftp + +@deftypefn {C Function} void scm_mutex_init (scm_t_mutex *m) +Initialize the mutex structure pointed to by @var{m}. +@end deftypefn + +@deftypefn {C Function} void scm_mutex_destroy (scm_t_mutex *m) +Deallocate all resources associated with @var{m}. +@end deftypefn + +@deftypefn {C Function} void scm_mutex_lock (scm_t_mutex *m) +Lock the mutex @var{m}. When it is already locked by a different +thread, wait until it becomes available. Locking a mutex that is +already locked by the current threads is not allowd and results in +undefined behavior. The mutices are not guaranteed to be fair. That +is, a thread that attempts a lock after yourself might be granted it +before you. +@end deftypefn + +@deftypefn {C Function} int scm_mutex_trylock (scm_t_mutex *m) +Lock @var{m} as with @code{scm_mutex_lock} but don't wait when this +does succeed immediately. Returns non-zero when the mutex could in +fact be locked , and zero when it is already locked by some other +thread. +@end deftypefn + +@deftypefn {C Function} void scm_mutex_unlock (scm_t_mutex *m) +Unlock the mutex @var{m}. The mutex must have been locked by the +current thread, else the behavior is undefined. +@end deftypefn + +@deftp {C Data Type} scm_t_cond +This data type represents a condition variable, to be used with +scm_cond_init, etc. +@end deftp + +@deftypefn {C Function} void scm_cond_init (scm_t_cond *c) +Initialize the mutex structure pointed to by @var{c}. +@end deftypefn + +@deftypefn {C Function} void scm_cond_destroy (scm_t_cond *c) +Deallocate all resources associated with @var{c}. +@end deftypefn + +@deftypefn {C Function} void scm_cond_wait (scm_t_cond *c, scm_t_mutex *m) +Wait for @var{c} to be signalled. While waiting @var{m} is unlocked +and locked again before @code{scm_cond_wait} returns. +@end deftypefn + +@deftypefn {C Function} void scm_cond_timedwait (scm_t_cond *c, scm_t_mutex *m, timespec *abstime) +Wait for @var{c} to be signalled as with @code{scm_cond_wait} but +don't wait longer than the point in time specified by @var{abstime}. +when the waiting is aborted, zero is returned; non-zero else. +@end deftypefn + +@deftypefn {C Function} void scm_cond_signal (scm_t_cond *c) +Signal the condition variable @var{c}. When one or more threads are +waiting for it to be signalled, select one arbitrarily and let its +wait succeed. +@end deftypefn + +@deftypefn {C Function} void scm_cond_broadcast (scm_t_cond *c) +Signal the condition variable @var{c}. When there are threads waiting +for it to be signalled, wake them all up and make all their waits +succeed. +@end deftypefn + +@deftp {C Type} scm_t_key +This type represents a key for a thread-specific value. +@end deftp + +@deftypefn {C Function} void scm_key_create (scm_t_key *keyp) +Create a new key for a thread-specific value. Each thread has its own +value associated to such a handle. The new handle is stored into +@var{keyp}, which must be non-NULL. +@end deftypefn + +@deftypefn {C Function} void scm_key_delete (scm_t_key key) +This function makes @var{key} invalid as a key for thread-specific data. +@end deftypefn + +@deftypefn {C Function} void scm_key_setspecific (scm_t_key key, const void *value) +Associate @var{value} with @var{key} in the calling thread. +@end deftypefn + +@deftypefn {C Function} int scm_key_getspecific (scm_t_key key) +Return the value currently associated with @var{key} in the calling +thread. When @code{scm_key_setspecific} has not yet been called in +this thread with this key, @code{NULL} is returned. +@end deftypefn + +@deftypefn {C Function} int scm_thread_select (...) +This function does the same thing as the system's @code{select} +function, but in a way that is friendly to the thread implementation. +You should call it in preference to the system @code{select}. +@end deftypefn + +@node Fluids +@subsection Fluids + +@cindex fluids + +Fluids are objects to store values in. They have a few properties +which make them useful in certain situations: Fluids can have one +value per dynamic root (@pxref{Dynamic Roots}), so that changes to the +value in a fluid are only visible in the same dynamic root. Since +threads are executed in separate dynamic roots, fluids can be used for +thread local storage (@pxref{Threads}). + +Fluids can be used to simulate the desirable effects of dynamically +scoped variables. Dynamically scoped variables are useful when you +want to set a variable to a value during some dynamic extent in the +execution of your program and have them revert to their original value +when the control flow is outside of this dynamic extent. See the +description of @code{with-fluids} below for details. + +New fluids are created with @code{make-fluid} and @code{fluid?} is +used for testing whether an object is actually a fluid. The values +stored in a fluid can be accessed with @code{fluid-ref} and +@code{fluid-set!}. + +@deffn {Scheme Procedure} make-fluid +@deffnx {C Function} scm_make_fluid () +Return a newly created fluid. +Fluids are objects of a certain type (a smob) that can hold one SCM +value per dynamic root. That is, modifications to this value are +only visible to code that executes within the same dynamic root as +the modifying code. When a new dynamic root is constructed, it +inherits the values from its parent. Because each thread executes +in its own dynamic root, you can use fluids for thread local storage. +@end deffn + +@deffn {Scheme Procedure} fluid? obj +@deffnx {C Function} scm_fluid_p (obj) +Return @code{#t} iff @var{obj} is a fluid; otherwise, return +@code{#f}. +@end deffn + +@deffn {Scheme Procedure} fluid-ref fluid +@deffnx {C Function} scm_fluid_ref (fluid) +Return the value associated with @var{fluid} in the current +dynamic root. If @var{fluid} has not been set, then return +@code{#f}. +@end deffn + +@deffn {Scheme Procedure} fluid-set! fluid value +@deffnx {C Function} scm_fluid_set_x (fluid, value) +Set the value associated with @var{fluid} in the current dynamic root. +@end deffn + +@code{with-fluids*} temporarily changes the values of one or more fluids, +so that the given procedure and each procedure called by it access the +given values. After the procedure returns, the old values are restored. + +@deffn {Scheme Procedure} with-fluids* fluids values thunk +@deffnx {C Function} scm_with_fluids (fluids, values, thunk) +Set @var{fluids} to @var{values} temporary, and call @var{thunk}. +@var{fluids} must be a list of fluids and @var{values} must be the +same number of their values to be applied. Each substitution is done +in the order given. @var{thunk} must be a procedure with no argument. +it is called inside a @code{dynamic-wind} and the fluids are +set/restored when control enter or leaves the established dynamic +extent. +@end deffn + +@deffn {Scheme Macro} with-fluids ((fluid value) ...) body... +Execute @var{body...} while each @var{fluid} is set to the +corresponding @var{value}. Both @var{fluid} and @var{value} are +evaluated and @var{fluid} must yield a fluid. @var{body...} is +executed inside a @code{dynamic-wind} and the fluids are set/restored +when control enter or leaves the established dynamic extent. +@end deffn + +@deftypefn {C Function} SCM scm_c_with_fluids (SCM fluids, SCM vals, SCM (*cproc)(void *), void *data) +@deftypefnx {C Function} SCM scm_c_with_fluid (SCM fluid, SCM val, SCM (*cproc)(void *), void *data) +The function @code{scm_c_with_fluids} is like @code{scm_with_fluids} +except that it takes a C function to call instead of a Scheme thunk. + +The function @code{scm_c_with_fluid} is similar but only allows one +fluid to be set instead of a list. +@end deftypefn + +@deftypefn {C Function} void scm_frame_fluid (SCM fluid, SCM val) +This function must be used inside a pair of calls to +@code{scm_frame_begin} and @code{scm_frame_end} (@pxref{Frames}). +During the dynamic extent of the frame, the fluid @var{fluid} is set +to @var{val}. + +More precisely, the value of the fluid is swapped with a `backup' +value whenever the frame is entered or left. The backup value is +initialized with the @var{val} argument. +@end deftypefn + +@node Futures +@subsection Futures +@cindex futures + +Futures are a convenient way to run a calculation in a new thread, and +only wait for the result when it's actually needed. + +Futures are similar to promises (@pxref{Delayed Evaluation}), in that +they allow mainline code to continue immediately. But @code{delay} +doesn't evaluate at all until forced, whereas @code{future} starts +immediately in a new thread. + +@deffn {syntax} future expr +Begin evaluating @var{expr} in a new thread, and return a ``future'' +object representing the calculation. +@end deffn + +@deffn {Scheme Procedure} make-future thunk +@deffnx {C Function} scm_make_future (thunk) +Begin evaluating the call @code{(@var{thunk})} in a new thread, and +return a ``future'' object representing the calculation. +@end deffn + +@deffn {Scheme Procedure} future-ref f +@deffnx {C Function} scm_future_ref (f) +Return the value computed by the future @var{f}. If @var{f} has not +yet finished executing then wait for it to do so. +@end deffn + + +@node Parallel Forms +@subsection Parallel forms +@cindex parallel forms + +The functions described in this section are available from + +@example +(use-modules (ice-9 threads)) +@end example + +@deffn syntax parallel expr1 @dots{} exprN +Evaluate each @var{expr} expression in parallel, each in a new thread. +Return the results as a set of @var{N} multiple values +(@pxref{Multiple Values}). +@end deffn + +@deffn syntax letpar ((var1 expr1) @dots{} (varN exprN)) body@dots{} +Evaluate each @var{expr} in parallel, each in a new thread, then bind +the results to the corresponding @var{var} variables and evaluate +@var{body}. + +@code{letpar} is like @code{let} (@pxref{Local Bindings}), but all the +expressions for the bindings are evaluated in parallel. +@end deffn + +@deffn {Scheme Procedure} par-map proc lst1 @dots{} lstN +@deffnx {Scheme Procedure} par-for-each proc lst1 @dots{} lstN +Call @var{proc} on the elements of the given lists. @code{par-map} +returns a list comprising the return values from @var{proc}. +@code{par-for-each} returns an unspecified value, but waits for all +calls to complete. + +The @var{proc} calls are @code{(@var{proc} @var{elem1} @dots{} +@var{elemN})}, where each @var{elem} is from the corresponding +@var{lst}. Each @var{lst} must be the same length. The calls are +made in parallel, each in a new thread. + +These functions are like @code{map} and @code{for-each} (@pxref{List +Mapping}), but make their @var{proc} calls in parallel. +@end deffn + +@deffn {Scheme Procedure} n-par-map n proc lst1 @dots{} lstN +@deffnx {Scheme Procedure} n-par-for-each n proc lst1 @dots{} lstN +Call @var{proc} on the elements of the given lists, in the same way as +@code{par-map} and @code{par-for-each} above, but use no more than +@var{n} new threads at any one time. The order in which calls are +initiated within that threads limit is unspecified. + +These functions are good for controlling resource consumption if +@var{proc} calls might be costly, or if there are many to be made. On +a dual-CPU system for instance @math{@var{n}=4} might be enough to +keep the CPUs utilized, and not consume too much memory. +@end deffn + +@deffn {Scheme Procedure} n-for-each-par-map n sproc pproc lst1 @dots{} lstN +Apply @var{pproc} to the elements of the given lists, and apply +@var{sproc} to each result returned by @var{pproc}. The final return +value is unspecified, but all calls will have been completed before +returning. + +The calls made are @code{(@var{sproc} (@var{pproc} @var{elem1} @dots{} +@var{elemN}))}, where each @var{elem} is from the corresponding +@var{lst}. Each @var{lst} must have the same number of elements. + +The @var{pproc} calls are made in parallel, in new threads. No more +than @var{n} new threads are used at any one time. The order in which +@var{pproc} calls are initiated within that limit is unspecified. + +The @var{sproc} calls are made serially, in list element order, one at +a time. @var{pproc} calls on later elements may execute in parallel +with the @var{sproc} calls. Exactly which thread makes each +@var{sproc} call is unspecified. + +This function is designed for individual calculations that can be done +in parallel, but with results needing to be handled serially, for +instance to write them to a file. The @var{n} limit on threads +controls system resource usage when there are many calculations or +when they might be costly. + +It will be seen that @code{n-for-each-par-map} is like a combination +of @code{n-par-map} and @code{for-each}, + +@example +(for-each sproc (n-par-map pproc lst1 ... lstN)) +@end example + +@noindent +But the actual implementation is more efficient since each @var{sproc} +call, in turn, can be initiated once the relevant @var{pproc} call has +completed, it doesn't need to wait for all to finish. +@end deffn + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: |