Monday, July 23, 2012

Gmmproc progress

I have recently pushed over 30 commits to glibmm gmmproc-refactor branch. This concludes gmmproc's first "milestone" - to generate glibmm sources, build a library, build the tests and examples and finally succesfully run the tests. But by saying "glibmm" I mean only GLib wrappers - Gio wrappers are next on the list.

First milestone?


Yeah, right, as if there are any. That "first milestone" may look modest, but I actually think that it is like 75% of work done. GIR parsing, type conversions system, parsing templates, replacing m4 code with perl and then tying them and squeezing them with foot into some semblance of a program - all of those had to be written to have something working.

I haven't yet made any benchmarks of gmmproc rewrite, but right now it seems to be faster than the old one. Still old one can be faster if we run parallel build (make -jX) - there is one of main differences between currently used gmmproc and its rewrite. The former processes and writes one set of files (like from widget.hg and widget.ccg to widget.h, widget.cc and widget_p.h) on every run, while the former processes all files in single run. That forces me to actually do parallel processing inside my program instead of reusing make's powers. Fortunately, I tried to write most of my code in a way that parallelizing it would be easy if done in OpenMP style.

Talking about speed - there is one area I would like to speed up in general - GIR parsing. It looks like the slowest part of whole gmmproc, but I didn't yet tried to profile it. I was thinking about using typelib instead, but from what I heard, there is no detailed C type information there (the "c:type" attributes from gir). This is still to be confirmed as it is not on top of my nowhere written list. Otherwise, using typelib would be, I imagine, faster. Provided that C-to-perl interface to GIRepository is written first - whooo, yak shaving!

Some plans


Still, I feel no hurry in rewriting as I rather see it to be used in next version of glibmm/gtkmm (I assume that those will be glibmm-4 and gtkmm-4). Thus I am not writing a strict drop-in replacement - I already have made (or I plan to make) some changes in generated API (like exception-to-GError conversion in vfuncs wrappers) and in template API (I would like to get rid of _CUSTOM_CTOR_CAST and similar in favour of _CLASS_FOO options).

There is still much to be done beside threading the application:
1. generating Doxygen documentation based on docs in GIR,
2. code documentation,
3. gmmproc macros documentation,
4. tests (there are some, but still not enough),
5. reports about unwrapped classes and functions,
6. and probably more.

I am happy to get this far and to actually finally see something more or less working.

Small disclaimer


The code is ugly mess. It needs to be reorganized, reshuffled in several places. WrapParser class is huge, even with moving some functions into shared modules. 'use' clauses have to be reviewed. 'constant' module for section traits was probably a crappy idea. Sometimes class/function naming is bogus (identity conversions, imbued types, tokens store?). Code style is very inconsistent (I started reading Modern Perl somewhere in the middle).
Oh, and commit messages are useless - they are probably going to be squashed at some point into single enormous commit for merging into master (and I am going to get only +1 commit of contribution on glibmm on Ohloh, damn!).

Wednesday, June 6, 2012

SyncEvolution

These are bit dated news (well, only two weeks or so), but the fork/exec rewrite of DBus server was merged into master branch. The main aim of rewrite was to allow several concurrent synchronisations to be done (provided that the sync sessions don't conflict with each other). It wasn't possible before, because libsynthesis (the main library used for sync) does not have asynchronous API. There were two solutions: either use threads or spawn children processes doing syncs. The latter solution was chosen, because Patrick Ohly did not want threads to avoid complications with some possibly thread-unaware libraries. (Of course waiting for libsynthesis to get asynchronous API wasn't an option.)

The rewrite involved splitting the code in one file of syncevo-dbus-server into several files and then detangling all tightly coupled classes - I guess that the result is quite nice compared to what it used to be. In the meantime new C++ DBus layer based on GLib GDBus was added. Most of this work was done by Chris Kühl - I was mostly helping in fixing issues in new DBus layer and then working full-time on it and the code using it. As a final step I ported command line test from C++ to Python, so our work could be proved to work.

This was a really long task, very often I felt that I was losing grasp on the code I was working on and probably sometimes I had actually lost it. Now I feel happy to see it finally merged into master.

Tuesday, February 14, 2012

gmmproc refactor

What?

gmmproc is a script used by most of C++ bindings of GNOME stack (called also mm-modules). It is responsible for generating actual C++ headers and sources from templates. That is so, because wrappers for most C API are straightforward, so writing them manually would be just a tedious job. Instead of that we just provide C API information, specify what names should C++ wrappers have and how to get a C instance from C++ one and vice versa and all happens automagically. Even documentation from C sources is taken and translated to use C++ names.

1 or 2 years or so ago.

Some time ago I was thinking about refactoring gmmproc. I was not the only one, because there were several notions that a rewrite could be welcome. I even made a topic on gtkmm-list about it and created a page at live.gnome.org. Main points would be using GIR as a source of API information and documentation, and getting rid of m4 as it makes it hard to add new features. I had some grand plans like creating two backends - one for defs (old API information) and GIR (new API information), creating conversion files on-the-fly, some configuration file a'la Doxygen, blah blah blah. Eventually I started some coding in Python, drawed some diagrams in my sketchbook, switched to C++ and then Perl and suddenly development slowed to molasses, because I already got bored. Apparently writing API structures is really uninteresting. Especially when it goes really slow and no end of it is in sight.

Now and ongoing.

I got back to it recently with a firm decision that I will finish it. I got over API structures by generating them basing on GIR definition I had to deduce from some python code in gobject-introspection (yeah, I wrote my own definition, because there seems to be none of such thing upstream - documentation is pitifully out of date). Also, most of the parser is also generated, but most important things are hand-written. Then I switched to refactoring a WrapParser and Output, which are 10 years old Perl code, added some needed infrastructure replacing m4, converted _CLASS_GOBJECT from m4/defs to Perl/GIR, added a scanner finding C <-> C++ type equivalents. My first aim is to have any compilable code being generated. For that still much work left to be done - mostly understanding and translating rest of m4 code to Perl (booooring!) and writing C <-> C++ conversion code (the one saying how to get `GtkWidget*' from `const Gtk::Widget&'; slightly less boring, but still).

Future plans are... no no no, no future plans for now. I did that before and got baffled by amount of work that needs to be done. Slowly all needed features will be introduced.

All of the code sits in gmmproc-refactor branch of glibmm. Additions here are mostly a bunch of kilo-line commits happenning once for two-three weeks, because I work on it offline at home in my free time. In the end all of it is going to be probably squashed into single commit before merging it to master.

I am usually pushing changes to repository when my single patch grows to at least 500kb. Now it has only 200 kb, so you have to wait. :)