[cells-gtk-devel] start-app and multithreading?

Peter Hildebrandt peter.hildebrandt at gmail.com
Tue Dec 4 14:57:10 UTC 2007


Peter,

thanks for your reply.  I've made some progress, but before suggesting a  
patch I'd like to verify a few internals.

The GTK/GDK doc says, that you're fine as long as you use gdk/gtk only in  
callback functions such as on-click-handlers.  These callbacks are  
apparently run within the lock we supply for gtk-main.  However in   
"Idles, timeouts, and input functions" [1] you'd need to sorround calls to  
gtk/gdk with the equivalent of with-gdk-threads.

[1] http://www.gnu.org/software/guile-gnome/docs/gdk/html/Threads.html

Now I have poked around the code for a while, and did not find any of  
those.  Does cells-gtk use "Idles, timeouts, and input functions"?  If  
yes, where?

My second question:  Is there somewhere a list of all windows that have  
been created using to-be?  Or will I have to hack my own using :after  
methods?  (for details why I need this, see below)


To give you an idea where things are going, here's a short write-up of the  
status quo.  Test-gtk works perfectly.  If you have loaded test-gtk and  
changed into the package,

(start-app-in-thread 'test-gtk)

starts the sample app and returns right away to the REPL.

A typical example how this facility would be used is along these lines:

;; create a hello-world app
(defmodel app (gtk-app)
   ((label :accessor label :initform (c-in "") :initarg :label))
   (:default-initargs
     :title "TestApp"
     :kids (list
	   (mk-label :text (c? (label (upper self)))))))

;; run the app
(start-app-in-thread 'app)

;; modify a slot in the app instance and watch cells(-gtk) propagate the  
change
(setf (label (gtk-current-app)) "Hallo Welt")

Once the app is running, you can create further windows

(to-be (mk-window :title "a window"))

and also instances of the application

(to-be (make-instance 'app))

I love interactive programming :-)

Three limitations apply:

(1) To maintain compatibility with start-app's behavior, the window  
started by start-app-in-thread serves as the applications main window --  
gtk-main will exit, when this one is closed.  The application (or the  
developer at the REPL) has to make sure all windows created by to-be are  
closed using not-to-be before the main window exits.  If he doesn't, they  
will remain inactive, until a new application is started.  (This is where  
a list of all open windows would come in handy, the solution being only a  
mapcar away)

(2) If start-app-in-thread is called while an application is still  
running, it will schedule the request and return immediately.  The new  
application is opened once the previous one is closed.  This limitation  
appears to be necessary to prevent hassle with applications that are not  
thread-safe and thus do not like being execute several times within the  
same lisp process.  If you really want to run your application in  
parallel, use (to-be (make-instance 'app)) or (make-be 'app).

(3) For technical reasons, you CANNOT use start-app and  
start-app-in-thread from the same lisp session (i.e., if you have used  
one, you will have to RESTART your lisp session before you can use the  
other)

In other words, (start-app-in-thread) behaves just like (start-app), the  
only difference being, that it returns immediately, running gtk in the  
background.

Comments are welcome.  If this behavior seems to be ok, I will factor out  
the relevant changes against the current cvs version and provide a patch  
for testing.


Here's a little write up of the technical details involved.

The major issue appears to be that GTK expects gtk-main to be called only  
once for every given process.  If it is called repeatedly, gtk plays along  
nicely, if the call comes from the same thread as before, otherwise it  
does not signal an error, but simply discards any screen output.

Interestingly, g-thread-init and gdk-thread-init may well be called from a  
different thread.  However, once gtk-main has been called, our process is  
doomed to use the same thread for subsequent calls to gtk-main.  I did not  
find this behavior documented anywhere, but I have come to believe that it  
simply reflects the C programming style of compile-link-run -- hence it  
did not occur to anyone that this might be a problem.

As long as you run gtk-main directly from your lisp session, it is not a  
problem either, since it is always the same caller as well. However, once  
you try to spawn a thread every time you launch gtk-main, things  
inevitably break.

Therefore, my code creates one thread dedicated to running gtk-main.  This  
thread is fired up the first time start-app-in-thread is called and should  
remain alive throughout the lisp session.  Subsequent calls to  
start-app-in-thread use a mutex to communicate start-app requests to the  
running thread.

Regards,
Peter


On Mon, 03 Dec 2007 13:29:59 +0100, Peter Denno <peter.denno at nist.gov>  
wrote:

> On Monday 03 December 2007 06:50, Peter Hildebrandt wrote:
>> I've been trying for a while to launch a gtk application in a
>> distinct thread (using sbcl):
>>
>> (sb-thread:make-thread (lambda () (cells-gtk-init) (start-app
>> 'my-app)))
>>
>> The thread appears to runs fine up to the point where (gtk-main) is
>> called, however no window is ever being displayed.
>
> I ran in to this problem. I don't think I resolved it. It may well be
> the case that I still don't understand restarts completely. The code
> to look at is probably start-app in gtk-app.lisp.
>
> If you typically run under slime, just for experimentation, try
> running from a command prompt instead.
>
>>
>>
>> The objective is to launch a GUI in the background, then return
>> back to the REPL (with the GUI still runnning in the background),
>> and modifying the underlying data structures directly, while the
>> GUI visualizes the results.  For another app I have this up and
>> running with cl-glut, but here I'd like to have (cells-)gtk for
>> various reasons.
>>
>> Did anybody ever encounter this issue, or has any ideas how to work
>> around it?
>>
>> Help is highly appreciated,
>>
>> Peter
>>
>>
>> _______________________________________________
>> cells-gtk-devel site list
>> cells-gtk-devel at common-lisp.net
>> http://common-lisp.net/mailman/listinfo/cells-gtk-devel
>





More information about the cells-gtk-devel mailing list