Qt->glib main event loop patch (common main loop)

nf2 nf2 at scheinwelt.at
Mon Nov 14 00:03:31 GMT 2005


Matthias Ettrich wrote:

>On Saturday 12 November 2005 20:36, Gary Greene wrote:
>[...]
>  
>
>>B) GParts
>>Another interesting project which would benefit from a common main loop,
>>is GParts (http://gparts.blogspot.com/).
>>Dmitry M. Shatrov gave me some demo-code which worked well with the
>>patched Qt. One example embeds KTHML into a Gtk+ window. I put a
>>screenshot here: http://www.scheinwelt.at/~norbertf/common_main_loop/
>>    
>>
>
>You can do that without patching Qt, and definitely without having all of KDE 
>depend on Glib, even in Qt 3.
>
>Qt's event loop is flexible enough (even in Qt 3) to hook a Glib event loop 
>into it. One of the issues I had last time I did this was that Glib didn't 
>give me the information when the next Glib timer was supposed to fire. You 
>need that to set the proper timeout for the select statement. 
>
That's probably because you tried to do it "upside down", by using the 
select statement inside QEventloop to do the filedescriptor polling. I 
have chosen glib main loop to do the polling and removed the select() 
code from QEventloop. That's why in my Qt patch all fd's get watched and 
all the timers work correctly.

I think i need to explain a little, why glib main loop is the right 
choice to act as a "common main loop" provider, and Qt should be one of 
it's clients. Its because of its design.

Glib main loop has been designed to be totally toolkit independent. It 
has no Gtk+ or x11 code inside. As i mentioned earlier glib only depends 
on libc.

How does this work:

Basically glib main loop is nothing but a shared poll() function. You 
plug in your filedescriptors and the code which calculates poll 
timeouts, checks for events and dispatches your events as a GSource. 
This happens by attaching the GSource to an existing glib main loop 
context, which links in your code with function pointers and your fd's 
as list.

typedef struct {
  gboolean (*prepare)  (GSource    *source,  gint       *timeout_);
  gboolean (*check)    (GSource    *source);
  gboolean (*dispatch) (GSource    *source,  GSourceFunc callback,  
gpointer    user_data);

  ...
} GSourceFuncs;

g_source_attach() / g_source_destroy () adds and removes a Gsource 
module to/from the main loop context.

You can add filedescriptors to your GSource with g_source_add_poll ().

The nice thing about this concept is, that every GSource behaves like an 
independent "select" (or "poll") function itself and doesn't have to 
care about other GSources that get processed in the same main loop.

That makes it possible to run Qt, Gtk or even more GUI-toolkits and 
asynchronous libraries in the same thread, without even knowing of each 
other.

>I also suggested at one point to develop a common event loop abstraction for 
>Unix C/C++ toolkits. A small, self-contained library that every toolkit can 
>use. Basically a glorified select() abstraction.This wasn't met with much 
>enthusiasm, more with "glib is exactly that". And so is QtCore, and Xt :-)
>  
>
Sorry, but i don't think that QtCore has the appropriate design for 
acting as a "common event loop" provider. It has a "plug one complete 
event loop implementation or the other" concept. It doesn't allow to 
attach independent Event-Sources (code and filedescriptor lists) to a 
shared "main loop context" at any point of a program, like glib does.

Btw: I don't care if libglib gets hard linked into Qt or is loaded on 
demand (by subclassing QAbstractEventDispatcher - at least in Qt4 this 
should work). That's an implementation detail, and honestly i don't 
think that having libglib.so in memory is a big problem - because of all 
the applications and libraries that are loading it anyway. I have chosen 
the patching approach, because i didn't want to hack KDE but rather use 
it as a big "test case".

cheers,
Norbert





More information about the kde-core-devel mailing list