Hi,
Right now the gtk event look works like this : call gtk_main [ handleEvents. true ] whileTrue: [ Processor yield ] first problem the gtk_main function blocks the smalltalk processes. second problem if we enter in the event handling loop this is an active waiting it burns your CPU :P. As we can see the Gtk event loop doesn't feet at all with Smalltalk. since in the first case Smalltalk processes are not handled. In the second case the Smalltalk processes are handled but with an high cpu usage. So here is my proposal for a new Gtk event handling : first we create a c thread with the gtk_main function, when there is an event the c function : invoke_smalltalk_closure will be called signal a Smalltalk semaphore and lock a C muted. in Smalltalk inside an infinite loop we wait for an event with a Semaphore, when there is an event we get the signal get the event and handle it : - if it works well the result is sent to a C Function and signal the C Mutex - if there is an exception launch a debugger and launch a new gtk_main inner loop Some events can occurs if we are not inside the gtk_main loop so we handle it like this : in the c function : invoke_smalltalk_closure we check if the thread is the main thread if yes we call Gtk innerEvent function. Right now that works well (for example I can launch iLiad without any problem) I should fix the gtk_dialog_run because this function launch an inner loop outside the same thread that the main gtk_loop; the two loops are locked :D. If you have a better idea, cleaner approach any comments, remarks are welcome ! Cheers, Gwenael _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
> Right now that works well (for example I can launch iLiad without any
> problem) I should fix the gtk_dialog_run because this function launch an > inner loop outside the same thread that the main gtk_loop; the two loops > are locked :D. I think it should not be hard to rewrite gtk_dialog_run in Smalltalk, see http://www.google.com/codesearch/p?hl=en#ErvFMsc8kPE/pub/GNOME/sources/gtk+/2.6/gtk+-2.6.9.tar.gz|z8d-VbwUHqs/gtk+-2.6.9/gtk/gtkdialog.c around line 900. > If you have a better idea, cleaner approach any comments, remarks are > welcome ! Can you post a patch? I know it is in your github repo, but still... Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
On Thursday 11 February 2010 11:39:38 am Paolo Bonzini wrote:
> > Right now that works well (for example I can launch iLiad without any > > problem) I should fix the gtk_dialog_run because this function launch an > > inner loop outside the same thread that the main gtk_loop; the two loops > > are locked :D. > > I think it should not be hard to rewrite gtk_dialog_run in Smalltalk, see > > http://www.google.com/codesearch/p?hl=en#ErvFMsc8kPE/pub/GNOME/sources/gtk+ > /2.6/gtk+-2.6.9.tar.gz|z8d-VbwUHqs/gtk+-2.6.9/gtk/gtkdialog.c > > around line 900. > Normally a simple run [ self showAll ] That should be enough ^^ > > If you have a better idea, cleaner approach any comments, remarks are > > welcome ! > > Can you post a patch? I know it is in your github repo, but still... > I'll clean up the code and send it this week end ;) > Paolo Gwen _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
On 02/12/2010 10:59 AM, Gwenael Casaccio wrote:
> On Thursday 11 February 2010 11:39:38 am Paolo Bonzini wrote: >>> Right now that works well (for example I can launch iLiad without any >>> problem) I should fix the gtk_dialog_run because this function launch an >>> inner loop outside the same thread that the main gtk_loop; the two loops >>> are locked :D. >> >> I think it should not be hard to rewrite gtk_dialog_run in Smalltalk, see >> >> http://www.google.com/codesearch/p?hl=en#ErvFMsc8kPE/pub/GNOME/sources/gtk+ >> /2.6/gtk+-2.6.9.tar.gz|z8d-VbwUHqs/gtk+-2.6.9/gtk/gtkdialog.c >> >> around line 900. >> > > Normally a simple > run [ > self showAll > ] > > That should be enough ^^ When it is, the caller should have said "showAll". "Run" is blocking. Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
On Friday 12 February 2010 11:55:36 am Paolo Bonzini wrote:
> On 02/12/2010 10:59 AM, Gwenael Casaccio wrote: > > On Thursday 11 February 2010 11:39:38 am Paolo Bonzini wrote: > >>> Right now that works well (for example I can launch iLiad without any > >>> > >>> problem) I should fix the gtk_dialog_run because this function launch > >>> an inner loop outside the same thread that the main gtk_loop; the two > >>> loops are locked :D. > >> > >> I think it should not be hard to rewrite gtk_dialog_run in Smalltalk, > >> see > >> > >> http://www.google.com/codesearch/p?hl=en#ErvFMsc8kPE/pub/GNOME/sources/g > >> tk+ /2.6/gtk+-2.6.9.tar.gz|z8d-VbwUHqs/gtk+-2.6.9/gtk/gtkdialog.c > >> > >> around line 900. > > > > Normally a simple > > run [ > > > > self showAll > > > > ] > > > > That should be enough ^^ > > When it is, the caller should have said "showAll". "Run" is blocking. > > Paolo you'll find as an attached file the first release of the new gtk event loop. Gwen _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk gtk-event-loop.patch (15K) Download Attachment |
On Tuesday 16 February 2010 01:44:01 pm Gwenael Casaccio wrote:
> On Friday 12 February 2010 11:55:36 am Paolo Bonzini wrote: > > On 02/12/2010 10:59 AM, Gwenael Casaccio wrote: > > > On Thursday 11 February 2010 11:39:38 am Paolo Bonzini wrote: > > >>> Right now that works well (for example I can launch iLiad without > > >>> any > > >>> > > >>> problem) I should fix the gtk_dialog_run because this function launch > > >>> an inner loop outside the same thread that the main gtk_loop; the two > > >>> loops are locked :D. > > >> > > >> I think it should not be hard to rewrite gtk_dialog_run in Smalltalk, > > >> see > > >> > > >> http://www.google.com/codesearch/p?hl=en#ErvFMsc8kPE/pub/GNOME/sources > > >> /g tk+ /2.6/gtk+-2.6.9.tar.gz|z8d-VbwUHqs/gtk+-2.6.9/gtk/gtkdialog.c > > >> > > >> around line 900. > > > > > > Normally a simple > > > run [ > > > > > > self showAll > > > > > > ] > > > > > > That should be enough ^^ > > > > When it is, the caller should have said "showAll". "Run" is blocking. > > > > Paolo > > Hi, > > you'll find as an attached file the first release of the new gtk event > loop. > > Gwen we should extend the binding generator to generate thread safe gtk functions (with gdk_threads_enter the gtk_function gdk_threads_leave) Gwen _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
On 02/16/2010 03:32 PM, Gwenael Casaccio wrote:
> we should extend the binding generator to generate thread safe gtk functions > (with gdk_threads_enter the gtk_function gdk_threads_leave) Please expand? Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by MrGwen
Despite the apparent harshness of the review, it's really good stuff.
Thanks! Go through the comments in the order I mention (see asterisked numbers; each number refers to the text before) and commit the solution to each part (which may not be exactly what I write of course!) separately so it's easy to understand when things wrong. So let's start... first: where is the ChangeLog? :-) > + handleInnerEvent [ > + > + | event | > + event := GTK.Gtk events. > + event ifNotNil: [ | args | > + args := Array new: event n_params value. > + 1 to: args size do: [ :i | args at: i put: (event data value at: i - 1) ]. > + [ ^ (event receiver value perform: event selector value withArguments: args) ] on: Exception do: [ :exception | > + Behavior debuggerClass open ] ] > + ] Why the handler? It shouldn't be necessary as the inner event runs in its own Smalltalk process. *10* > + insideLoop [ > + > + | event | > + eventSem wait. > + event := GTK.Gtk events. > + event ifNotNil: [ | args | > + args := Array new: event n_params value. > + 1 to: args size do: [ :i | args at: i put: (event data value at: i - 1) ]. > + [ GTK.Gtk result: (event receiver value perform: event selector value withArguments: args) mutex: event mutex value ] on: Exception do: [ :exception | > + event status value: 0. > + Behavior debuggerClass open. > + GTK.Gtk result: nil mutex: event mutex value ] ] What about something like this instead, trapping Exception is almost always wrong (you trap Notification and Warning as well): [ [ result := event receiver value perform: event selector value withArguments: args ] on: System.UnhandledException do: [ :ex | event status value: 0. ex pass ] ] ensure: [ GTK.Gtk result: result mutex: event mutex value ] *11* > - sem := Semaphore new. > - GTK.Gtk main: sem. > + eventSem:= Semaphore new. > + GTK.Gtk eventSemaphore: eventSem. > + GTK.Gtk mainLoop. > + [ self insideLoop. What about instead keeping more of the old code: *3* sem := Semaphore new. GTK.Gtk mainLoop: sem. [ self insideLoop: sem ? (BTW I'd rename insideLoop to #processEvents or something like that). *2* > + true ] whileTrue: [ "DOES NOT WORK :::::: Processor yield" ] Is it needed at all, since we yield when waiting on sem? *1* Just do [ self insideLoop ] repeat (or the similar thing with sem if you accept my suggestion above). > diff --git a/packages/gtk/MoreFuncs.st b/packages/gtk/MoreFuncs.st > index a07ae29..d16210d 100644 > --- a/packages/gtk/MoreFuncs.st > +++ b/packages/gtk/MoreFuncs.st > @@ -12,9 +12,9 @@ Gtk class extend [ > > ] > > - main: aSemaphore [ > + mainLoop [ > <category: 'C call-outs'> > - <asyncCCall: 'gstGtkMain' args: #(#smalltalk )> > + <asyncCCall: 'gstGtkMain' args: #()> Doesn't need to be asynchronous anymore. In fact, I'd like to deprecate #asyncCCall:, I'm not even sure I understand their implications. Just make it return void. *4* > +static OOP result = NULL; This is never read?!? Also, maybe you want to move it to SmalltalkClosureStruct. *5* > +typedef struct SmalltalkClosureStruct { > + OOP receiver; > + OOP selector; > + OOP *data; > + OOP widget; > + int n_params; > + GMutex *mutex; > + int status > +} SmalltalkClosureStruct; > + > +static SmalltalkClosureStruct *event; Does not need to be static. *6* > -static void my_gtk_main (OOP semaphore); > +static void my_gtk_main (); As above, consider keeping the parameter. *3* > + event = malloc (sizeof (*event)); Nowhere freed. *7* > + event->receiver = stc->receiver; > + event->selector = stc->selector; registerOOP on these and args. Even better, construct a DirectedMessage object so that #insideLoop and #handleInnerEvent can just do "event message value send". Right now they have duplicated code! *7* > + if (g_thread_self () != main_thread) { g_thread_equal. *8* > + event->mutex = g_mutex_new (); > + g_mutex_lock (event->mutex); > + > + _gst_vm_proxy->syncSignal (event_sem, true); > + _gst_vm_proxy->wakeUp (); > + > + g_mutex_lock (event->mutex); Locking twice is surely wrong? *9* > + // Smalltalk event handling raises an exception launch an inner > + // event loop > + // > + if (event->status == 0) > + gtk_main (); Longer longer longer explanation needed? (And no // comments). Actually, let's postpone this to after the next iteration. > +void > +set_event_semaphore (OOP semaphore) > +{ > + event_sem = semaphore; > + _gst_vm_proxy->registerOOP (semaphore); > +} Unnecessary if you pass the semaphore to my_gtk_main. *3* > +void > +set_result (OOP anObject, GMutex *mutex) > +{ > + result = anObject; > + g_mutex_unlock (mutex); > +} Pass back the entire events struct so that you can also call unregisterOOP, free the args, and free the struct itself. If you make it like this: void set_event_result (SmalltalkClosureStruct *event, OOP anObject) { event->result = anObject; g_mutex_unlock (event->mutex); } you can even declare it as an instance-side method in SmalltalkClosureStruct. Much nicer that way! *5* > - self > + "self > connectSignal: 'paste-clipboard' to: self selector: #paste userData: nil; > connectSignal: 'cut-clipboard' to: self selector: #cut userData: nil. > > @@ -24,7 +24,7 @@ GTK.GtkTextView subclass: GtkTextWidget [ > connectSignal: 'begin-user-action' to: self selector: #'beginUserAction' userData: nil; > connectSignal: 'end-user-action' to: self selector: #'endUserAction' userData: nil; > connectSignal: 'insert-text' to: self selector: #'insert:at:text:size:' userData: nil; > - connectSignal: 'delete-range' to: self selector: #'delete:from:to:' userData: nil > + connectSignal: 'delete-range' to: self selector: #'delete:from:to:' userData: nil" What's the problem? Things like this should not be there for the new event loop to go in. > @@ -218,10 +221,7 @@ THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.'; > <category: 'file events'> > > (GTK.GtkFileChooserDialog save: 'Save image as...' parent: window) > - runNonBlockingAndDo: [ :dlg :res | > - imageName := dlg getFilename. > - dlg destroy. > - res = GTK.Gtk gtkResponseAccept ifTrue: [ self saveImage: [ ObjectMemory snapshot: imageName ] ] ] > + run Same here of course. > -<start>VisualGST.VisualGST open. > - GTK.Gtk main</start> > +<start> > + | a | > + VisualGST.VisualGST open. > + [ GTK.Gtk main ] fork. > + a := Semaphore new. > + a wait. > + 'byebye' printNl. > +</start> This is just debugging code I guess? Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by Paolo Bonzini-2
On 02/16/2010 05:00 PM, Paolo Bonzini wrote:
> On 02/16/2010 03:32 PM, Gwenael Casaccio wrote: >> we should extend the binding generator to generate thread safe gtk >> functions >> (with gdk_threads_enter the gtk_function gdk_threads_leave) > > Please expand? Uhm, from discussion on IRC I see what you're saying. While nice, this approach is probably a kind of dead end. You'd have a huge nightmare stemming from executing C callbacks in a thread and Smalltalk callbacks in another. Instead, we should keep the best of the two approaches we have. From your code we get the fact that polling runs in another thread. From what exists we get the fact that only one thread runs GTK+ stuff. Based on GLib's code, this is approximately the code that should run in the other thread: gpointer loop (gpointer data) { static GPollFD *fds; static int allocated_nfds; GMainLoop *loop = data; GMainContext *context = g_main_loop_get_context (loop); if (!fds) { fds = g_new (GPollFD, 20); allocated_nfds = 20; } while (g_main_loop_is_running (loop)) { int nfds, maxprio, timeout; if (!g_main_context_acquire (context)) { if (!g_main_context_pending (context)) continue; } else { g_main_context_prepare (context, &maxprio); while ((nfds = g_main_context_query (context, maxprio, &timeout, fds, allocated_nfds)) > allocated_nfds) { g_free (fds); fds = g_new (GPollFD, nfds); allocated_nfds = nfds; } // release the context so that the other thread can dispatch g_main_context_release (context); g_poll (timeout, fds, nfds); // If the other thread is now dispatching, calling // g_main_context_pending will wait until it releases the // context and then poll again---but without dispatching, // so we still have to signal the semaphore! if (!g_main_context_acquire (context)) { if (!g_main_context_pending (context)) continue; } else { g_main_context_check (context, maxprio, fds, nfds); g_main_context_release (context); } } // signal smalltalk semaphore and wake up other thread sched_yield (); } } static GMainLoop *loop; static GThread *thread; void gstGtkMain () { loop = g_main_loop_new (NULL, TRUE); thread = // create thread } void gstGtkMainQuit () { g_main_loop_quit (loop); g_thread_join (thread); } and the Smalltalk process will just call repeatedly (with an async C callout, contradicting what I said in the previous email): void gstGtkMainDispatch () { while (!g_main_context_acquire (context)) { g_main_context_pending (context); } g_main_context_dispatch (g_main_loop_get_context (loop)); g_main_context_release (context); } after waiting on a Semaphore. Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by MrGwen
On 02/16/2010 01:44 PM, Gwenael Casaccio wrote:
> Hi, > > you'll find as an attached file the first release of the new gtk event loop. And you'll find attached the second release of the new GTK event loop. :-) The handling of dialogs is needed with this one too, but it should not be hard (especially with the #runOnAnswer: temporary trick). I only tested it with example_tictactoe.st but it seems to work! Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk gst-eventloop-second-try.patch (12K) Download Attachment |
Free forum by Nabble | Edit this page |