The mysteries of GLib

Sun, 23 November, 2008

The more I explore GLib, the more difficulty I have with its design choices. I'll certainly find GLib useful, and I'm not dismissing it, but some promises have not been fulfilled.

The not-so-quiet main loop

GLib provides an interesting main loop feature, which allows your programs (console, daemon, not just UI) to be event-driven instead of procedural. What seems limiting is that only file descriptors can be event sources. Everyone knows that in Unix, everything is a file, right? So, why would you want an event source that's not a file descriptor? Oh, maybe because I'd like to declare events in the "user space" of my program, and not solely on low-level IO events.

The rationale given is that the Unix poll() function is the heart of the main loop. By using poll, the call is supposed to block until an interesting event occurs, sparing your CPU the incessant fast loop cycles. The only problem is, poll() doesn't work that way. Even the Unix man page seems confused about what the POLLIN flag means.

POLLIN There is data to read.

The behavior of poll() with POLLIN, however, is that it returns immediately with a POLLIN revent even when there is no data to read. That's because POLLIN really means "calling read() now won't block because the device is ready". POLLIN does not mean that there is data to read. This means your GLib app's check() must also call read() on every iteration to discern if there is actually data to read. It also means the CPU-saving long-blocking-until-an-event is actually a tight, wasteful quick-spinning loop. Maybe I should just put blocking read()s into dedicated threads.

Abstracting the wrong thing

So, since GLib is cross-platform, it abstracts away the platform-specific code, right? Not so with sockets. While a GIOChannel provides wrappers to do things like read a line from a file descriptor, there is no method given to create the file descriptor in the first place. So, to use sockets, I still need the #ifdef's for Windows-vs-Unix that I would write if I wasn't using a portability library.

The funny thing is, reading a line from a socket file descriptor (using recv()) is already the same on Windows/Unix. The priority seems to have been on making common interfaces for all file descriptors (files/sockets/pipes) instead of making common interfaces for the OS's in question (Windows/Unix).

One last thing...

GTK's combo boxes are oogly. Shoot, they're weird on Linux. There's no effort to use a native widget in Windows, and I'm sure on a Mac it looks even less native. Am I missing something here? Is there something special about MFC's licensing that forbids creating a GTK wrapper and requires a total re-write? It seems petty, and it's not a GLib-specific issue, but it could be a enough to make me look at a different library for cross-platform UI development.

In conclusion

Again, GLib appears great and I'm sure I'll use it. You get regex, a lexical scanner, and plenty of collection types. I just hope that when I explore those corners I won't encounter so many gotchas.

About Me

Erik Mackdanz is a software developer in Austin, Texas, along with everybody else.

Links