mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
946 lines
36 KiB
Text
946 lines
36 KiB
Text
@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 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)
|
|
@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
|
|
|
|
@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 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
|
|
|
|
@deffn {Scheme Procedure} thread-exited? thread
|
|
@deffnx {C Function} scm_thread_exited_p (thread)
|
|
Return @code{#t} iff @var{thread} has exited.
|
|
@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
|
|
|
|
@deffn {Scheme Procedure} make-fair-condition-variable
|
|
@deffnx {C Function} scm_make_fair_condition_variable ()
|
|
Make a new fair 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-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) ...) 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:
|