wingo pushed a commit to branch master
in repository guile.

commit 51d322b2d4a0ea90510087427dfa92d8384c9b76
Author: Andy Wingo <wi...@pobox.com>
Date:   Tue Oct 18 21:24:01 2016 +0200

    Update "Asyncs" section of manual.
    
    * doc/ref/api-scheduling.texi (Asyncs): Update.
---
 doc/ref/api-scheduling.texi |   83 ++++++++++++++++++++++++-------------------
 1 file changed, 46 insertions(+), 37 deletions(-)

diff --git a/doc/ref/api-scheduling.texi b/doc/ref/api-scheduling.texi
index 6048776..1fb9ec7 100644
--- a/doc/ref/api-scheduling.texi
+++ b/doc/ref/api-scheduling.texi
@@ -8,7 +8,7 @@
 @section Threads, Mutexes, Asyncs and Dynamic Roots
 
 @menu
-* Asyncs::                      Asynchronous procedure invocation.
+* Asyncs::                      Asynchronous interrupts.
 * Atomics::                     Atomic references.
 * Threads::                     Multiple threads of execution.
 * Mutexes and Condition Variables:: Synchronization primitives.
@@ -22,31 +22,48 @@
 
 
 @node Asyncs
-@subsection Asyncs
+@subsection Asynchronous Interrupts
 
 @cindex asyncs
+@cindex asynchronous interrupts
+@cindex interrupts
 
-Asyncs are a means of deferring the execution of Scheme code until it is
-safe to do so.
+Every Guile thread can be interrupted.  Threads running Guile code will
+periodically check if there are pending interrupts and run them if
+necessary.  To interrupt a thread, call @code{system-async-mark} on that
+thread.
 
-Asyncs are integrated into the core of Guile.  A running Guile program
-will periodically check if there are asyncs to run, invoking them as
-needed.  For example, it is not possible to execute Scheme code in a
-POSIX signal handler, but in Guile a signal handler can enqueue a system
-async to be executed in the near future, when it is safe to do so.
-
-Asyncs can also be queued for threads other than the current one.  This
-way, you can cause threads to asynchronously execute arbitrary code.
-
-To cause the future asynchronous execution of a procedure in a given
-thread, use @code{system-async-mark}.
+@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)
+Enqueue @var{proc} (a procedure with zero arguments) for future
+execution in @var{thread}.  When @var{proc} has already been enqueued
+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.
+@end deffn
 
-Automatic invocation of 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.
+Note that @code{scm_system_async_mark_for_thread} is not
+``async-signal-safe'' and so cannot be called from a C signal handler.
+(Indeed in general, @code{libguile} functions are not safe to call from
+C signal handlers.)
+
+Though an interrupt procedure can have any side effect permitted to
+Guile code, asynchronous interrupts are generally used either for
+profiling or for prematurely cancelling a computation.  The former case
+is mostly transparent to the program being run, by design, but the
+latter case can introduce bugs.  Like finalizers (@pxref{Foreign Object
+Memory Management}), asynchronous interrupts introduce concurrency in a
+program.  An asyncronous interrupt can run in the middle of some
+mutex-protected operation, for example, and potentially corrupt the
+program's state.
+
+If some bit of Guile code needs to temporarily inhibit interrupts, it
+can use @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
@@ -59,22 +76,6 @@ In addition to the C versions of 
@code{call-with-blocked-asyncs} and
 inside a @dfn{dynamic context} (@pxref{Dynamic Wind}) to block or
 unblock 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.
-
-As we mentioned above, Scheme signal handlers are already called within
-an async and so can run any Scheme code.  However, note that the C
-function is not safe to be called from C signal handlers.  Use
-@code{scm_sigaction} or @code{scm_sigaction_for_thread} to install
-signal handlers.
-@end deffn
-
 @deffn {Scheme Procedure} call-with-blocked-asyncs proc
 @deffnx {C Function} scm_call_with_blocked_asyncs (proc)
 Call @var{proc} and block the execution of asyncs by one level for the
@@ -113,6 +114,14 @@ one level.  This function must be used inside a pair of 
calls to
 Wind}).
 @end deftypefn
 
+Finally, note that threads can also be interrupted via POSIX signals.
+@xref{Signals}.  As an implementation detail, signal handlers will
+effectively call @code{system-async-mark} in a signal-safe way,
+eventually running the signal handler using the same async mechanism.
+In this way you can temporarily inhibit signal handlers from running
+using the above interfaces.
+
+
 @node Atomics
 @subsection Atomics
 

Reply via email to