elisp @@ macro
[bpt/guile.git] / doc / ref / api-scheduling.texi
index a301663..0d036be 100644 (file)
@@ -1,6 +1,6 @@
 @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.
 
@@ -247,7 +247,7 @@ Once @var{body} or @var{handler} returns, the return value is made the
 
 @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
 
@@ -267,7 +267,7 @@ specified; @code{#f} is returned otherwise).
 
 @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")
@@ -376,7 +376,7 @@ The returned mutex will be recursive.
 
 @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
 
@@ -446,9 +446,9 @@ which the calling thread will wait to be signalled before returning.
 @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
@@ -481,7 +481,7 @@ Return a new condition variable.
 
 @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
 
@@ -702,7 +702,7 @@ implicitly bound to some definite value).
 
 @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
 
@@ -726,7 +726,7 @@ Disassociate the given fluid from any value, making it unbound.
 
 @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
 
@@ -869,7 +869,7 @@ 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.
 
-@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}
@@ -888,7 +888,7 @@ canonical form.  For example,
 (my-param 0.75)
 (my-param) @result{} 3/4
 @end example
-@end defun
+@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
@@ -926,6 +926,21 @@ locations.  That includes the separate locations when outside any
 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
@@ -982,6 +997,24 @@ 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
@@ -995,6 +1028,22 @@ 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:
 
@@ -1024,7 +1073,8 @@ 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.
+if it already started, or initiates it.  In the former case, the calling
+thread may process other futures in the meantime.
 @end deffn