GObject in GC implementation Plan

Daniel Espinosa esodan at gmail.com
Thu Mar 22 00:48:12 EDT 2007

2007/3/21, Josh Sled <jsled at asynchronous.org>:
> On Wed, 2007-03-21 at 00:42 -0600, Daniel Espinosa wrote:
> > Get GObject as the base of GC's objects. With the following advantages:
> >       - Get ref counting
> >       - Get signals events
> Using GObject is a prerequisite of either of the separate "ref counting"
> and "signals" projects, but aren't advantages that directly follow from
> using GObject.
> > ******OPTION 1: PORT QofEntity TO USE GObject AS BASE CLASS
> > *******OPTION 2: PORT QofInstance TO USE GObject AS BASE CLASS
> I read Option1-Step1 and Option2-Step2 as basically the same thing:
> "everything will just happen".  They're not really "steps"; I don't take
> away from them a clear plan of action.
> Option 3 is broken out better, but it doesn't seem as suitable as Option
> 2.  In particular, I don't see why one would change the type hierarchy
> twice (in Steps 2 and 5).  As well, it seems pretty agreeable all around
> to merge QofInstance and QofEntity from the start.  At least for the
> purposes of discussion, let's call this merged type "GncObject".
> I'd agree with Chris; Option 2 is probably the better path.  Or maybe a
> modified version of Option 3, where:
> - QofInstance and QofEntity are combined
> - The GnuCash types then subclass GncObject.
>   - QofInstance fields are just inherited (not included by pointer)
> - Minimal changes to use G[nc]Object.  I'm thinking, here, for example:
>     // ..._get_type() { ...g_type_static_register()... }
>     // ...
>     Account*
>     xaccAccountMalloc()
>     {
>         Account *a = g_object_new(GNC_ACCOUNT_TYPE, NULL);
>         // ...existing Account setup...
>         return a;
>     }
>   ...and, well, that's about all.  No signal or property registration,
>   in particular.
Any GObject I'll setup will use properties or signal registration,
unless they *must* need it.

> [from Option 3...]
> > Step 4:
> > Setup QofInstance to be a GObject and be sure to have a correct
> > construction/destruction process, this will ensure a correct
> > refcounting.
> I'd suggest — in any plan — deferring handling "correct"
> construction/destruction and ref counting to a later phase of work.

The realy point here is to ensure the construction/destruction of
QofInstance and its base class GObject, when
g_object_new/g_object_unref is called, I need to think how to call
g_object_new and ensure the GObject's mechanisms work fine for the
GC's and QOF construction/destruction process with out modify a lot of
code at the same time.

> In particular, here's what I see happening.  Once you start to modify
> (say) xaccFreeTransaction() to be "correct", it will want to look like:
>     xaccFreeTransaction(Transaction *t)
>     {
>         g_object_unref(t);
>     }
> ...then it only makes sense for its dispose handler to look like...
>     {
>         GList *splits = ...;
>         g_list_foreach(splits, g_object_unref, ...);
>     }
> ...which means you have to have "correct" both ref and unref behavior
> for the Splits, which means, they need a "correct" dispose handler
> like...
>     {
>         g_object_unref(split->account);
>     }
> ...which means ... for it to be "correct", everything needs to happen
> all at once.  It quickly gets to a point where a bunch of changes need
> to be made to every file at the same time, increasing the chance that
> the whole set isn't clear or clearly acceptable.
> I don't think that that necessarily needs to be the case. Better
> construction/destruction and ref-counting can be phased in.  In
> particular, I think there are related groups of objects (Maybe {Account,
> Split, Transaction}.  {GncCommodity, GncPrice, GncNumeric} ... &c.) that
> could ref-count with each other, probably while intentionally ignoring
> other groups of objects.  Along the way it wouldn't be fully "correct"
> nor complete, but it'd be much more tractable.

I realy want to make as less changes as possible, thats why I'm
sharing this plan.

The Option 3 is for get GObject in the early steps and when GncObject
was finished change (this process is realy easy to do) change the base
class to GncObject.

If we gain GC's objects to be GObject some other could use, for
example, a signal "modified" in a Transaction to create two
transactions to separate the "sale" and the "tax" of the transaction
when needed, a feature some one (including me) wants in GC; and get
advantages even if it doesn't use GncObject as its base class yet.

Please reconsider again, and think about the possibilities.

If Option 2 is taken, take in a count that any GC object that use
GncObject as its base class *needs* to be setup to be a GObject in
order to ensure a good work of it, if I could create a GncObject alone
(using g_object_new (GNC_TYPE_OBJECT, NULL) ) I can take the objects
by group but the GncObject member *must* be a pointer, if not I need
to setup all of then at the same time and the modifications will be a
lot and may be dificult to follow; as Josh Sled said "increasing the
chance that the whole set isn't clear or clearly acceptable".

Trabajar, la mejor arma para tu superación
"de grano en grano, se hace la arena" (R) (entrámite, pero para los
cuates: LIBRE)

More information about the gnucash-devel mailing list