Next: , Previous: , Up: Scheduling   [Contents][Index]


6.22.3 Asynchronous Interrupts

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 system-async-mark on that thread.

Scheme Procedure: system-async-mark proc [thread]
C Function: scm_system_async_mark (proc)
C Function: scm_system_async_mark_for_thread (proc, thread)

Enqueue proc (a procedure with zero arguments) for future execution in thread. When proc has already been enqueued for thread but has not been executed yet, this call has no effect. When thread is omitted, the thread that called system-async-mark is used.

Note that scm_system_async_mark_for_thread is not “async-signal-safe” and so cannot be called from a C signal handler. (Indeed in general, 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 (see 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 call-with-blocked-asyncs. This function works by temporarily increasing the 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 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 call-with-blocked-asyncs and call-with-unblocked-asyncs, C code can use scm_dynwind_block_asyncs and scm_dynwind_unblock_asyncs inside a dynamic context (see Dynamic Wind) to block or unblock asyncs temporarily.

Scheme Procedure: call-with-blocked-asyncs proc
C Function: scm_call_with_blocked_asyncs (proc)

Call proc and block the execution of asyncs by one level for the current thread while it is running. Return the value returned by proc. For the first two variants, call proc with no arguments; for the third, call it with data.

C Function: void * scm_c_call_with_blocked_asyncs (void * (*proc) (void *data), void *data)

The same but with a C function proc instead of a Scheme thunk.

Scheme Procedure: call-with-unblocked-asyncs proc
C Function: scm_call_with_unblocked_asyncs (proc)

Call proc and unblock the execution of asyncs by one level for the current thread while it is running. Return the value returned by proc. For the first two variants, call proc with no arguments; for the third, call it with data.

C Function: void * scm_c_call_with_unblocked_asyncs (void *(*proc) (void *data), void *data)

The same but with a C function proc instead of a Scheme thunk.

C Function: void scm_dynwind_block_asyncs ()

During the current dynwind context, increase the blocking of asyncs by one level. This function must be used inside a pair of calls to scm_dynwind_begin and scm_dynwind_end (see Dynamic Wind).

C Function: void scm_dynwind_unblock_asyncs ()

During the current dynwind context, decrease the blocking of asyncs by one level. This function must be used inside a pair of calls to scm_dynwind_begin and scm_dynwind_end (see Dynamic Wind).

Sometimes you want to interrupt a thread that might be waiting for something to happen, for example on a file descriptor or a condition variable. In that case you can inform Guile of how to interrupt that wait using the following procedures:

C Function: int scm_c_prepare_to_wait_on_fd (int fd)

Inform Guile that the current thread is about to sleep, and that if an asynchronous interrupt is signalled on this thread, Guile should wake up the thread by writing a zero byte to fd. Returns zero if the prepare succeeded, or nonzero if the thread already has a pending async and that it should avoid waiting.

C Function: int scm_c_prepare_to_wait_on_cond (scm_i_pthread_mutex_t *mutex, scm_i_pthread_cond_t *cond)

Inform Guile that the current thread is about to sleep, and that if an asynchronous interrupt is signalled on this thread, Guile should wake up the thread by acquiring mutex and signalling cond. The caller must already hold mutex and only drop it as part of the pthread_cond_wait call. Returns zero if the prepare succeeded, or nonzero if the thread already has a pending async and that it should avoid waiting.

C Function: void scm_c_wait_finished (void)

Inform Guile that the current thread has finished waiting, and that asynchronous interrupts no longer need any special wakeup action; the current thread will periodically poll its internal queue instead.

Guile’s own interface to sleep, wait-condition-variable, select, and so on all call the above routines as appropriate.

Finally, note that threads can also be interrupted via POSIX signals. See Signals. As an implementation detail, signal handlers will effectively call 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.


Next: , Previous: , Up: Scheduling   [Contents][Index]