mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-10 22:10:21 +02:00
* scheme-scheduling.texi (Arbiters): New explanatory text.
(Asyncs): New explanations and documentation. (Scheduling): Added menu entry descriptions. (Fluids): New documentation.
This commit is contained in:
parent
f4f2b29a5f
commit
ac0b7ebd29
2 changed files with 7 additions and 360 deletions
|
@ -1,3 +1,10 @@
|
|||
2001-04-11 Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
|
||||
|
||||
* scheme-scheduling.texi (Arbiters): New explanatory text.
|
||||
(Asyncs): New explanations and documentation.
|
||||
(Scheduling): Added menu entry descriptions.
|
||||
(Fluids): New documentation.
|
||||
|
||||
2001-04-11 Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
|
||||
|
||||
* scheme-procedures.texi (Lambda): Documented the lambda form.
|
||||
|
|
|
@ -1,360 +0,0 @@
|
|||
@page
|
||||
@node Scheduling
|
||||
@chapter 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::
|
||||
* Asyncs::
|
||||
* Dynamic Roots::
|
||||
* Threads::
|
||||
* Fluids::
|
||||
@end menu
|
||||
|
||||
|
||||
@node Arbiters
|
||||
@section Arbiters
|
||||
|
||||
@deffn primitive 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 primitive try-arbiter arb
|
||||
Return @code{#t} and lock the arbiter @var{arb} if the arbiter
|
||||
was unlocked. Otherwise, return @code{#f}.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive release-arbiter arb
|
||||
Return @code{#t} and unlock the arbiter @var{arb} if the
|
||||
arbiter was locked. Otherwise, return @code{#f}.
|
||||
@end deffn
|
||||
|
||||
|
||||
@node Asyncs
|
||||
@section Asyncs
|
||||
|
||||
@deffn primitive async thunk
|
||||
Create a new async for the procedure @var{thunk}.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive system-async thunk
|
||||
Create a new async for the procedure @var{thunk}. Also
|
||||
add it to the system's list of active async objects.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive async-mark a
|
||||
Mark the async @var{a} for future execution.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive system-async-mark a
|
||||
Mark the async @var{a} for future execution.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive run-asyncs list_of_a
|
||||
Execute all thunks from the asyncs of the list @var{list_of_a}.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive noop . args
|
||||
Do nothing. When called without arguments, return @code{#f},
|
||||
otherwise return the first argument.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive unmask-signals
|
||||
Unmask signals. The returned value is not specified.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive mask-signals
|
||||
Mask signals. The returned value is not specified.
|
||||
@end deffn
|
||||
|
||||
|
||||
@node Dynamic Roots
|
||||
@section 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 primitive 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 primitive 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 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 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 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
|
||||
@section Threads
|
||||
@cindex threads
|
||||
@cindex Guile threads
|
||||
|
||||
@strong{[NOTE: this chapter was written for Cygnus Guile and has not yet
|
||||
been updated for the Guile 1.x release.]}
|
||||
|
||||
Here is a the reference for Guile's threads. In this chapter I simply
|
||||
quote verbatim Tom Lord's description of the low-level primitives
|
||||
written in C (basically an interface to the POSIX threads library) and
|
||||
Anthony Green's description of the higher-level thread procedures
|
||||
written in scheme.
|
||||
@cindex posix threads
|
||||
@cindex Lord, Tom
|
||||
@cindex Green, Anthony
|
||||
|
||||
When using Guile threads, keep in mind that each guile thread is
|
||||
executed in a new dynamic root.
|
||||
|
||||
@menu
|
||||
* Low level thread primitives::
|
||||
* Higher level thread procedures::
|
||||
@end menu
|
||||
|
||||
|
||||
@node Low level thread primitives
|
||||
@subsection 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 primitive 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 describing the condition. [Error codes are currently
|
||||
meaningless integers. In the future, real values will be specified.]
|
||||
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 primitive 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 primitive yield
|
||||
If one or more threads are waiting to execute, calling yield forces an
|
||||
immediate context switch to one of them. Otherwise, yield has no effect.
|
||||
@end deffn
|
||||
|
||||
@c begin (texi-doc-string "guile" "make-mutex")
|
||||
@deffn primitive make-mutex
|
||||
Create a new mutex object.
|
||||
@end deffn
|
||||
|
||||
@c begin (texi-doc-string "guile" "lock-mutex")
|
||||
@deffn primitive lock-mutex mutex
|
||||
Lock @var{mutex}. If the mutex is already locked, the calling thread
|
||||
blocks until the mutex becomes available. The function returns when
|
||||
the calling thread owns the lock on @var{mutex}.
|
||||
@end deffn
|
||||
|
||||
@c begin (texi-doc-string "guile" "unlock-mutex")
|
||||
@deffn primitive unlock-mutex mutex
|
||||
Unlocks @var{mutex} if the calling thread owns the lock on @var{mutex}.
|
||||
Calling unlock-mutex on a mutex not owned by the current thread results
|
||||
in undefined behaviour. Once a mutex has been unlocked, one thread
|
||||
blocked on @var{mutex} is awakened and grabs the mutex lock.
|
||||
@end deffn
|
||||
|
||||
@c begin (texi-doc-string "guile" "make-condition-variable")
|
||||
@deffn primitive make-condition-variable
|
||||
@end deffn
|
||||
|
||||
@c begin (texi-doc-string "guile" "wait-condition-variable")
|
||||
@deffn primitive wait-condition-variable cond-var mutex
|
||||
@end deffn
|
||||
|
||||
@c begin (texi-doc-string "guile" "signal-condition-variable")
|
||||
@deffn primitive signal-condition-variable cond-var
|
||||
@end deffn
|
||||
|
||||
|
||||
@node Higher level thread procedures
|
||||
@subsection Higher level thread procedures
|
||||
|
||||
@c new by ttn, needs review
|
||||
|
||||
Higher level thread procedures are available by loading the
|
||||
@code{(ice-9 threads)} module. These provide standardized
|
||||
thread creation and mutex interaction.
|
||||
|
||||
@deffn primitive %thread-handler tag args@dots{}
|
||||
|
||||
This procedure is specified as the standard error-handler for
|
||||
@code{make-thread} and @code{begin-thread}. If the number of @var{args}
|
||||
is three or more, use @code{display-error}, otherwise display a message
|
||||
"uncaught throw to @var{tag}". All output is sent to the port specified
|
||||
by @code{current-error-port}.
|
||||
|
||||
Before display, global var @code{the-last-stack} is set to @code{#f}
|
||||
and signals are unmasked with @code{unmask-signals}.
|
||||
|
||||
[FIXME: Why distinguish based on number of args?! Cue voodoo music here.]
|
||||
@end deffn
|
||||
|
||||
@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 @code{%thread-handler} as the error
|
||||
handler.
|
||||
@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 @code{%thread-handler} as the error
|
||||
handler.
|
||||
@end deffn
|
||||
|
||||
@deffn macro with-mutex m [body@dots{}]
|
||||
Lock mutex @var{m}, evaluate @var{body}, and then unlock @var{m}.
|
||||
These sub-operations form the branches of a @code{dynamic-wind}.
|
||||
@end deffn
|
||||
|
||||
@deffn macro monitor first [rest@dots{}]
|
||||
Evaluate forms @var{first} and @var{rest} under a newly created
|
||||
anonymous mutex, using @code{with-mutex}.
|
||||
|
||||
[FIXME: Is there any way to access the mutex?]
|
||||
@end deffn
|
||||
|
||||
|
||||
@node Fluids
|
||||
@section Fluids
|
||||
|
||||
@deffn primitive 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 primitive fluid? obj
|
||||
Return @code{#t} iff @var{obj} is a fluid; otherwise, return
|
||||
@code{#f}.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive 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 primitive fluid-set! fluid value
|
||||
Set the value associated with @var{fluid} in the current dynamic root.
|
||||
@end deffn
|
||||
|
||||
@deffn primitive 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
|
||||
one after another. @var{thunk} must be a procedure with no argument.
|
||||
@end deffn
|
||||
|
||||
|
||||
@c Local Variables:
|
||||
@c TeX-master: "guile.texi"
|
||||
@c End:
|
Loading…
Add table
Add a link
Reference in a new issue