Hey Matt,
On Sun, 2008-11-09 at 12:52 -0500, Matthew Barnes wrote:
Over the weekend I hit a milestone with a science experiment I started
earlier in the year to turn Camel into a GObject-based library with
minimal API breakage. The short-term goal of this effort is to make it
easier to generate language and D-Bus bindings for Camel.
This is awesome news :-).
I now have running code which I've posted to a new evolution-data-server
branch called camel-gobject [1]. The branch contains a couple very
small patches (evolution.patch and evolution-exchange.patch) that must
be applied before building Evolution against the GObject-based Camel
library.
Evolution seems to be working just fine with my standard setup, but I
haven't tested all the built-in Camel providers and various third-party
extensions. If others want to chip in with the testing I'd be grateful.
Techie Details
--
My approach was basically to pull off the same stunt that was done to
GtkObject when GObject was introduced: turn the base CamelObject class
into a GObject subclass, and convert the CamelObject API into a set of
thin wrappers for equivalent operations in GObject. For example:
camel_object_ref() now calls g_object_ref()
camel_object_unref()now calls g_object_unref()
camel_type_register() now calls g_type_register_static()
...etc...
Obviously this breaks Camel's ABI. There's no way around that.
I think, you are correct. This needs to happen at some time.
The (intentional) API breakage is very minimal:
CamelType is now an alias for GType. It is no longer a pointer
to the class structure. That was supposed to be an implementation
detail anyway, but Camel (and Evo, and Evo-Exchange) exploits that
in a number of places. The class structure can be properly accessed
using camel_type_get_global_classfuncs(), which is now an alias for
g_type_class_peek().
The corollary to that is when to fetch the parent class structure.
Most classes define a static parent_class pointer for chaining up
in class methods. The parent_class pointer should be set in the
class initialization function, NOT before the type registration in
get_type(). Just like you would in normal GObject code. There
were LOTS of places in Camel were that needed fixing.
Camel interfaces are dead, but they were never really used anyway.
The other half of the problem was CamelObjectBag. It formerly shared a
mutex with CamelObject's reference counting, I think because CamelObject
ref's and unref's were non-atomic. GObject's reference counting is
atomic, so with that issue out of the way I gave each CamelObjectBag its
own mutex, cleaned up the code a bit, and split it off into a separate
source file (camel-object-bag.c). After an evening's worth of debugging
it seems to be working fine now.
Now What?
-
So with the interesting part now done, next comes the long and tedious
part: rewriting all the internal CamelObject boilerplate into GObject
boilerplate and making sure we're not using any newly deprecated API.
But that can be done gradually and with help from others.
In time I'd also like to explore taking greater advantage of GObject
signals and properties in Camel, and also deprecating CamelArgV and
CamelArgGetV.
Also the Camel Events to GObject signals right, or you meant the same?
I haven't discussed this with the other Evolution/Camel developers yet,
so there are currently no plans to include it in 2.26. That may change,
but for now it remains purely experimental.
2.26 might be a very tough one, with Kill-Bonobo also in, we may have
too many things to shape up.
Matthew Barnes
[1]
http://svn.gnome.org/viewvc/evolution-data-server/branches/camel-gobject/
___
Evolution-hackers mailing list
Evolution-hackers@gnome.org
http://mail.gnome.org/mailman/listinfo/evolution-hackers
___
Evolution-hackers mailing list
Evolution-hackers@gnome.org
http://mail.gnome.org/mailman/listinfo/evolution-hackers