@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
+@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.
@deffn {Scheme Procedure} thread? obj
@deffnx {C Function} scm_thread_p (obj)
-Return @code{#t} iff @var{obj} is a thread; otherwise, return
+Return @code{#t} ff @var{obj} is a thread; otherwise, return
@code{#f}.
@end deffn
@deffn {Scheme Procedure} thread-exited? thread
@deffnx {C Function} scm_thread_exited_p (thread)
-Return @code{#t} iff @var{thread} has exited.
+Return @code{#t} if @var{thread} has exited, or @code{#f} otherwise.
@end deffn
@c begin (texi-doc-string "guile" "yield")
@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
+@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{args@dots{}}
+the error to the current error port. The @var{arg} @dots{}
expressions are evaluated in the new thread.
@end deffn
-@deffn macro begin-thread first [rest@dots{}]
-Evaluate forms @var{first} and @var{rest} in a new thread formed by
+@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
in all threads is one way to avoid such problems.
@sp 1
-@deffn {Scheme Procedure} make-mutex . flags
+@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{flags} is
+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
@deffn {Scheme Procedure} mutex? obj
@deffnx {C Function} scm_mutex_p (obj)
-Return @code{#t} iff @var{obj} is a mutex; otherwise, return
+Return @code{#t} if @var{obj} is a mutex; otherwise, return
@code{#f}.
@end deffn
@code{wait-condition-variable}, except that the mutex is left in an
unlocked state when the function returns.)
-When @var{timeout} is also 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
+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} condition-variable? obj
@deffnx {C Function} scm_condition_variable_p (obj)
-Return @code{#t} iff @var{obj} is a condition variable; otherwise,
+Return @code{#t} if @var{obj} is a condition variable; otherwise,
return @code{#f}.
@end deffn
(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.
+@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 @var{body}, and is re-locked if
-@var{body} is re-entered by a captured continuation.
+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 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.
+@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 @var{body} must not
+(@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
@deffn {Scheme Procedure} fluid? obj
@deffnx {C Function} scm_fluid_p (obj)
-Return @code{#t} iff @var{obj} is a fluid; otherwise, return
+Return @code{#t} if @var{obj} is a fluid; otherwise, return
@code{#f}.
@end deffn
@deffn {Scheme Procedure} fluid-bound? fluid
@deffnx {C Function} scm_fluid_bound_p (fluid)
-Returns @code{#t} iff the given fluid is bound to a value, otherwise
+Returns @code{#t} if the given fluid is bound to a value, otherwise
@code{#f}.
@end deffn
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.
+@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)
affect. And introducing a new setting to existing code is often easier
with a parameter object than adding arguments.
-@defun make-parameter init [converter]
+@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}
(my-param 0.75)
(my-param) @result{} 3/4
@end example
-@end defun
+@end deffn
-@deffn {Scheme Syntax} parameterize ((param value) @dots{}) body @dots{}
+@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{body} is evaluated
-in that environment, the result is the return from the last form in
-@var{body}.
+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
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
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
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:
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.
+if it already started, or initiates it. In the former case, the calling
+thread may process other futures in the meantime.
@end deffn
relatively cheap as they re-use existing threads, and portable, since
they automatically use one thread per available CPU core.
-@deffn syntax parallel expr1 @dots{} exprN
+@deffn syntax parallel expr @dots{}
Evaluate each @var{expr} expression in parallel, each in its own thread.
-Return the results as a set of @var{N} multiple values
-(@pxref{Multiple Values}).
+Return the results of @var{n} expressions as a set of @var{n} multiple
+values (@pxref{Multiple Values}).
@end deffn
-@deffn syntax letpar ((var1 expr1) @dots{} (varN exprN)) body@dots{}
+@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 evaluate
-@var{body}.
+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 @dots{} lstN
-@deffnx {Scheme Procedure} par-for-each proc lst1 @dots{} lstN
+@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} @dots{}
-@var{elemN})}, 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.
+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.
Therefore, they should be avoided.
-@deffn {Scheme Procedure} n-par-map n proc lst1 @dots{} lstN
-@deffnx {Scheme Procedure} n-par-for-each n proc lst1 @dots{} lstN
+@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
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
+@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