From 54928a79fed9ba4a40756c9072f3a7ca38413f96 Mon Sep 17 00:00:00 2001 From: Matt Birkholz Date: Sat, 17 Mar 2018 12:44:55 -0700 Subject: [PATCH] glib: Document with-glib-lock. --- src/glib/glib.pkg | 1 - src/glib/glib.scm | 2 -- src/glib/glib.texi | 43 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/glib/glib.pkg b/src/glib/glib.pkg index 0776325be..767f34c4a 100644 --- a/src/glib/glib.pkg +++ b/src/glib/glib.pkg @@ -114,7 +114,6 @@ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. (export () stop-glib-thread) (import (glib) - glib-mutex ;exposed by integrated with-glib-lock with-glib-lock assert-glib-locked run-glib-cleanups diff --git a/src/glib/glib.scm b/src/glib/glib.scm index 1fbdd0b9f..ef1aac4c4 100644 --- a/src/glib/glib.scm +++ b/src/glib/glib.scm @@ -133,13 +133,11 @@ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. (define (without-glib-lock thunk) (without-thread-mutex-lock glib-mutex thunk)) -#;(define-integrable (assert-glib-locked operator) #f) (define (assert-glib-locked operator) ;; Useful at least when debugging single threaded worlds. (if (not (eq? (current-thread) (thread-mutex-owner glib-mutex))) (outf-error ";glib not locked: "operator"\n"))) -#;(define-integrable (assert-without-interruption operator) #f) (define (assert-without-interruption operator) (if (not (get-thread-event-block)) (outf-error ";not without-interruption: "operator"\n"))) diff --git a/src/glib/glib.texi b/src/glib/glib.texi index 12a386c04..817dcf956 100644 --- a/src/glib/glib.texi +++ b/src/glib/glib.texi @@ -84,6 +84,31 @@ Scheme's representative of a toolkit resource is dropped and collected, the toolkit resource is freed, just as the C/Unix FFI's malloced aliens are automatically freed. +The GLib library, and thus libraries build ``on top'' of GLib, are not +ready for multiple threads. This is not an issue in single-processing +worlds, but future multi-processing worlds will need to ensure that +just one Scheme thread is ``in'' the toolkits. As of version 0.7, the +@code{with-glib-lock} procedure is provided. It serializes access to +the toolkits by locking a mutex. If the current thread has not used +this procedure to lock GLib, every callout to the toolkits will write +a warning line to stderr. + +Callbacks occur during callouts and execute while GLib is locked +(assuming GLib was locked when the callout was made). Thus using +@code{with-glib-lock} in a callback will cause a deadlock. + +@anchor{with-glib-lock} +@deffn Procedure with-glib-lock thunk +Locks GLib's mutex for the duration of @var{thunk}. Thus this +procedure cannot be used inside @var{thunk} or the current thread will +deadlock in the attempt to lock GLib's mutex twice. +@end deffn + +@deffn Procedure without-glib-lock thunk +Invokes @var{thunk} after releasing the current thread's lock on +GLib's mutex, and acquires a lock again before returning. +@end deffn + @node API Reference, Implementation Notes, Introduction, Top @unnumberedsec The GLib Package @@ -208,6 +233,10 @@ password, Scheme's @code{call-with-pass-phrase} procedure is called. If the ports are GCed or the stack unwound, pending operations are cancelled. Re-winding the stack is an error. +These procedures do @emph{not} require you to lock GLib first. They +seek to acquire the lock and so cannot be used while the current +thread holds the lock; it will deadlock. + @deffn Procedure open-input-gfile uri Returns an input port that reads from @var{uri}. @end deffn @@ -222,7 +251,8 @@ Returns a list of strings --- the names of the ``children'' of @end deffn A more direct interface to GIO's GFile operations is provided by the -following 8 classes and 18 operations. +following 8 classes and 18 operations. These procedures @emph{do} +require that the current thread lock GLib (@pxref{with-glib-lock}). @verbatim @@ -523,6 +553,11 @@ the target filesystem. @node Debugging Facilities, , GIO, API Reference @section Debugging Facilities +@deffn Procedure assert-glib-locked name +If the current thread does not own GLib's mutex, emit a warning line +on stderr. +@end deffn + @deffn Procedure stop-glib-thread A convenient procedure to call in an emergency. @end deffn @@ -566,14 +601,14 @@ In the example call to @code{gtk-label-get-text} above, a Scheme object represents the GtkLabel. It is a gtk-label instance, whose class is a specialization of the abstract gtk-object class. -@unnumberedsec Glib Thread +@unnumberedsec GLib Thread -When the Glib system loads, it starts a toolkit main loop with Scheme +When the GLib system loads, it starts a toolkit main loop with Scheme attached as an custom idle task. The main loop then re-starts Scheme, which creates a thread to ``run'' the toolkit (actually, return to it). Thus Scheme threads multitask with the toolkit. Scheme runs as an idle task in the toolkit, and the toolkit runs in a Scheme thread. -A program using the Glib system does not call @code{g_main_loop_run}. +A program using the GLib system does not call @code{g_main_loop_run}. It need only create toolkit objects and attach signal handlers to them. -- 2.25.1