mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-12 06:41:13 +02:00
Changes to the thread sections.
This commit is contained in:
parent
5441c65c48
commit
931b9657a0
1 changed files with 177 additions and 36 deletions
|
@ -289,6 +289,7 @@ executed in a new dynamic root.
|
||||||
@menu
|
@menu
|
||||||
* Low level thread primitives::
|
* Low level thread primitives::
|
||||||
* Higher level thread procedures::
|
* Higher level thread procedures::
|
||||||
|
* C level thread interface::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@ -303,12 +304,11 @@ executed in a new dynamic root.
|
||||||
Evaluate @code{(thunk)} in a new thread, and new dynamic context,
|
Evaluate @code{(thunk)} in a new thread, and new dynamic context,
|
||||||
returning a new thread object representing the thread.
|
returning a new thread object representing the thread.
|
||||||
|
|
||||||
If an error occurs during evaluation, call error-handler, passing it an
|
If an error occurs during evaluation, call error-handler, passing it
|
||||||
error code describing the condition. [Error codes are currently
|
an error code. If this happens, the error-handler is called outside
|
||||||
meaningless integers. In the future, real values will be specified.]
|
the scope of the new root -- it is called in the same dynamic context
|
||||||
If this happens, the error-handler is called outside the scope of the new
|
in which with-new-thread was evaluated, but not in the caller's
|
||||||
root -- it is called in the same dynamic context in which
|
thread.
|
||||||
with-new-thread was evaluated, but not in the caller's thread.
|
|
||||||
|
|
||||||
All the evaluation rules for dynamic roots apply to threads.
|
All the evaluation rules for dynamic roots apply to threads.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
@ -337,6 +337,10 @@ blocks until the mutex becomes available. The function returns when
|
||||||
the calling thread owns the lock on @var{mutex}. Locking a mutex that
|
the calling thread owns the lock on @var{mutex}. Locking a mutex that
|
||||||
a thread already owns will succeed right away and will not block the
|
a thread already owns will succeed right away and will not block the
|
||||||
thread. That is, Guile's mutexes are @emph{recursive}.
|
thread. That is, Guile's mutexes are @emph{recursive}.
|
||||||
|
|
||||||
|
When a system async is activated for a thread that is blocked in a
|
||||||
|
call to @code{lock-mutex}, the waiting is interrupted and the async is
|
||||||
|
executed. When the async returns, the waiting is resumed.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} try-mutex mutex
|
@deffn {Scheme Procedure} try-mutex mutex
|
||||||
|
@ -357,6 +361,7 @@ with a call to @code{unlock-mutex}. Only the last call to
|
||||||
|
|
||||||
@c begin (texi-doc-string "guile" "make-condition-variable")
|
@c begin (texi-doc-string "guile" "make-condition-variable")
|
||||||
@deffn {Scheme Procedure} make-condition-variable
|
@deffn {Scheme Procedure} make-condition-variable
|
||||||
|
Make a new condition variable.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@c begin (texi-doc-string "guile" "wait-condition-variable")
|
@c begin (texi-doc-string "guile" "wait-condition-variable")
|
||||||
|
@ -366,18 +371,25 @@ Wait until @var{cond-var} has been signalled. While waiting,
|
||||||
is locked again when this function returns. When @var{time} is given,
|
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
|
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
|
can be either a integer as returned by @code{current-time} or a pair
|
||||||
as returned by @code{gettimeofday}. When the waiting is aborted the
|
as returned by @code{gettimeofday}. When the waiting is aborted,
|
||||||
mutex is locked and @code{#f} is returned. When the condition
|
@code{#f} is returned. When the condition variable has in fact been
|
||||||
variable is in fact signalled, the mutex is also locked and @code{#t}
|
signalled, @code{#t} is returned. The mutex is re-locked in any case
|
||||||
is returned.
|
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
|
@end deffn
|
||||||
|
|
||||||
@c begin (texi-doc-string "guile" "signal-condition-variable")
|
@c begin (texi-doc-string "guile" "signal-condition-variable")
|
||||||
@deffn {Scheme Procedure} signal-condition-variable cond-var
|
@deffn {Scheme Procedure} signal-condition-variable cond-var
|
||||||
|
Wake up one thread that is waiting for @var{cv}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@c begin (texi-doc-string "guile" "broadcast-condition-variable")
|
@c begin (texi-doc-string "guile" "broadcast-condition-variable")
|
||||||
@deffn {Scheme Procedure} signal-condition-variable cond-var
|
@deffn {Scheme Procedure} signal-condition-variable cond-var
|
||||||
|
Wake up all threads that are waiting for @var{cv}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@node Higher level thread procedures
|
@node Higher level thread procedures
|
||||||
|
@ -389,30 +401,16 @@ Higher level thread procedures are available by loading the
|
||||||
@code{(ice-9 threads)} module. These provide standardized
|
@code{(ice-9 threads)} module. These provide standardized
|
||||||
thread creation and mutex interaction.
|
thread creation and mutex interaction.
|
||||||
|
|
||||||
@deffn {Scheme Procedure} %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{}]
|
@deffn macro make-thread proc [args@dots{}]
|
||||||
Apply @var{proc} to @var{args} in a new thread formed by
|
Apply @var{proc} to @var{args} in a new thread formed by
|
||||||
@code{call-with-new-thread} using @code{%thread-handler} as the error
|
@code{call-with-new-thread} using a default error handler that display
|
||||||
handler.
|
the error to the current error port.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn macro begin-thread first [rest@dots{}]
|
@deffn macro begin-thread first [rest@dots{}]
|
||||||
Evaluate forms @var{first} and @var{rest} in a new thread formed by
|
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
|
@code{call-with-new-thread} using a default error handler that display
|
||||||
handler.
|
the error to the current error port.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn macro with-mutex m [body@dots{}]
|
@deffn macro with-mutex m [body@dots{}]
|
||||||
|
@ -423,10 +421,153 @@ These sub-operations form the branches of a @code{dynamic-wind}.
|
||||||
@deffn macro monitor first [rest@dots{}]
|
@deffn macro monitor first [rest@dots{}]
|
||||||
Evaluate forms @var{first} and @var{rest} under a newly created
|
Evaluate forms @var{first} and @var{rest} under a newly created
|
||||||
anonymous mutex, using @code{with-mutex}.
|
anonymous mutex, using @code{with-mutex}.
|
||||||
|
|
||||||
[FIXME: Is there any way to access the mutex?]
|
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@node C level thread interface
|
||||||
|
@subsection C level thread interface
|
||||||
|
|
||||||
|
You can create and manage threads, mutexes, and condition variables
|
||||||
|
with the C versions of the primitives above. For example, you can
|
||||||
|
create a mutex with @code{scm_make_mutex} and lock it with
|
||||||
|
@code{scm_lock_mutex}. In addition to these primitives there is also
|
||||||
|
a second set of primitives for threading related things. 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.
|
||||||
|
|
||||||
|
@deftp {C Data Type} scm_t_thread
|
||||||
|
This data type represents a thread, to be used with scm_thread_create,
|
||||||
|
etc.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
@deftypefun {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 deftypefun
|
||||||
|
|
||||||
|
@deftypefun {C Function} void scm_thread_detach (scm_t_thread t)
|
||||||
|
Detach the thread @var{t}. See @code{scm_thread_create}.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun {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 deftypefun
|
||||||
|
|
||||||
|
@deftypefun {C Function} scm_t_thread scm_thread_self ()
|
||||||
|
Return the handle of the calling thread.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftp {C Data Type} scm_t_mutex
|
||||||
|
This data type represents a mutex, to be used with scm_mutex_init,
|
||||||
|
etc.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
@deftypefun {C Function} void scm_mutex_init (scm_t_mutex *m)
|
||||||
|
Initialize the mutex structure pointed to by @var{m}.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun {C Function} void scm_mutex_destroy (scm_t_mutex *m)
|
||||||
|
Deallocate all resources associated with @var{m}.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun {C Function} void scm_mutex_lock (scm_t_mutex *m)
|
||||||
|
Lock the mutex @var{m}. When it is already locked by a different
|
||||||
|
thread, wait until it becomes available. Locking a mutex that is
|
||||||
|
already locked by the current threads is not allowd and results in
|
||||||
|
undefined behavior. The mutices are not guaranteed to be fair. That
|
||||||
|
is, a thread that attempts a lock after yourself might be granted it
|
||||||
|
before you.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun {C Function} int scm_mutex_trylock (scm_t_mutex *m)
|
||||||
|
Lock @var{m} as with @code{scm_mutex_lock} but don't wait when this
|
||||||
|
does succeed immediately. Returns non-zero when the mutex could in
|
||||||
|
fact be locked , and zero when it is already locked by some other
|
||||||
|
thread.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun {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, else the behavior is undefined.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftp {C Data Type} scm_t_cond
|
||||||
|
This data type represents a condition variable, to be used with
|
||||||
|
scm_cond_init, etc.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
@deftypefun {C Function} void scm_cond_init (scm_t_cond *c)
|
||||||
|
Initialize the mutex structure pointed to by @var{c}.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun {C Function} void scm_cond_destroy (scm_t_cond *c)
|
||||||
|
Deallocate all resources associated with @var{c}.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun {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 deftypefun
|
||||||
|
|
||||||
|
@deftypefun {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 deftypefun
|
||||||
|
|
||||||
|
@deftypefun {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 deftypefun
|
||||||
|
|
||||||
|
@deftypefun {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 deftypefun
|
||||||
|
|
||||||
|
@deftp {C Type} scm_t_key
|
||||||
|
This type represents a key for a thread-specific value.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
@deftypefun {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 deftypefun
|
||||||
|
|
||||||
|
@deftypefun {C Function} void scm_key_delete (scm_t_key key)
|
||||||
|
This function makes @var{key} invalid as a key for thread-specific data.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun {C Function} void scm_key_setspecific (scm_t_key key, const void *value)
|
||||||
|
Associate @var{value} with @var{key} in the calling thread.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun {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 deftypefun
|
||||||
|
|
||||||
|
@deftypefun {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 deftypefun
|
||||||
|
|
||||||
@node Fluids
|
@node Fluids
|
||||||
@section Fluids
|
@section Fluids
|
||||||
|
@ -435,12 +576,12 @@ anonymous mutex, using @code{with-mutex}.
|
||||||
|
|
||||||
@c FIXME::martin: Review me!
|
@c FIXME::martin: Review me!
|
||||||
|
|
||||||
Fluids are objects to store values in. They have a few properties which
|
Fluids are objects to store values in. They have a few properties
|
||||||
make them useful in certain situations: Fluids can have one value per
|
which make them useful in certain situations: Fluids can have one
|
||||||
dynamic root (@pxref{Dynamic Roots}), so that changes to the value in a
|
value per dynamic root (@pxref{Dynamic Roots}), so that changes to the
|
||||||
fluid are only visible in the same dynamic root. Since threads are
|
value in a fluid are only visible in the same dynamic root. Since
|
||||||
executed in separate dynamic roots, fluids can be used for thread local
|
threads are executed in separate dynamic roots, fluids can be used for
|
||||||
storage (@pxref{Threads}).
|
thread local storage (@pxref{Threads}).
|
||||||
|
|
||||||
Fluids can be used to simulate the desirable effects of dynamically
|
Fluids can be used to simulate the desirable effects of dynamically
|
||||||
scoped variables. Dynamically scoped variables are useful when you
|
scoped variables. Dynamically scoped variables are useful when you
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue