@lisp
(ensure-gtk-main)
@end lisp
-This function ensures that the Gtk+ main loop is started in background thread. If the loop has not been started or if had been terminated, restarts the background thread.
+This function ensures that the Gtk+ main loop is started.
-@RFunction join-main-thread
+If your Lisp supports multithreading, it starts the main loop in background thread (if it had not been started) and immediately returns. If your Lisp does not support multithreading, the main loop is started and waits for it to complete.
+
+Calls to @ref{ensure-gtk-main} must be paired by calls to @ref{leave-gtk-main}. When the @ref{leave-gtk-main} is called the same number of time as @ref{ensure-gtk-main} is called then the main loop quits (e.g., main loops are nested).
+
+It is also useful to call @ref{join-gtk-main} after @ref{ensure-gtk-main} to wait for main loop to quit.
+
+@RFunction leave-gtk-main
+@lisp
+(leave-gtk-main)
+@end lisp
+This function terminates the gtk main loop.
+
+Calls to @ref{ensure-gtk-main} must be paired by calls to @ref{leave-gtk-main}. When the @ref{leave-gtk-main} is called the same number of time as @ref{ensure-gtk-main} is called then the main loop quits (e.g., main loops are nested).
+
+
+@RFunction join-gtk-main
@lisp
-(join-main-thread)
+(join-gtk-thread)
@end lisp
-This function waits for the background thread that runs the Gtk+ main loop to quit.
+This function waits for the background thread that runs the Gtk+ main loop to quit. See @ref{ensure-gtk-main}.
@RFunction gtk-main-iteration
@lisp
(with-gdk-threads-lock (%gtk-main)))
#+thread-support
-(defvar *main-thread* nil)
-
-#+thread-support
-(at-finalize ()
- (when (and *main-thread* (bt:thread-alive-p *main-thread*))
- (bt:destroy-thread *main-thread*)
- (setf *main-thread* nil)))
-
-#+thread-support
-(defun ensure-gtk-main ()
- (when (and *main-thread* (not (bt:thread-alive-p *main-thread*)))
- (setf *main-thread* nil))
- (unless *main-thread*
- (setf *main-thread* (bt:make-thread (lambda () (gtk-main)) :name "cl-gtk2 main thread"))))
-
-#+thread-support
-(defun join-main-thread ()
- (when *main-thread*
- (bt:join-thread *main-thread*)))
-
-#+thread-support
-(export 'join-main-thread)
+(progn
+ (defvar *main-thread* nil)
+ (defvar *main-thread-level* nil)
+ (defvar *main-thread-lock* (bt:make-lock "*main-thread* lock"))
+
+ (at-finalize ()
+ (when (and *main-thread* (bt:thread-alive-p *main-thread*))
+ (bt:destroy-thread *main-thread*)
+ (setf *main-thread* nil)))
+
+ (defun ensure-gtk-main ()
+ (bt:with-lock-held (*main-thread-lock*)
+ (when (and *main-thread* (not (bt:thread-alive-p *main-thread*)))
+ (setf *main-thread* nil))
+ (unless *main-thread*
+ (setf *main-thread* (bt:make-thread (lambda () (gtk-main)) :name "cl-gtk2 main thread")
+ *main-thread-level* 0))
+ (incf *main-thread-level*))
+ (values))
+
+ (defun join-gtk-main ()
+ (when *main-thread*
+ (bt:join-thread *main-thread*)))
+
+ (defun leave-gtk-main ()
+ (bt:with-lock-held (*main-thread-lock*)
+ (decf *main-thread-level*)
+ (when (zerop *main-thread-level*)
+ (gtk-main-quit)))))
#-thread-support
-(defun ensure-gtk-main ()
- (gtk-main))
-
-(export 'ensure-gtk-main)
+(progn
+ (defun ensure-gtk-main ()
+ (gtk-main)
+ (values))
-#+thread-support
-(defun leave-gtk-main ()) ;noop on multithreading
+ (defun leave-gtk-main ()
+ (gtk-main-quit))
+
+ (defun join-gtk-main ()))
-#-thread-support
-(defun leave-gtk-main ()
- (gtk-main-quit))
+(export 'ensure-gtk-main)
(export 'leave-gtk-main)
+(export 'join-gtk-main)
+
(defcfun gtk-main-level :uint)
(defcfun gtk-main-quit :void)