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