X-Git-Url: http://git.hcoop.net/bpt/guile.git/blobdiff_plain/3cf066df9b59d7fec390168f09da1a4aaa8d72e7..fb50a753e125f77093826963fd786b9592f7e08d:/doc/ref/api-scheduling.texi diff --git a/doc/ref/api-scheduling.texi b/doc/ref/api-scheduling.texi dissimilarity index 60% index f85ea4aaa..0d036be9e 100644 --- a/doc/ref/api-scheduling.texi +++ b/doc/ref/api-scheduling.texi @@ -1,920 +1,1192 @@ -@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. -* Mutexes:: Synchronization primitives. -@end menu - - -@node Arbiters -@subsection Arbiters -@cindex arbiters - -Arbiters are synchronization objects, they can be used by threads to -control access to a shared resource. An arbiter can be locked to -indicate a resource is in use, and unlocked when done. - -An arbiter is like a light-weight mutex (@pxref{Mutexes}). It uses -less memory and may be faster, but there's no way for a thread to -block waiting on an arbiter, it can only test and get the status -returned. - -@deffn {Scheme Procedure} make-arbiter name -@deffnx {C Function} scm_make_arbiter (name) -Return an arbiter object, initially unlocked. Currently @var{name} is -only used for diagnostic output. -@end deffn - -@deffn {Scheme Procedure} try-arbiter arb -@deffnx {C Function} scm_try_arbiter (arb) -If @var{arb} is unlocked, then lock it and return @code{#t}. If -@var{arb} is already locked, then do nothing and return @code{#f}. -@end deffn - -@deffn {Scheme Procedure} release-arbiter arb -@deffnx {C Function} scm_release_arbiter (arb) -If @var{arb} is locked, then unlock it and return @code{#t}. If -@var{arb} is already unlocked, then do nothing and return @code{#f}. - -Typical usage is for the thread which locked an arbiter to later -release it, but that's not required, any thread can release it. -@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-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. - -@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 - -@node C level thread interface -@subsubsection C level thread interface - -You can create and manage threads -with the C versions of the primitives above. -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_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 condition variable 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 - - -@node Mutexes -@subsection Mutexes -@cindex mutex - -A mutex is a thread synchronization object, it can be used by threads -to control access to a shared resource. A mutex can be locked to -indicate a resource is in use, and other threads can then block on the -mutex to wait for the resource (or can just test and do something else -if not available). ``Mutex'' is short for ``mutual exclusion''. - -There are two types of mutexes, ``standard'' and ``fair''. They're -created by @code{make-mutex} and @code{make-fair-mutex} respectively, -the operation functions are then common to both. - -Note that for both types of mutex there's no protection against a -``deadly embrace''. For instance if one thread has locked mutex A and -is waiting on mutex B, but another thread owns B and is waiting on A, -then an endless wait will occur (in the current implementation). -Acquiring requisite mutexes in a fixed order (like always A before B) -in all threads is one way to avoid such problems. - -@sp 1 -@deffn {Scheme Procedure} make-mutex -@deffnx {Scheme Procedure} make-fair-mutex -Return a new mutex object. - -@code{make-mutex} creates a standard mutex. This is fast, but its -features are restricted. Recursive locking (multiple lock calls by -one thread) is not permitted, and an unlock can be done only when -already locked and only by the owning thread. When multiple threads -are blocked waiting to acquire the mutex, it's unspecified which will -get it next. - -@code{make-fair-mutex} creates a fair mutex. This has more features -and error checking. Recursive locking is allowed, a given thread can -make multiple lock calls and the mutex is released when a balancing -number of unlocks are done. Other threads blocked waiting to acquire -the mutex form a queue and the one waiting longest will be the next to -acquire it. -@end deffn - -@deffn {Scheme Procedure} lock-mutex mutex -Lock @var{mutex}. If the mutex is already locked by another thread -then block and return only when @var{mutex} has been acquired. - -For standard mutexes (@code{make-mutex}), if the thread has itself -already locked @var{mutex} it must not call @code{lock-mutex} on it a -further time. Behaviour is unspecified if this is done. - -For a fair mutex (@code{make-fair-mutex}), if the thread has itself -already locked @var{mutex}, then a further @code{lock-mutex} call -increments the lock count. An additional @code{unlock-mutex} will be -required to finally release. - -When a system async (@pxref{System asyncs}) is activated for a thread -blocked in @code{lock-mutex}, the wait is interrupted and the async is -executed. When the async returns the wait resumes. -@end deffn - -@deffn {Scheme Procedure} try-mutex mutex -Try to lock @var{mutex} as per @code{lock-mutex}. If @var{mutex} can -be acquired immediately then this is done and the return is @code{#t}. -If @var{mutex} is locked by some other thread then nothing is done and -the return is @code{#f}. -@end deffn - -@deffn {Scheme Procedure} unlock-mutex mutex -Unlock @var{mutex}. - -For a standard mutex (@code{make-mutex}), if @var{mutex} is not locked -by the calling thread then behaviour is unspecified. - -For a fair mutex (@code{make-fair-mutex}), if @var{mutex} is not -locked by the calling thread then an error is thrown. -@end deffn - -@sp 1 -The following are higher level operations on mutexes. These are -available from - -@example -(use-modules (ice-9 threads)) -@end example - -@deffn macro with-mutex mutex [body@dots{}] -Lock @var{mutex}, evaluate the @var{body} forms, then unlock -@var{mutex}. The return value is the return from the last @var{body} -form. - -The lock, body and unlock form the branches of a @code{dynamic-wind} -(@pxref{Dynamic Wind}), so @var{mutex} is automatically unlocked if an -error or new continuation exits @var{body}, and is re-locked if -@var{body} is re-entered by a captured continuation. -@end deffn - -@deffn macro monitor body@dots{} -Evaluate the @var{body} forms, with a mutex locked so only one thread -can execute that code at any one time. The return value is the return -from the last @var{body} form. - -Each @code{monitor} form has its own private mutex and the locking and -evaluation is as per @code{with-mutex} above. A standard mutex -(@code{make-mutex}) is used, which means @var{body} must not -recursively re-enter the @code{monitor} form. - -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 - -@sp 1 -The following provide access to standard mutexes from C code. - -@deftp {C Data Type} scm_t_mutex -A mutex, to be used with @code{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) -Free all resources associated with @var{m}. -@end deftypefn - -@deftypefn {C Function} void scm_mutex_lock (scm_t_mutex *m) -Lock the mutex @var{m}. This is as per @code{lock-mutex} above on a -standard mutex. -@end deftypefn - -@deftypefn {C Function} int scm_mutex_trylock (scm_t_mutex *m) -Attempt to lock mutex @var{m}, as per @code{scm_mutex_lock}. If -@var{m} is unlocked then this is done and the return is non-zero. If -@var{m} is already locked by another thread then do nothing and return -zero. -@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, otherwise the behavior is undefined. -@end deftypefn - - -@c Local Variables: -@c TeX-master: "guile.texi" -@c End: +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009, 2010, 2012, 2013 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Scheduling +@section Threads, Mutexes, Asyncs and Dynamic Roots + +@menu +* Arbiters:: Synchronization primitives. +* Asyncs:: Asynchronous procedure invocation. +* Threads:: Multiple threads of execution. +* Mutexes and Condition Variables:: Synchronization primitives. +* Blocking:: How to block properly in guile mode. +* Critical Sections:: Avoiding concurrency and reentries. +* Fluids and Dynamic States:: Thread-local variables, etc. +* Parameters:: Dynamic scoping in Scheme. +* Futures:: Fine-grain parallelism. +* Parallel Forms:: Parallel execution of forms. +@end menu + + +@node Arbiters +@subsection Arbiters +@cindex arbiters + +Arbiters are synchronization objects, they can be used by threads to +control access to a shared resource. An arbiter can be locked to +indicate a resource is in use, and unlocked when done. + +An arbiter is like a light-weight mutex (@pxref{Mutexes and Condition +Variables}). It uses less memory and may be faster, but there's no +way for a thread to block waiting on an arbiter, it can only test and +get the status returned. + +@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) +If @var{arb} is unlocked, then lock it and return @code{#t}. +If @var{arb} is already locked, then do nothing and return +@code{#f}. +@end deffn + +@deffn {Scheme Procedure} release-arbiter arb +@deffnx {C Function} scm_release_arbiter (arb) +If @var{arb} is locked, then unlock it and return @code{#t}. If +@var{arb} is already unlocked, then do nothing and return @code{#f}. + +Typical usage is for the thread which locked an arbiter to later +release it, but that's not required, any thread can release it. +@end deffn + + +@node Asyncs +@subsection Asyncs + +@cindex asyncs +@cindex user asyncs +@cindex system asyncs + +Asyncs are a means of deferring the execution 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 queuing 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_dynwind_block_asyncs} and @code{scm_dynwind_unblock_asyncs} +inside a @dfn{dynamic context} (@pxref{Dynamic Wind}) 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 + +@deffn {Scheme Procedure} call-with-blocked-asyncs proc +@deffnx {C Function} scm_call_with_blocked_asyncs (proc) +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 + +@deftypefn {C Function} {void *} scm_c_call_with_blocked_asyncs (void * (*proc) (void *data), void *data) +The same but with a C function @var{proc} instead of a Scheme thunk. +@end deftypefn + +@deffn {Scheme Procedure} call-with-unblocked-asyncs proc +@deffnx {C Function} scm_call_with_unblocked_asyncs (proc) +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_c_call_with_unblocked_asyncs (void *(*proc) (void *data), void *data) +The same but with a C function @var{proc} instead of a Scheme thunk. +@end deftypefn + +@deftypefn {C Function} void scm_dynwind_block_asyncs () +During the current dynwind context, increase the blocking of asyncs by +one level. This function must be used inside a pair of calls to +@code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic +Wind}). +@end deftypefn + +@deftypefn {C Function} void scm_dynwind_unblock_asyncs () +During the current dynwind context, decrease the blocking of asyncs by +one level. This function must be used inside a pair of calls to +@code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic +Wind}). +@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 Threads +@subsection Threads +@cindex threads +@cindex Guile threads +@cindex POSIX threads + +Guile supports POSIX threads, unless it was configured with +@code{--without-threads} or the host lacks POSIX thread support. When +thread support is available, the @code{threads} feature is provided +(@pxref{Feature Manipulation, @code{provided?}}). + +The procedures below manipulate Guile threads, which are wrappers around +the system's POSIX threads. For application-level parallelism, using +higher-level constructs, such as futures, is recommended +(@pxref{Futures}). + +@deffn {Scheme Procedure} all-threads +@deffnx {C Function} scm_all_threads () +Return a list of all threads. +@end deffn + +@deffn {Scheme Procedure} current-thread +@deffnx {C Function} scm_current_thread () +Return the thread that called this function. +@end deffn + +@c begin (texi-doc-string "guile" "call-with-new-thread") +@deffn {Scheme Procedure} call-with-new-thread thunk [handler] +Call @code{thunk} in a new thread and with a new dynamic state, +returning the new thread. The procedure @var{thunk} is called via +@code{with-continuation-barrier}. + +When @var{handler} is specified, then @var{thunk} is called from +within a @code{catch} with tag @code{#t} that has @var{handler} as its +handler. This catch is established inside the continuation barrier. + +Once @var{thunk} or @var{handler} returns, the return value is made +the @emph{exit value} of the thread and the thread is terminated. +@end deffn + +@deftypefn {C Function} SCM scm_spawn_thread (scm_t_catch_body body, void *body_data, scm_t_catch_handler handler, void *handler_data) +Call @var{body} in a new thread, passing it @var{body_data}, returning +the new thread. The function @var{body} is called via +@code{scm_c_with_continuation_barrier}. + +When @var{handler} is non-@code{NULL}, @var{body} is called via +@code{scm_internal_catch} with tag @code{SCM_BOOL_T} that has +@var{handler} and @var{handler_data} as the handler and its data. This +catch is established inside the continuation barrier. + +Once @var{body} or @var{handler} returns, the return value is made the +@emph{exit value} of the thread and the thread is terminated. +@end deftypefn + +@deffn {Scheme Procedure} thread? obj +@deffnx {C Function} scm_thread_p (obj) +Return @code{#t} ff @var{obj} is a thread; otherwise, return +@code{#f}. +@end deffn + +@c begin (texi-doc-string "guile" "join-thread") +@deffn {Scheme Procedure} join-thread thread [timeout [timeoutval]] +@deffnx {C Function} scm_join_thread (thread) +@deffnx {C Function} scm_join_thread_timed (thread, timeout, timeoutval) +Wait for @var{thread} to terminate and return its exit value. Threads +that have not been created with @code{call-with-new-thread} or +@code{scm_spawn_thread} have an exit value of @code{#f}. When +@var{timeout} is given, it specifies a point in time where the waiting +should be aborted. It can be either an integer as returned by +@code{current-time} or a pair as returned by @code{gettimeofday}. +When the waiting is aborted, @var{timeoutval} is returned (if it is +specified; @code{#f} is returned otherwise). +@end deffn + +@deffn {Scheme Procedure} thread-exited? thread +@deffnx {C Function} scm_thread_exited_p (thread) +Return @code{#t} if @var{thread} has exited, or @code{#f} otherwise. +@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 + +@deffn {Scheme Procedure} cancel-thread thread +@deffnx {C Function} scm_cancel_thread (thread) +Asynchronously notify @var{thread} to exit. Immediately after +receiving this notification, @var{thread} will call its cleanup handler +(if one has been set) and then terminate, aborting any evaluation that +is in progress. + +Because Guile threads are isomorphic with POSIX threads, @var{thread} +will not receive its cancellation signal until it reaches a cancellation +point. See your operating system's POSIX threading documentation for +more information on cancellation points; note that in Guile, unlike +native POSIX threads, a thread can receive a cancellation notification +while attempting to lock a mutex. +@end deffn + +@deffn {Scheme Procedure} set-thread-cleanup! thread proc +@deffnx {C Function} scm_set_thread_cleanup_x (thread, proc) +Set @var{proc} as the cleanup handler for the thread @var{thread}. +@var{proc}, which must be a thunk, will be called when @var{thread} +exits, either normally or by being canceled. Thread cleanup handlers +can be used to perform useful tasks like releasing resources, such as +locked mutexes, when thread exit cannot be predicted. + +The return value of @var{proc} will be set as the @emph{exit value} of +@var{thread}. + +To remove a cleanup handler, pass @code{#f} for @var{proc}. +@end deffn + +@deffn {Scheme Procedure} thread-cleanup thread +@deffnx {C Function} scm_thread_cleanup (thread) +Return the cleanup handler currently installed for the thread +@var{thread}. If no cleanup handler is currently installed, +thread-cleanup returns @code{#f}. +@end deffn + +Higher level thread procedures are available by loading the +@code{(ice-9 threads)} module. These provide standardized +thread creation. + +@deffn macro make-thread proc arg @dots{} +Apply @var{proc} to @var{arg} @dots{} 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. The @var{arg} @dots{} +expressions are evaluated in the new thread. +@end deffn + +@deffn macro begin-thread expr1 expr2 @dots{} +Evaluate forms @var{expr1} @var{expr2} @dots{} 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 + +@node Mutexes and Condition Variables +@subsection Mutexes and Condition Variables +@cindex mutex +@cindex condition variable + +A mutex is a thread synchronization object, it can be used by threads +to control access to a shared resource. A mutex can be locked to +indicate a resource is in use, and other threads can then block on the +mutex to wait for the resource (or can just test and do something else +if not available). ``Mutex'' is short for ``mutual exclusion''. + +There are two types of mutexes in Guile, ``standard'' and +``recursive''. They're created by @code{make-mutex} and +@code{make-recursive-mutex} respectively, the operation functions are +then common to both. + +Note that for both types of mutex there's no protection against a +``deadly embrace''. For instance if one thread has locked mutex A and +is waiting on mutex B, but another thread owns B and is waiting on A, +then an endless wait will occur (in the current implementation). +Acquiring requisite mutexes in a fixed order (like always A before B) +in all threads is one way to avoid such problems. + +@sp 1 +@deffn {Scheme Procedure} make-mutex flag @dots{} +@deffnx {C Function} scm_make_mutex () +@deffnx {C Function} scm_make_mutex_with_flags (SCM flags) +Return a new mutex. It is initially unlocked. If @var{flag} @dots{} is +specified, it must be a list of symbols specifying configuration flags +for the newly-created mutex. The supported flags are: +@table @code +@item unchecked-unlock +Unless this flag is present, a call to `unlock-mutex' on the returned +mutex when it is already unlocked will cause an error to be signalled. + +@item allow-external-unlock +Allow the returned mutex to be unlocked by the calling thread even if +it was originally locked by a different thread. + +@item recursive +The returned mutex will be recursive. + +@end table +@end deffn + +@deffn {Scheme Procedure} mutex? obj +@deffnx {C Function} scm_mutex_p (obj) +Return @code{#t} if @var{obj} is a mutex; otherwise, return +@code{#f}. +@end deffn + +@deffn {Scheme Procedure} make-recursive-mutex +@deffnx {C Function} scm_make_recursive_mutex () +Create a new recursive mutex. It is initially unlocked. Calling this +function is equivalent to calling `make-mutex' and specifying the +@code{recursive} flag. +@end deffn + +@deffn {Scheme Procedure} lock-mutex mutex [timeout [owner]] +@deffnx {C Function} scm_lock_mutex (mutex) +@deffnx {C Function} scm_lock_mutex_timed (mutex, timeout, owner) +Lock @var{mutex}. If the mutex is already locked, then block and +return only when @var{mutex} has been acquired. + +When @var{timeout} is given, it specifies a point in time where the +waiting should be aborted. It can be either an 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 @var{owner} is given, it specifies an owner for @var{mutex} other +than the calling thread. @var{owner} may also be @code{#f}, +indicating that the mutex should be locked but left unowned. + +For standard mutexes (@code{make-mutex}), and error is signalled if +the thread has itself already locked @var{mutex}. + +For a recursive mutex (@code{make-recursive-mutex}), if the thread has +itself already locked @var{mutex}, then a further @code{lock-mutex} +call increments the lock count. An additional @code{unlock-mutex} +will be required to finally release. + +If @var{mutex} was locked by a thread that exited before unlocking it, +the next attempt to lock @var{mutex} will succeed, but +@code{abandoned-mutex-error} will be signalled. + +When a system async (@pxref{System asyncs}) is activated for a thread +blocked in @code{lock-mutex}, the wait is interrupted and the async is +executed. When the async returns, the wait resumes. +@end deffn + +@deftypefn {C Function} void scm_dynwind_lock_mutex (SCM mutex) +Arrange for @var{mutex} to be locked whenever the current dynwind +context is entered and to be unlocked when it is exited. +@end deftypefn + +@deffn {Scheme Procedure} try-mutex mx +@deffnx {C Function} scm_try_mutex (mx) +Try to lock @var{mutex} as per @code{lock-mutex}. If @var{mutex} can +be acquired immediately then this is done and the return is @code{#t}. +If @var{mutex} is locked by some other thread then nothing is done and +the return is @code{#f}. +@end deffn + +@deffn {Scheme Procedure} unlock-mutex mutex [condvar [timeout]] +@deffnx {C Function} scm_unlock_mutex (mutex) +@deffnx {C Function} scm_unlock_mutex_timed (mutex, condvar, timeout) +Unlock @var{mutex}. An error is signalled if @var{mutex} is not locked +and was not created with the @code{unchecked-unlock} flag set, or if +@var{mutex} is locked by a thread other than the calling thread and was +not created with the @code{allow-external-unlock} flag set. + +If @var{condvar} is given, it specifies a condition variable upon +which the calling thread will wait to be signalled before returning. +(This behavior is very similar to that of +@code{wait-condition-variable}, except that the mutex is left in an +unlocked state when the function returns.) + +When @var{timeout} is also given and not false, it specifies a point in +time where the waiting should be aborted. It can be either an integer +as returned by @code{current-time} or a pair as returned by +@code{gettimeofday}. When the waiting is aborted, @code{#f} is +returned. Otherwise the function returns @code{#t}. +@end deffn + +@deffn {Scheme Procedure} mutex-owner mutex +@deffnx {C Function} scm_mutex_owner (mutex) +Return the current owner of @var{mutex}, in the form of a thread or +@code{#f} (indicating no owner). Note that a mutex may be unowned but +still locked. +@end deffn + +@deffn {Scheme Procedure} mutex-level mutex +@deffnx {C Function} scm_mutex_level (mutex) +Return the current lock level of @var{mutex}. If @var{mutex} is +currently unlocked, this value will be 0; otherwise, it will be the +number of times @var{mutex} has been recursively locked by its current +owner. +@end deffn + +@deffn {Scheme Procedure} mutex-locked? mutex +@deffnx {C Function} scm_mutex_locked_p (mutex) +Return @code{#t} if @var{mutex} is locked, regardless of ownership; +otherwise, return @code{#f}. +@end deffn + +@deffn {Scheme Procedure} make-condition-variable +@deffnx {C Function} scm_make_condition_variable () +Return a new condition variable. +@end deffn + +@deffn {Scheme Procedure} condition-variable? obj +@deffnx {C Function} scm_condition_variable_p (obj) +Return @code{#t} if @var{obj} is a condition variable; otherwise, +return @code{#f}. +@end deffn + +@deffn {Scheme Procedure} wait-condition-variable condvar mutex [time] +@deffnx {C Function} scm_wait_condition_variable (condvar, mutex, time) +Wait until @var{condvar} 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. When +the thread block while re-acquiring the mutex, execution of asyncs is +blocked. +@end deffn + +@deffn {Scheme Procedure} signal-condition-variable condvar +@deffnx {C Function} scm_signal_condition_variable (condvar) +Wake up one thread that is waiting for @var{condvar}. +@end deffn + +@deffn {Scheme Procedure} broadcast-condition-variable condvar +@deffnx {C Function} scm_broadcast_condition_variable (condvar) +Wake up all threads that are waiting for @var{condvar}. +@end deffn + +@sp 1 +The following are higher level operations on mutexes. These are +available from + +@example +(use-modules (ice-9 threads)) +@end example + +@deffn macro with-mutex mutex body1 body2 @dots{} +Lock @var{mutex}, evaluate the body @var{body1} @var{body2} @dots{}, +then unlock @var{mutex}. The return value is that returned by the last +body form. + +The lock, body and unlock form the branches of a @code{dynamic-wind} +(@pxref{Dynamic Wind}), so @var{mutex} is automatically unlocked if an +error or new continuation exits the body, and is re-locked if +the body is re-entered by a captured continuation. +@end deffn + +@deffn macro monitor body1 body2 @dots{} +Evaluate the body form @var{body1} @var{body2} @dots{} with a mutex +locked so only one thread can execute that code at any one time. The +return value is the return from the last body form. + +Each @code{monitor} form has its own private mutex and the locking and +evaluation is as per @code{with-mutex} above. A standard mutex +(@code{make-mutex}) is used, which means the body must not +recursively re-enter the @code{monitor} form. + +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 Blocking +@subsection Blocking in Guile Mode + +Up to Guile version 1.8, a thread blocked in guile mode would prevent +the garbage collector from running. Thus threads had to explicitly +leave guile mode with @code{scm_without_guile ()} before making a +potentially blocking call such as a mutex lock, a @code{select ()} +system call, etc. The following functions could be used to temporarily +leave guile mode or to perform some common blocking operations in a +supported way. + +Starting from Guile 2.0, blocked threads no longer hinder garbage +collection. Thus, the functions below are not needed anymore. They can +still be used to inform the GC that a thread is about to block, giving +it a (small) optimization opportunity for ``stop the world'' garbage +collections, should they occur while the thread is blocked. + +@deftypefn {C Function} {void *} scm_without_guile (void *(*func) (void *), void *data) +Leave guile mode, call @var{func} on @var{data}, enter guile mode and +return the result of calling @var{func}. + +While a thread has left guile mode, it must not call any libguile +functions except @code{scm_with_guile} or @code{scm_without_guile} and +must not use any libguile macros. Also, local variables of type +@code{SCM} that are allocated while not in guile mode are not +protected from the garbage collector. + +When used from non-guile mode, calling @code{scm_without_guile} is +still allowed: it simply calls @var{func}. In that way, you can leave +guile mode without having to know whether the current thread is in +guile mode or not. +@end deftypefn + +@deftypefn {C Function} int scm_pthread_mutex_lock (pthread_mutex_t *mutex) +Like @code{pthread_mutex_lock}, but leaves guile mode while waiting for +the mutex. +@end deftypefn + +@deftypefn {C Function} int scm_pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) +@deftypefnx {C Function} int scm_pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *abstime) +Like @code{pthread_cond_wait} and @code{pthread_cond_timedwait}, but +leaves guile mode while waiting for the condition variable. +@end deftypefn + +@deftypefn {C Function} int scm_std_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) +Like @code{select} but leaves guile mode while waiting. Also, the +delivery of a system async causes this function to be interrupted with +error code @code{EINTR}. +@end deftypefn + +@deftypefn {C Function} {unsigned int} scm_std_sleep ({unsigned int} seconds) +Like @code{sleep}, but leaves guile mode while sleeping. Also, the +delivery of a system async causes this function to be interrupted. +@end deftypefn + +@deftypefn {C Function} {unsigned long} scm_std_usleep ({unsigned long} usecs) +Like @code{usleep}, but leaves guile mode while sleeping. Also, the +delivery of a system async causes this function to be interrupted. +@end deftypefn + + +@node Critical Sections +@subsection Critical Sections + +@deffn {C Macro} SCM_CRITICAL_SECTION_START +@deffnx {C Macro} SCM_CRITICAL_SECTION_END +These two macros can be used to delimit a critical section. +Syntactically, they are both statements and need to be followed +immediately by a semicolon. + +Executing @code{SCM_CRITICAL_SECTION_START} will lock a recursive +mutex and block the executing of system asyncs. Executing +@code{SCM_CRITICAL_SECTION_END} will unblock the execution of system +asyncs and unlock the mutex. Thus, the code that executes between +these two macros can only be executed in one thread at any one time +and no system asyncs will run. However, because the mutex is a +recursive one, the code might still be reentered by the same thread. +You must either allow for this or avoid it, both by careful coding. + +On the other hand, critical sections delimited with these macros can +be nested since the mutex is recursive. + +You must make sure that for each @code{SCM_CRITICAL_SECTION_START}, +the corresponding @code{SCM_CRITICAL_SECTION_END} is always executed. +This means that no non-local exit (such as a signalled error) might +happen, for example. +@end deffn + +@deftypefn {C Function} void scm_dynwind_critical_section (SCM mutex) +Call @code{scm_dynwind_lock_mutex} on @var{mutex} and call +@code{scm_dynwind_block_asyncs}. When @var{mutex} is false, a recursive +mutex provided by Guile is used instead. + +The effect of a call to @code{scm_dynwind_critical_section} is that +the current dynwind context (@pxref{Dynamic Wind}) turns into a +critical section. Because of the locked mutex, no second thread can +enter it concurrently and because of the blocked asyncs, no system +async can reenter it from the current thread. + +When the current thread reenters the critical section anyway, the kind +of @var{mutex} determines what happens: When @var{mutex} is recursive, +the reentry is allowed. When it is a normal mutex, an error is +signalled. +@end deftypefn + + +@node Fluids and Dynamic States +@subsection Fluids and Dynamic States + +@cindex fluids + +A @emph{fluid} is an object that can store one value per @emph{dynamic +state}. Each thread has a current dynamic state, and when accessing a +fluid, this current dynamic state is used to provide the actual value. +In this way, fluids can be used for thread local storage, but they are +in fact more flexible: dynamic states are objects of their own and can +be made current for more than one thread at the same time, or only be +made current temporarily, for example. + +Fluids can also 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 [dflt] +@deffnx {C Function} scm_make_fluid () +@deffnx {C Function} scm_make_fluid_with_default (dflt) +Return a newly created fluid, whose initial value is @var{dflt}, or +@code{#f} if @var{dflt} is not given. +Fluids are objects that can hold one +value per dynamic state. That is, modifications to this value are +only visible to code that executes with the same dynamic state as +the modifying code. When a new dynamic state is constructed, it +inherits the values from its parent. Because each thread normally executes +with its own dynamic state, you can use fluids for thread local storage. +@end deffn + +@deffn {Scheme Procedure} make-unbound-fluid +@deffnx {C Function} scm_make_unbound_fluid () +Return a new fluid that is initially unbound (instead of being +implicitly bound to some definite value). +@end deffn + +@deffn {Scheme Procedure} fluid? obj +@deffnx {C Function} scm_fluid_p (obj) +Return @code{#t} if @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 +its default value. Calling @code{fluid-ref} on an unbound fluid produces +a runtime error. +@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 + +@deffn {Scheme Procedure} fluid-unset! fluid +@deffnx {C Function} scm_fluid_unset_x (fluid) +Disassociate the given fluid from any value, making it unbound. +@end deffn + +@deffn {Scheme Procedure} fluid-bound? fluid +@deffnx {C Function} scm_fluid_bound_p (fluid) +Returns @code{#t} if the given fluid is bound to a value, otherwise +@code{#f}. +@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-fluid* fluid value thunk +@deffnx {C Function} scm_with_fluid (fluid, value, thunk) +Set @var{fluid} to @var{value} temporarily, and call @var{thunk}. +@var{thunk} must be a procedure with no argument. +@end deffn + +@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) @dots{}) body1 body2 @dots{} +Execute body @var{body1} @var{body2} @dots{} 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. The 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_dynwind_fluid (SCM fluid, SCM val) +This function must be used inside a pair of calls to +@code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic +Wind}). During the dynwind context, the fluid @var{fluid} is set to +@var{val}. + +More precisely, the value of the fluid is swapped with a `backup' +value whenever the dynwind context is entered or left. The backup +value is initialized with the @var{val} argument. +@end deftypefn + +@deffn {Scheme Procedure} make-dynamic-state [parent] +@deffnx {C Function} scm_make_dynamic_state (parent) +Return a copy of the dynamic state object @var{parent} +or of the current dynamic state when @var{parent} is omitted. +@end deffn + +@deffn {Scheme Procedure} dynamic-state? obj +@deffnx {C Function} scm_dynamic_state_p (obj) +Return @code{#t} if @var{obj} is a dynamic state object; +return @code{#f} otherwise. +@end deffn + +@deftypefn {C Procedure} int scm_is_dynamic_state (SCM obj) +Return non-zero if @var{obj} is a dynamic state object; +return zero otherwise. +@end deftypefn + +@deffn {Scheme Procedure} current-dynamic-state +@deffnx {C Function} scm_current_dynamic_state () +Return the current dynamic state object. +@end deffn + +@deffn {Scheme Procedure} set-current-dynamic-state state +@deffnx {C Function} scm_set_current_dynamic_state (state) +Set the current dynamic state object to @var{state} +and return the previous current dynamic state object. +@end deffn + +@deffn {Scheme Procedure} with-dynamic-state state proc +@deffnx {C Function} scm_with_dynamic_state (state, proc) +Call @var{proc} while @var{state} is the current dynamic +state object. +@end deffn + +@deftypefn {C Procedure} void scm_dynwind_current_dynamic_state (SCM state) +Set the current dynamic state to @var{state} for the current dynwind +context. +@end deftypefn + +@deftypefn {C Procedure} {void *} scm_c_with_dynamic_state (SCM state, void *(*func)(void *), void *data) +Like @code{scm_with_dynamic_state}, but call @var{func} with +@var{data}. +@end deftypefn + +@node Parameters +@subsection Parameters + +@cindex SRFI-39 +@cindex parameter object +@tindex Parameter + +A parameter object is a procedure. Calling it with no arguments returns +its value. Calling it with one argument sets the value. + +@example +(define my-param (make-parameter 123)) +(my-param) @result{} 123 +(my-param 456) +(my-param) @result{} 456 +@end example + +The @code{parameterize} special form establishes new locations for +parameters, those new locations having effect within the dynamic scope +of the @code{parameterize} body. Leaving restores the previous +locations. Re-entering (through a saved continuation) will again use +the new locations. + +@example +(parameterize ((my-param 789)) + (my-param)) @result{} 789 +(my-param) @result{} 456 +@end example + +Parameters are like dynamically bound variables in other Lisp dialects. +They allow an application to establish parameter settings (as the name +suggests) just for the execution of a particular bit of code, restoring +when done. Examples of such parameters might be case-sensitivity for a +search, or a prompt for user input. + +Global variables are not as good as parameter objects for this sort of +thing. Changes to them are visible to all threads, but in Guile +parameter object locations are per-thread, thereby truly limiting the +effect of @code{parameterize} to just its dynamic execution. + +Passing arguments to functions is thread-safe, but that soon becomes +tedious when there's more than a few or when they need to pass down +through several layers of calls before reaching the point they should +affect. And introducing a new setting to existing code is often easier +with a parameter object than adding arguments. + +@deffn {Scheme Procedure} make-parameter init [converter] +Return a new parameter object, with initial value @var{init}. + +If a @var{converter} is given, then a call @code{(@var{converter} +val)} is made for each value set, its return is the value stored. +Such a call is made for the @var{init} initial value too. + +A @var{converter} allows values to be validated, or put into a +canonical form. For example, + +@example +(define my-param (make-parameter 123 + (lambda (val) + (if (not (number? val)) + (error "must be a number")) + (inexact->exact val)))) +(my-param 0.75) +(my-param) @result{} 3/4 +@end example +@end deffn + +@deffn {library syntax} parameterize ((param value) @dots{}) body1 body2 @dots{} +Establish a new dynamic scope with the given @var{param}s bound to new +locations and set to the given @var{value}s. @var{body1} @var{body2} +@dots{} is evaluated in that environment. The value returned is that of +last body form. + +Each @var{param} is an expression which is evaluated to get the +parameter object. Often this will just be the name of a variable +holding the object, but it can be anything that evaluates to a +parameter. + +The @var{param} expressions and @var{value} expressions are all +evaluated before establishing the new dynamic bindings, and they're +evaluated in an unspecified order. + +For example, + +@example +(define prompt (make-parameter "Type something: ")) +(define (get-input) + (display (prompt)) + ...) + +(parameterize ((prompt "Type a number: ")) + (get-input) + ...) +@end example +@end deffn + +Parameter objects are implemented using fluids (@pxref{Fluids and +Dynamic States}), so each dynamic state has its own parameter +locations. That includes the separate locations when outside any +@code{parameterize} form. When a parameter is created it gets a +separate initial location in each dynamic state, all initialized to the +given @var{init} value. + +New code should probably just use parameters instead of fluids, because +the interface is better. But for migrating old code or otherwise +providing interoperability, Guile provides the @code{fluid->parameter} +procedure: + +@deffn {Scheme Procedure} fluid->parameter fluid [conv] +Make a parameter that wraps a fluid. + +The value of the parameter will be the same as the value of the fluid. +If the parameter is rebound in some dynamic extent, perhaps via +@code{parameterize}, the new value will be run through the optional +@var{conv} procedure, as with any parameter. Note that unlike +@code{make-parameter}, @var{conv} is not applied to the initial value. +@end deffn + +As alluded to above, because each thread usually has a separate dynamic +state, each thread has its own locations behind parameter objects, and +changes in one thread are not visible to any other. When a new dynamic +state or thread is created, the values of parameters in the originating +context are copied, into new locations. + +@cindex SRFI-39 +Guile's parameters conform to SRFI-39 (@pxref{SRFI-39}). + + +@node Futures +@subsection Futures +@cindex futures +@cindex fine-grain parallelism +@cindex parallelism + +The @code{(ice-9 futures)} module provides @dfn{futures}, a construct +for fine-grain parallelism. A future is a wrapper around an expression +whose computation may occur in parallel with the code of the calling +thread, and possibly in parallel with other futures. Like promises, +futures are essentially proxies that can be queried to obtain the value +of the enclosed expression: + +@lisp +(touch (future (+ 2 3))) +@result{} 5 +@end lisp + +However, unlike promises, the expression associated with a future may be +evaluated on another CPU core, should one be available. This supports +@dfn{fine-grain parallelism}, because even relatively small computations +can be embedded in futures. Consider this sequential code: + +@lisp +(define (find-prime lst1 lst2) + (or (find prime? lst1) + (find prime? lst2))) +@end lisp + +The two arms of @code{or} are potentially computation-intensive. They +are independent of one another, yet, they are evaluated sequentially +when the first one returns @code{#f}. Using futures, one could rewrite +it like this: + +@lisp +(define (find-prime lst1 lst2) + (let ((f (future (find prime? lst2)))) + (or (find prime? lst1) + (touch f)))) +@end lisp + +This preserves the semantics of @code{find-prime}. On a multi-core +machine, though, the computation of @code{(find prime? lst2)} may be +done in parallel with that of the other @code{find} call, which can +reduce the execution time of @code{find-prime}. + +Futures may be nested: a future can itself spawn and then @code{touch} +other futures, leading to a directed acyclic graph of futures. Using +this facility, a parallel @code{map} procedure can be defined along +these lines: + +@lisp +(use-modules (ice-9 futures) (ice-9 match)) + +(define (par-map proc lst) + (match lst + (() + '()) + ((head tail ...) + (let ((tail (future (par-map proc tail))) + (head (proc head))) + (cons head (touch tail)))))) +@end lisp + +Note that futures are intended for the evaluation of purely functional +expressions. Expressions that have side-effects or rely on I/O may +require additional care, such as explicit synchronization +(@pxref{Mutexes and Condition Variables}). + +Guile's futures are implemented on top of POSIX threads +(@pxref{Threads}). Internally, a fixed-size pool of threads is used to +evaluate futures, such that offloading the evaluation of an expression +to another thread doesn't incur thread creation costs. By default, the +pool contains one thread per available CPU core, minus one, to account +for the main thread. The number of available CPU cores is determined +using @code{current-processor-count} (@pxref{Processes}). + +When a thread touches a future that has not completed yet, it processes +any pending future while waiting for it to complete, or just waits if +there are no pending futures. When @code{touch} is called from within a +future, the execution of the calling future is suspended, allowing its +host thread to process other futures, and resumed when the touched +future has completed. This suspend/resume is achieved by capturing the +calling future's continuation, and later reinstating it (@pxref{Prompts, +delimited continuations}). + +Note that @code{par-map} above is not tail-recursive. This could lead +to stack overflows when @var{lst} is large compared to +@code{(current-processor-count)}. To address that, @code{touch} uses +the suspend mechanism described above to limit the number of nested +futures executing on the same stack. Thus, the above code should never +run into stack overflows. + +@deffn {Scheme Syntax} future exp +Return a future for expression @var{exp}. This is equivalent to: + +@lisp +(make-future (lambda () exp)) +@end lisp +@end deffn + +@deffn {Scheme Procedure} make-future thunk +Return a future for @var{thunk}, a zero-argument procedure. + +This procedure returns immediately. Execution of @var{thunk} may begin +in parallel with the calling thread's computations, if idle CPU cores +are available, or it may start when @code{touch} is invoked on the +returned future. + +If the execution of @var{thunk} throws an exception, that exception will +be re-thrown when @code{touch} is invoked on the returned future. +@end deffn + +@deffn {Scheme Procedure} future? obj +Return @code{#t} if @var{obj} is a future. +@end deffn + +@deffn {Scheme Procedure} touch f +Return the result of the expression embedded in future @var{f}. + +If the result was already computed in parallel, @code{touch} returns +instantaneously. Otherwise, it waits for the computation to complete, +if it already started, or initiates it. In the former case, the calling +thread may process other futures in the meantime. +@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 + +They provide high-level parallel constructs. The following functions +are implemented in terms of futures (@pxref{Futures}). Thus they are +relatively cheap as they re-use existing threads, and portable, since +they automatically use one thread per available CPU core. + +@deffn syntax parallel expr @dots{} +Evaluate each @var{expr} expression in parallel, each in its own thread. +Return the results of @var{n} expressions as a set of @var{n} multiple +values (@pxref{Multiple Values}). +@end deffn + +@deffn syntax letpar ((var expr) @dots{}) body1 body2 @dots{} +Evaluate each @var{expr} in parallel, each in its own thread, then bind +the results to the corresponding @var{var} variables, and then evaluate +@var{body1} @var{body2} @enddots{} + +@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 lst2 @dots{} +@deffnx {Scheme Procedure} par-for-each proc lst1 lst2 @dots{} +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} @var{elem2} +@dots{})}, where each @var{elem} is from the corresponding @var{lst} . +Each @var{lst} must be the same length. The calls are potentially made +in parallel, depending on the number of CPU cores available. + +These functions are like @code{map} and @code{for-each} (@pxref{List +Mapping}), but make their @var{proc} calls in parallel. +@end deffn + +Unlike those above, the functions described below take a number of +threads as an argument. This makes them inherently non-portable since +the specified number of threads may differ from the number of available +CPU cores as returned by @code{current-processor-count} +(@pxref{Processes}). In addition, these functions create the specified +number of threads when they are called and terminate them upon +completion, which makes them quite expensive. + +Therefore, they should be avoided. + +@deffn {Scheme Procedure} n-par-map n proc lst1 lst2 @dots{} +@deffnx {Scheme Procedure} n-par-for-each n proc lst1 lst2 @dots{} +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} 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 lst2 @dots{} +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 separate threads. No more +than @var{n} 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 n 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: