mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-01 20:30:28 +02:00
Deprecate user asyncs
* libguile/async.c: * libguile/async.h: * libguile/deprecated.c: * libguile/deprecated.h (scm_async, scm_async_mark, scm_run_asyncs): Deprecate these functions, which comprise the "users asyncs" facility. * module/oop/goops.scm: Adapt to <async> deprecation. * doc/ref/api-scheduling.texi: * doc/ref/libguile-concepts.texi: * doc/ref/libguile-foreign-objects.texi: * doc/ref/posix.texi: Remove documentation on user asyncs, and replace references to "system asyncs" to be just "asyncs".
This commit is contained in:
parent
56d8d9a257
commit
59f09d185b
9 changed files with 130 additions and 182 deletions
|
@ -25,45 +25,28 @@
|
||||||
@subsection Asyncs
|
@subsection Asyncs
|
||||||
|
|
||||||
@cindex asyncs
|
@cindex asyncs
|
||||||
@cindex user asyncs
|
|
||||||
@cindex system asyncs
|
|
||||||
|
|
||||||
Asyncs are a means of deferring the execution of Scheme code until it is
|
Asyncs are a means of deferring the execution of Scheme code until it is
|
||||||
safe to do so.
|
safe to do so.
|
||||||
|
|
||||||
Guile provides two kinds of asyncs that share the basic concept but are
|
Asyncs are integrated into the core of Guile. A running Guile program
|
||||||
otherwise quite different: system asyncs and user asyncs. System asyncs
|
will periodically check if there are asyncs to run, invoking them as
|
||||||
are integrated into the core of Guile and are executed automatically
|
needed. For example, it is not possible to execute Scheme code in a
|
||||||
when the system is in a state to allow the execution of Scheme code.
|
POSIX signal handler, but in Guile a signal handler can enqueue a system
|
||||||
For example, it is not possible to execute Scheme code in a POSIX signal
|
async to be executed in the near future, when it is safe to do so.
|
||||||
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.
|
Asyncs can also be queued for threads other than the current one. This
|
||||||
This way, you can cause threads to asynchronously execute arbitrary
|
way, you can cause threads to asynchronously execute arbitrary code.
|
||||||
code.
|
|
||||||
|
|
||||||
User asyncs offer a convenient means of queuing 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
|
To cause the future asynchronous execution of a procedure in a given
|
||||||
thread, use @code{system-async-mark}.
|
thread, use @code{system-async-mark}.
|
||||||
|
|
||||||
Automatic invocation of system asyncs can be temporarily disabled by
|
Automatic invocation of asyncs can be temporarily disabled by calling
|
||||||
calling @code{call-with-blocked-asyncs}. This function works by
|
@code{call-with-blocked-asyncs}. This function works by temporarily
|
||||||
temporarily increasing the @emph{async blocking level} of the current
|
increasing the @emph{async blocking level} of the current thread while a
|
||||||
thread while a given procedure is running. The blocking level starts
|
given procedure is running. The blocking level starts out at zero, and
|
||||||
out at zero, and whenever a safe point is reached, a blocking level
|
whenever a safe point is reached, a blocking level greater than zero
|
||||||
greater than zero will prevent the execution of queued asyncs.
|
will prevent the execution of queued asyncs.
|
||||||
|
|
||||||
Analogously, the procedure @code{call-with-unblocked-asyncs} will
|
Analogously, the procedure @code{call-with-unblocked-asyncs} will
|
||||||
temporarily decrease the blocking level of the current thread. You
|
temporarily decrease the blocking level of the current thread. You
|
||||||
|
@ -74,7 +57,7 @@ In addition to the C versions of @code{call-with-blocked-asyncs} and
|
||||||
@code{call-with-unblocked-asyncs}, C code can use
|
@code{call-with-unblocked-asyncs}, C code can use
|
||||||
@code{scm_dynwind_block_asyncs} and @code{scm_dynwind_unblock_asyncs}
|
@code{scm_dynwind_block_asyncs} and @code{scm_dynwind_unblock_asyncs}
|
||||||
inside a @dfn{dynamic context} (@pxref{Dynamic Wind}) to block or
|
inside a @dfn{dynamic context} (@pxref{Dynamic Wind}) to block or
|
||||||
unblock system asyncs temporarily.
|
unblock asyncs temporarily.
|
||||||
|
|
||||||
@deffn {Scheme Procedure} system-async-mark proc [thread]
|
@deffn {Scheme Procedure} system-async-mark proc [thread]
|
||||||
@deffnx {C Function} scm_system_async_mark (proc)
|
@deffnx {C Function} scm_system_async_mark (proc)
|
||||||
|
@ -85,16 +68,18 @@ in @var{thread}. When @var{proc} has already been marked for
|
||||||
When @var{thread} is omitted, the thread that called
|
When @var{thread} is omitted, the thread that called
|
||||||
@code{system-async-mark} is used.
|
@code{system-async-mark} is used.
|
||||||
|
|
||||||
This procedure is not safe to be called from signal handlers. Use
|
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
|
@code{scm_sigaction} or @code{scm_sigaction_for_thread} to install
|
||||||
signal handlers.
|
signal handlers.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} call-with-blocked-asyncs proc
|
@deffn {Scheme Procedure} call-with-blocked-asyncs proc
|
||||||
@deffnx {C Function} scm_call_with_blocked_asyncs (proc)
|
@deffnx {C Function} scm_call_with_blocked_asyncs (proc)
|
||||||
Call @var{proc} and block the execution of system asyncs by one level
|
Call @var{proc} and block the execution of asyncs by one level for the
|
||||||
for the current thread while it is running. Return the value returned
|
current thread while it is running. Return the value returned by
|
||||||
by @var{proc}. For the first two variants, call @var{proc} with no
|
@var{proc}. For the first two variants, call @var{proc} with no
|
||||||
arguments; for the third, call it with @var{data}.
|
arguments; for the third, call it with @var{data}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@ -104,10 +89,10 @@ The same but with a C function @var{proc} instead of a Scheme thunk.
|
||||||
|
|
||||||
@deffn {Scheme Procedure} call-with-unblocked-asyncs proc
|
@deffn {Scheme Procedure} call-with-unblocked-asyncs proc
|
||||||
@deffnx {C Function} scm_call_with_unblocked_asyncs (proc)
|
@deffnx {C Function} scm_call_with_unblocked_asyncs (proc)
|
||||||
Call @var{proc} and unblock the execution of system asyncs by one
|
Call @var{proc} and unblock the execution of asyncs by one level for the
|
||||||
level for the current thread while it is running. Return the value
|
current thread while it is running. Return the value returned by
|
||||||
returned by @var{proc}. For the first two variants, call @var{proc}
|
@var{proc}. For the first two variants, call @var{proc} with no
|
||||||
with no arguments; for the third, call it with @var{data}.
|
arguments; for the third, call it with @var{data}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deftypefn {C Function} {void *} scm_c_call_with_unblocked_asyncs (void *(*proc) (void *data), void *data)
|
@deftypefn {C Function} {void *} scm_c_call_with_unblocked_asyncs (void *(*proc) (void *data), void *data)
|
||||||
|
@ -128,32 +113,6 @@ one level. This function must be used inside a pair of calls to
|
||||||
Wind}).
|
Wind}).
|
||||||
@end deftypefn
|
@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 Atomics
|
@node Atomics
|
||||||
@subsection Atomics
|
@subsection Atomics
|
||||||
|
|
||||||
|
@ -443,9 +402,9 @@ If @var{mutex} was locked by a thread that exited before unlocking it,
|
||||||
the next attempt to lock @var{mutex} will succeed, but
|
the next attempt to lock @var{mutex} will succeed, but
|
||||||
@code{abandoned-mutex-error} will be signalled.
|
@code{abandoned-mutex-error} will be signalled.
|
||||||
|
|
||||||
When a system async (@pxref{System asyncs}) is activated for a thread
|
When an async (@pxref{Asyncs}) is activated for a thread blocked in
|
||||||
blocked in @code{lock-mutex}, the wait is interrupted and the async is
|
@code{lock-mutex}, the wait is interrupted and the async is executed.
|
||||||
executed. When the async returns, the wait resumes.
|
When the async returns, the wait resumes.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deftypefn {C Function} void scm_dynwind_lock_mutex (SCM mutex)
|
@deftypefn {C Function} void scm_dynwind_lock_mutex (SCM mutex)
|
||||||
|
@ -526,12 +485,11 @@ as returned by @code{gettimeofday}. When the waiting is aborted,
|
||||||
signalled, @code{#t} is returned. The mutex is re-locked in any case
|
signalled, @code{#t} is returned. The mutex is re-locked in any case
|
||||||
before @code{wait-condition-variable} returns.
|
before @code{wait-condition-variable} returns.
|
||||||
|
|
||||||
When a system async is activated for a thread that is blocked in a
|
When an async is activated for a thread that is blocked in a call to
|
||||||
call to @code{wait-condition-variable}, the waiting is interrupted,
|
@code{wait-condition-variable}, the waiting is interrupted, the mutex is
|
||||||
the mutex is locked, and the async is executed. When the async
|
locked, and the async is executed. When the async returns, the mutex is
|
||||||
returns, the mutex is unlocked again and the waiting is resumed. When
|
unlocked again and the waiting is resumed. When the thread block while
|
||||||
the thread block while re-acquiring the mutex, execution of asyncs is
|
re-acquiring the mutex, execution of asyncs is blocked.
|
||||||
blocked.
|
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} signal-condition-variable condvar
|
@deffn {Scheme Procedure} signal-condition-variable condvar
|
||||||
|
@ -625,18 +583,18 @@ leaves guile mode while waiting for the condition variable.
|
||||||
|
|
||||||
@deftypefn {C Function} int scm_std_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
|
@deftypefn {C Function} int scm_std_select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
|
||||||
Like @code{select} but leaves guile mode while waiting. Also, the
|
Like @code{select} but leaves guile mode while waiting. Also, the
|
||||||
delivery of a system async causes this function to be interrupted with
|
delivery of an async causes this function to be interrupted with error
|
||||||
error code @code{EINTR}.
|
code @code{EINTR}.
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
@deftypefn {C Function} {unsigned int} scm_std_sleep ({unsigned int} seconds)
|
@deftypefn {C Function} {unsigned int} scm_std_sleep ({unsigned int} seconds)
|
||||||
Like @code{sleep}, but leaves guile mode while sleeping. Also, the
|
Like @code{sleep}, but leaves guile mode while sleeping. Also, the
|
||||||
delivery of a system async causes this function to be interrupted.
|
delivery of an async causes this function to be interrupted.
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
@deftypefn {C Function} {unsigned long} scm_std_usleep ({unsigned long} usecs)
|
@deftypefn {C Function} {unsigned long} scm_std_usleep ({unsigned long} usecs)
|
||||||
Like @code{usleep}, but leaves guile mode while sleeping. Also, the
|
Like @code{usleep}, but leaves guile mode while sleeping. Also, the
|
||||||
delivery of a system async causes this function to be interrupted.
|
delivery of an async causes this function to be interrupted.
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
|
|
||||||
|
@ -649,14 +607,14 @@ These two macros can be used to delimit a critical section.
|
||||||
Syntactically, they are both statements and need to be followed
|
Syntactically, they are both statements and need to be followed
|
||||||
immediately by a semicolon.
|
immediately by a semicolon.
|
||||||
|
|
||||||
Executing @code{SCM_CRITICAL_SECTION_START} will lock a recursive
|
Executing @code{SCM_CRITICAL_SECTION_START} will lock a recursive mutex
|
||||||
mutex and block the executing of system asyncs. Executing
|
and block the executing of asyncs. Executing
|
||||||
@code{SCM_CRITICAL_SECTION_END} will unblock the execution of system
|
@code{SCM_CRITICAL_SECTION_END} will unblock the execution of system
|
||||||
asyncs and unlock the mutex. Thus, the code that executes between
|
asyncs and unlock the mutex. Thus, the code that executes between these
|
||||||
these two macros can only be executed in one thread at any one time
|
two macros can only be executed in one thread at any one time and no
|
||||||
and no system asyncs will run. However, because the mutex is a
|
asyncs will run. However, because the mutex is a recursive one, the
|
||||||
recursive one, the code might still be reentered by the same thread.
|
code might still be reentered by the same thread. You must either allow
|
||||||
You must either allow for this or avoid it, both by careful coding.
|
for this or avoid it, both by careful coding.
|
||||||
|
|
||||||
On the other hand, critical sections delimited with these macros can
|
On the other hand, critical sections delimited with these macros can
|
||||||
be nested since the mutex is recursive.
|
be nested since the mutex is recursive.
|
||||||
|
|
|
@ -418,7 +418,7 @@ do such a thing on its own.
|
||||||
|
|
||||||
If you do not want to allow the running of asynchronous signal handlers,
|
If you do not want to allow the running of asynchronous signal handlers,
|
||||||
you can block them temporarily with @code{scm_dynwind_block_asyncs}, for
|
you can block them temporarily with @code{scm_dynwind_block_asyncs}, for
|
||||||
example. See @xref{System asyncs}.
|
example. @xref{Asyncs}.
|
||||||
|
|
||||||
Since signal handling in Guile relies on safe points, you need to make
|
Since signal handling in Guile relies on safe points, you need to make
|
||||||
sure that your functions do offer enough of them. Normally, calling
|
sure that your functions do offer enough of them. Normally, calling
|
||||||
|
|
|
@ -279,10 +279,10 @@ Note that the finalizer may be invoked in ways and at times you might
|
||||||
not expect. In particular, if the user's Guile is built with support
|
not expect. In particular, if the user's Guile is built with support
|
||||||
for threads, the finalizer may be called from any thread that is running
|
for threads, the finalizer may be called from any thread that is running
|
||||||
Guile. In Guile 2.0, finalizers are invoked via ``asyncs'', which
|
Guile. In Guile 2.0, finalizers are invoked via ``asyncs'', which
|
||||||
interleaves them with running Scheme code; @pxref{System asyncs}. In
|
interleaves them with running Scheme code; @pxref{Asyncs}. In Guile 2.2
|
||||||
Guile 2.2 there will be a dedicated finalization thread, to ensure that
|
there will be a dedicated finalization thread, to ensure that the
|
||||||
the finalization doesn't run within the critical section of any other
|
finalization doesn't run within the critical section of any other thread
|
||||||
thread known to Guile.
|
known to Guile.
|
||||||
|
|
||||||
In either case, finalizers run concurrently with the main program, and
|
In either case, finalizers run concurrently with the main program, and
|
||||||
so they need to be async-safe and thread-safe. If for some reason this
|
so they need to be async-safe and thread-safe. If for some reason this
|
||||||
|
|
|
@ -2007,11 +2007,11 @@ information.
|
||||||
|
|
||||||
The following procedures raise, handle and wait for signals.
|
The following procedures raise, handle and wait for signals.
|
||||||
|
|
||||||
Scheme code signal handlers are run via a system async (@pxref{System
|
Scheme code signal handlers are run via an async (@pxref{Asyncs}), so
|
||||||
asyncs}), so they're called in the handler's thread at the next safe
|
they're called in the handler's thread at the next safe opportunity.
|
||||||
opportunity. Generally this is after any currently executing
|
Generally this is after any currently executing primitive procedure
|
||||||
primitive procedure finishes (which could be a long time for
|
finishes (which could be a long time for primitives that wait for an
|
||||||
primitives that wait for an external event).
|
external event).
|
||||||
|
|
||||||
@deffn {Scheme Procedure} kill pid sig
|
@deffn {Scheme Procedure} kill pid sig
|
||||||
@deffnx {C Function} scm_kill (pid, sig)
|
@deffnx {C Function} scm_kill (pid, sig)
|
||||||
|
|
|
@ -44,91 +44,17 @@
|
||||||
|
|
||||||
/* {Asynchronous Events}
|
/* {Asynchronous Events}
|
||||||
*
|
*
|
||||||
* There are two kinds of asyncs: system asyncs and user asyncs. The
|
* Asyncs are used to run arbitrary code at the next safe point in a
|
||||||
* two kinds have some concepts in commen but work slightly
|
* specified thread. You can use them to trigger execution of Scheme
|
||||||
* differently and are not interchangeable.
|
* code from signal handlers or to interrupt a thread, for example.
|
||||||
*
|
|
||||||
* System asyncs are used to run arbitrary code at the next safe point
|
|
||||||
* in a specified thread. You can use them to trigger execution of
|
|
||||||
* Scheme code from signal handlers or to interrupt a thread, for
|
|
||||||
* example.
|
|
||||||
*
|
*
|
||||||
* Each thread has a list of 'activated asyncs', which is a normal
|
* Each thread has a list of 'activated asyncs', which is a normal
|
||||||
* Scheme list of procedures with zero arguments. When a thread
|
* Scheme list of procedures with zero arguments. When a thread
|
||||||
* executes a SCM_ASYNC_TICK statement (which is included in
|
* executes a SCM_ASYNC_TICK statement (which is included in SCM_TICK),
|
||||||
* SCM_TICK), it will call all procedures on this list.
|
* it will call all procedures on this list.
|
||||||
*
|
|
||||||
* Also, a thread will wake up when a procedure is added to its list
|
|
||||||
* of active asyncs and call them. After that, it will go to sleep
|
|
||||||
* again. (Not implemented yet.)
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* User asyncs are a little data structure that consists of a
|
|
||||||
* procedure of zero arguments and a mark. There are functions for
|
|
||||||
* setting the mark of a user async and for calling all procedures of
|
|
||||||
* marked asyncs in a given list. Nothing you couldn't quickly
|
|
||||||
* implement yourself.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* User asyncs. */
|
|
||||||
|
|
||||||
static scm_t_bits tc16_async;
|
|
||||||
|
|
||||||
/* cmm: this has SCM_ prefix because SCM_MAKE_VALIDATE expects it.
|
|
||||||
this is ugly. */
|
|
||||||
#define SCM_ASYNCP(X) SCM_TYP16_PREDICATE (tc16_async, X)
|
|
||||||
#define VALIDATE_ASYNC(pos, a) SCM_MAKE_VALIDATE_MSG(pos, a, ASYNCP, "user async")
|
|
||||||
|
|
||||||
#define ASYNC_GOT_IT(X) (SCM_SMOB_FLAGS (X))
|
|
||||||
#define SET_ASYNC_GOT_IT(X, V) (SCM_SET_SMOB_FLAGS ((X), ((V))))
|
|
||||||
#define ASYNC_THUNK(X) SCM_SMOB_OBJECT_1 (X)
|
|
||||||
|
|
||||||
|
|
||||||
SCM_DEFINE (scm_async, "async", 1, 0, 0,
|
|
||||||
(SCM thunk),
|
|
||||||
"Create a new async for the procedure @var{thunk}.")
|
|
||||||
#define FUNC_NAME s_scm_async
|
|
||||||
{
|
|
||||||
SCM_RETURN_NEWSMOB (tc16_async, SCM_UNPACK (thunk));
|
|
||||||
}
|
|
||||||
#undef FUNC_NAME
|
|
||||||
|
|
||||||
SCM_DEFINE (scm_async_mark, "async-mark", 1, 0, 0,
|
|
||||||
(SCM a),
|
|
||||||
"Mark the async @var{a} for future execution.")
|
|
||||||
#define FUNC_NAME s_scm_async_mark
|
|
||||||
{
|
|
||||||
VALIDATE_ASYNC (1, a);
|
|
||||||
SET_ASYNC_GOT_IT (a, 1);
|
|
||||||
return SCM_UNSPECIFIED;
|
|
||||||
}
|
|
||||||
#undef FUNC_NAME
|
|
||||||
|
|
||||||
SCM_DEFINE (scm_run_asyncs, "run-asyncs", 1, 0, 0,
|
|
||||||
(SCM list_of_a),
|
|
||||||
"Execute all thunks from the asyncs of the list @var{list_of_a}.")
|
|
||||||
#define FUNC_NAME s_scm_run_asyncs
|
|
||||||
{
|
|
||||||
while (! SCM_NULL_OR_NIL_P (list_of_a))
|
|
||||||
{
|
|
||||||
SCM a;
|
|
||||||
SCM_VALIDATE_CONS (1, list_of_a);
|
|
||||||
a = SCM_CAR (list_of_a);
|
|
||||||
VALIDATE_ASYNC (SCM_ARG1, a);
|
|
||||||
if (ASYNC_GOT_IT (a))
|
|
||||||
{
|
|
||||||
SET_ASYNC_GOT_IT (a, 0);
|
|
||||||
scm_call_0 (ASYNC_THUNK (a));
|
|
||||||
}
|
|
||||||
list_of_a = SCM_CDR (list_of_a);
|
|
||||||
}
|
|
||||||
return SCM_BOOL_T;
|
|
||||||
}
|
|
||||||
#undef FUNC_NAME
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static scm_i_pthread_mutex_t async_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
static scm_i_pthread_mutex_t async_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
@ -448,8 +374,6 @@ scm_critical_section_end (void)
|
||||||
void
|
void
|
||||||
scm_init_async ()
|
scm_init_async ()
|
||||||
{
|
{
|
||||||
tc16_async = scm_make_smob_type ("async", 0);
|
|
||||||
|
|
||||||
#include "libguile/async.x"
|
#include "libguile/async.x"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
|
|
||||||
SCM_API void scm_async_tick (void);
|
SCM_API void scm_async_tick (void);
|
||||||
SCM_API void scm_switch (void);
|
SCM_API void scm_switch (void);
|
||||||
SCM_API SCM scm_async (SCM thunk);
|
|
||||||
SCM_API SCM scm_async_mark (SCM a);
|
|
||||||
SCM_API SCM scm_system_async_mark (SCM a);
|
SCM_API SCM scm_system_async_mark (SCM a);
|
||||||
SCM_API SCM scm_system_async_mark_for_thread (SCM a, SCM thread);
|
SCM_API SCM scm_system_async_mark_for_thread (SCM a, SCM thread);
|
||||||
SCM_INTERNAL void scm_i_queue_async_cell (SCM cell, scm_i_thread *);
|
SCM_INTERNAL void scm_i_queue_async_cell (SCM cell, scm_i_thread *);
|
||||||
|
@ -41,7 +39,6 @@ SCM_INTERNAL int scm_i_setup_sleep (scm_i_thread *,
|
||||||
SCM obj, scm_i_pthread_mutex_t *m,
|
SCM obj, scm_i_pthread_mutex_t *m,
|
||||||
int fd);
|
int fd);
|
||||||
SCM_INTERNAL void scm_i_reset_sleep (scm_i_thread *);
|
SCM_INTERNAL void scm_i_reset_sleep (scm_i_thread *);
|
||||||
SCM_API SCM scm_run_asyncs (SCM list_of_a);
|
|
||||||
SCM_API SCM scm_noop (SCM args);
|
SCM_API SCM scm_noop (SCM args);
|
||||||
SCM_API SCM scm_call_with_blocked_asyncs (SCM proc);
|
SCM_API SCM scm_call_with_blocked_asyncs (SCM proc);
|
||||||
SCM_API SCM scm_call_with_unblocked_asyncs (SCM proc);
|
SCM_API SCM scm_call_with_unblocked_asyncs (SCM proc);
|
||||||
|
|
|
@ -578,6 +578,68 @@ SCM_DEFINE (scm_release_arbiter, "release-arbiter", 1, 0, 0,
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* User asyncs. */
|
||||||
|
|
||||||
|
static scm_t_bits tc16_async;
|
||||||
|
|
||||||
|
/* cmm: this has SCM_ prefix because SCM_MAKE_VALIDATE expects it.
|
||||||
|
this is ugly. */
|
||||||
|
#define SCM_ASYNCP(X) SCM_TYP16_PREDICATE (tc16_async, X)
|
||||||
|
#define VALIDATE_ASYNC(pos, a) SCM_MAKE_VALIDATE_MSG(pos, a, ASYNCP, "user async")
|
||||||
|
|
||||||
|
#define ASYNC_GOT_IT(X) (SCM_SMOB_FLAGS (X))
|
||||||
|
#define SET_ASYNC_GOT_IT(X, V) (SCM_SET_SMOB_FLAGS ((X), ((V))))
|
||||||
|
#define ASYNC_THUNK(X) SCM_SMOB_OBJECT_1 (X)
|
||||||
|
|
||||||
|
|
||||||
|
SCM_DEFINE (scm_async, "async", 1, 0, 0,
|
||||||
|
(SCM thunk),
|
||||||
|
"Create a new async for the procedure @var{thunk}.")
|
||||||
|
#define FUNC_NAME s_scm_async
|
||||||
|
{
|
||||||
|
scm_c_issue_deprecation_warning
|
||||||
|
("\"User asyncs\" are deprecated. Use closures instead.");
|
||||||
|
|
||||||
|
SCM_RETURN_NEWSMOB (tc16_async, SCM_UNPACK (thunk));
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
SCM_DEFINE (scm_async_mark, "async-mark", 1, 0, 0,
|
||||||
|
(SCM a),
|
||||||
|
"Mark the async @var{a} for future execution.")
|
||||||
|
#define FUNC_NAME s_scm_async_mark
|
||||||
|
{
|
||||||
|
VALIDATE_ASYNC (1, a);
|
||||||
|
SET_ASYNC_GOT_IT (a, 1);
|
||||||
|
return SCM_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
SCM_DEFINE (scm_run_asyncs, "run-asyncs", 1, 0, 0,
|
||||||
|
(SCM list_of_a),
|
||||||
|
"Execute all thunks from the asyncs of the list @var{list_of_a}.")
|
||||||
|
#define FUNC_NAME s_scm_run_asyncs
|
||||||
|
{
|
||||||
|
while (! SCM_NULL_OR_NIL_P (list_of_a))
|
||||||
|
{
|
||||||
|
SCM a;
|
||||||
|
SCM_VALIDATE_CONS (1, list_of_a);
|
||||||
|
a = SCM_CAR (list_of_a);
|
||||||
|
VALIDATE_ASYNC (SCM_ARG1, a);
|
||||||
|
if (ASYNC_GOT_IT (a))
|
||||||
|
{
|
||||||
|
SET_ASYNC_GOT_IT (a, 0);
|
||||||
|
scm_call_0 (ASYNC_THUNK (a));
|
||||||
|
}
|
||||||
|
list_of_a = SCM_CDR (list_of_a);
|
||||||
|
}
|
||||||
|
return SCM_BOOL_T;
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -585,6 +647,7 @@ scm_i_init_deprecated ()
|
||||||
{
|
{
|
||||||
scm_tc16_arbiter = scm_make_smob_type ("arbiter", 0);
|
scm_tc16_arbiter = scm_make_smob_type ("arbiter", 0);
|
||||||
scm_set_smob_print (scm_tc16_arbiter, arbiter_print);
|
scm_set_smob_print (scm_tc16_arbiter, arbiter_print);
|
||||||
|
tc16_async = scm_make_smob_type ("async", 0);
|
||||||
#include "libguile/deprecated.x"
|
#include "libguile/deprecated.x"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,6 +223,12 @@ SCM_DEPRECATED SCM scm_release_arbiter (SCM arb);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SCM_DEPRECATED SCM scm_async (SCM thunk);
|
||||||
|
SCM_DEPRECATED SCM scm_async_mark (SCM a);
|
||||||
|
SCM_DEPRECATED SCM scm_run_asyncs (SCM list_of_a);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void scm_i_init_deprecated (void);
|
void scm_i_init_deprecated (void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
;; once you have an instance. Perhaps FIXME to provide a
|
;; once you have an instance. Perhaps FIXME to provide a
|
||||||
;; smob-type-name->class procedure.
|
;; smob-type-name->class procedure.
|
||||||
<promise> <thread> <mutex> <condition-variable>
|
<promise> <thread> <mutex> <condition-variable>
|
||||||
<regexp> <hook> <bitvector> <random-state> <async>
|
<regexp> <hook> <bitvector> <random-state>
|
||||||
<directory> <array> <character-set>
|
<directory> <array> <character-set>
|
||||||
<dynamic-object> <guardian> <macro>
|
<dynamic-object> <guardian> <macro>
|
||||||
|
|
||||||
|
@ -3097,7 +3097,8 @@ var{initargs}."
|
||||||
;;;
|
;;;
|
||||||
|
|
||||||
(begin-deprecated
|
(begin-deprecated
|
||||||
(define-public <arbiter> (find-subclass <top> '<arbiter>)))
|
(define-public <arbiter> (find-subclass <top> '<arbiter>))
|
||||||
|
(define-public <async> (find-subclass <top> '<async>)))
|
||||||
|
|
||||||
(define <promise> (find-subclass <top> '<promise>))
|
(define <promise> (find-subclass <top> '<promise>))
|
||||||
(define <thread> (find-subclass <top> '<thread>))
|
(define <thread> (find-subclass <top> '<thread>))
|
||||||
|
@ -3107,7 +3108,6 @@ var{initargs}."
|
||||||
(define <hook> (find-subclass <top> '<hook>))
|
(define <hook> (find-subclass <top> '<hook>))
|
||||||
(define <bitvector> (find-subclass <top> '<bitvector>))
|
(define <bitvector> (find-subclass <top> '<bitvector>))
|
||||||
(define <random-state> (find-subclass <top> '<random-state>))
|
(define <random-state> (find-subclass <top> '<random-state>))
|
||||||
(define <async> (find-subclass <top> '<async>))
|
|
||||||
(define <directory> (find-subclass <top> '<directory>))
|
(define <directory> (find-subclass <top> '<directory>))
|
||||||
(define <array> (find-subclass <top> '<array>))
|
(define <array> (find-subclass <top> '<array>))
|
||||||
(define <character-set> (find-subclass <top> '<character-set>))
|
(define <character-set> (find-subclass <top> '<character-set>))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue