SigC::, sigc::, Build Environment, and Main Event Loop Update from deeply-nested recursive functions.



Hi: nothing interesting to see here, no outstanding issues or urgent bugs, so if you've anything at all better to do, please just move along :-)

However, I did want to post a status update to a suggestion Murray made two weeks ago in "The flexibility of printed information" thread. There were several disparate issues under discussion involving documentation, signals, threads, the Main Event Loop, support, errors
in my own build environment, and misguided comments (from myself) ensuing therefrom. I can't now seem to locate the exact post that I had originally replied to, nor even my original reply in the old thread. Given the turgidity and confusion contained therein, I can't say its sorely missed. Saves a bit of personal embarrassment, in fact :-)

But at least some of the topics seemed to be of general interest, and I did promise to update r.e. my progress, so (in no particular order) I'm posting it here:

1. Main Event Loop Update. I had written a recursive function method for a TreeStore RowInfo class, RowInfo::complete_row(), that given a starting point in a somewhat extended filesystem (i.e., a filesystem spread out over several mount points sort of like what a poor man's Logical Volume Manager might do, but without the OS support), would recursively descend through the filesystem and record date, size, and application-specific filetype information on each of the files and directories encountered. The complete_row() method sticks all this information into a Gtk::TreeStore but (as one might imagine) even on a good day on large filesystems complete_row()'s execution is somewhat slower than instantaneous. I needed a way to keep the user up2date on its progress, and provide a StopButton to tell complete_row() to quit in the event the user started the recursion in some high place that on second thought he decided he'd really rather not know anything more about.

   I mean, how many times have *you* ever interrupted a "du" or "find"?

   My original attempt at a solution involved placing complete_row() in a separate worker thread and having it communicate via signals with the master UI thread. And this sorta kinda almost worked, just not reliably: its principal defect arose from its origins in a non-threaded application that used a all-purpose do-everything Gtk::TreeStore for all purposes and to do everything, including (but by no means limited to) being hooked into the GUI's TreeView whilst it itself was being constructed.

Murray tactfully suggested this was not the usually recommended approach to multi-threaded application design, and (as I already had a working signal mechanism in place) suggested the following (appropriately placed) one-line solution:

   while(Gtk::Main::instance()->events_pending())
       Gtk::Main::instance()->iteration();

...this being from
   http://www.gtkmm.org/docs/gtkmm-2.4/examples/book/update_ui/
and does exacly what I want: (a) upon entry the recursive complete_row() method checks its parent C_RowInfo class's static signal member for instructions from the Main Event Loop (e.g. to flag the current row as incomplete and quit if the user has pressed the "stop" button"), (b) upon the recursive completion of each directory, complete_row() emits a signal of its own containing the path of the just-completed directory, then executes the above one-line while() loop, which (c) causes an iteration through the Main Event Loop. The Main Event Loop (d) in turn then receives the just-emitted complete_row signal, writes the directory path to the relevant StatusBar to provide the user some progress context, and checks the "on_StopButton_clicked()" callback to see if the user has seen enough. If the user has, then (e) a signal is sent to the C_RowInfo class static C_RowSignal member, which then (f) causes complete_row() to recursively unwind and quit. Like clockwork. And all within a single thread.

   You might have a similar problem in need of an obvious solution, and -- like myself -- have neglected to look in the obvious place. Which is why I have included it here.

2. SigC::, sigc::, and My 0wn Turgid Build Environent. Actually, I had hoped to post the above Event Loop update solution ten days ago, as it only took a few hours to implement. Unfortunately, there was another more pressing item in my exchange with Murray that I wished to address first. This had to do with an (ad)mixture of SigC:: and sigc:: namespaces in my code, and the resulting confusion that ensued when I coded signals. Glade generates code that uses SigC::, SigC:: was visible to my compilation, and SigC:: is what I used. But all the recent gtkmm/glibmm documentation referred to sigc::, and I was tangling myself up trying to distinguish slot factory SigC::Slot() from slot factory sigc::mem_fun(). Amongst other issues, including a disconcerting

(process:4535): GLib-GObject-CRITICAL **: file gobject.c: line 853>
(g_object_newv): assertion `G_TYPE_IS_OBJECT (object_type)' failed

error emitted at process startup. Which I had traced (gdb is my fiend:) to the initialization of the aforementioned static C_RowSignal signal member in my C_RowInfo class. Now C_RowSignal itself is a class that contained a static SigC::signal member, and as such (apparently) needed to be derived from Glib::Object. All of which made perfect sense to me, but not (apparently) to the assertion at line 853 of glib::gobject.c.

But don't Go There: you're needed here at home. Besides, this one too is solved: for various reasons far beyond my personal control, my target platform is plain vanilla completely un-updated Red Hat Linux 7.3 and, due to an inability to find an updated Render package, I had prevented myself from doing a complete upgrade of my build environment to gtk+/gtkmm-2.4. I was seemingly stuck at glib-2.3.6, glibmm-2.3.8, gtk+-2.2.4, and gtkmm-2.2.12. The first two required libsigc++-2.0.16, whilst the latter needed libsigc++-1.2.5. Which is why the old SigC:: namespace was visible in my build. And I didn't know any better than not to use it. But I couldn't get rid of libsigc++-1.2.x unless I could upgrade to gtk+-2.4.x/gtkmm-2.4.x, and I couldn't do that unless I had updated the Render header files, which I thought were part of the system X11/XFree86 package, which I thought I couldn't require my intended customers to upgrade, so I thought I was stuck at gtk+/gtkmm-2.2.x.

  Only I thought wrong. About Render I mean. I finally found a suitable render-0.8 tarball at a suitably obscure SGI (bless 'em) ftp site, upgraded to glib-2.6.6/glibmm-2.6.1, gtk+-2.6.10/gtkmm-2.6.5, libglade/libglademm-2.4.2, and glade-2.6.8/glademm-2.6.0, all on stock vanilla totally un-upgraded Red Hat Linux 7.3 and without libsigc++-1.2.anything. As coded on a closed-course by a "professional" systems programmer: don't try these stunts at home...

  (But if you've read thus far and think you really must, reply to this and I'll see if I can post my library build script.)

  The upshot of removing libsigc++1.2.x was that SigC:: namespace became invisible outside the Glade-generated code (I still don't know why it is visible even there -- possibly something todo with #include <sigc++/compatibility.h>:) and I was mercifully forced to convert all my own signal stuff to sigc:: after which I found I no longer needed to derive my C_RowSignal class from Glib::Object, and those sniveling start-up objections from gobject.c magically disappeared.

  The immoral being that on gtkmm-list one can learn something new
  every day.

  On a *really* bad day, *two* new things...

3. One of the new things I'd like to learn today is this: the odd documentation frustration notwithstanding, in general I've been *very* impressed with the overall code quality of Gtk+/Gtkmm. As a pleasant if unexpected surprise, in two and a half years of development this archive application the only bugs I've been able to positively identify have been my
own. Yeah, I know that gtk+/gtkmm has some some, but I've tried hard (if unsuccessfully) to keep my particular application simple so as not to exercise them. So I'm personally quite pleased. However, I have a partner and colleague who has personal friends at Trolltech, and while never having actually coded with Qt, is understandably biased in that direction. He inquires whether commercial support is available for Gtk+/Gtkmm. It it?


Thanks!

Ed Leaver



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]