GObject in GC implementation Plan

Daniel Espinosa esodan at gmail.com
Tue Apr 3 01:04:23 EDT 2007


2007/3/30, Derek Atkins <warlord at mit.edu>:
> Hi,
>
> Sorry for not responding to this sooner.. Apparently it fell into
> my Spam folder and I didn't notice it until today.   Mea Culpa.
>
> More inline...
>
> "Daniel Espinosa" <esodan at gmail.com> writes:
>
> > GOBJECT IN GC IMPLEMENTATION PLAN:
> >
> > OBJECTIVE
> >
> > Get GObject as the base of GC's objects. With the following advantages:
> >       - Get ref counting
> >       - Get signals events
>
> I would say that these are three objectives, not one, and that these
> three objectives do not have to happen at once.  In other words I think
> we can have a multi-step process:
>
>   1) Get GObject as the base of GC's objects.  Get this to work by
>      itself using the existing (non-refcounted) methods.  Obviously
>      this is going to require changing EVERY object in the tree at
>      once, so it's a major bit of work, but let's make this as SMALL
>      as possible.  ONLY use GObjects for create/destroy.  Don't do
>      refcounting.  Don't do signals.  Don't change the QOF String
>      types to GTypes in the APIs.  Keep all that, just change the
>      objects to use GObject.  Once we get that working then we can
>      merge into trunk!
>
>   2) Implement GObject refcounting.  I think this might be able to go
>      on an object by object basis, but I don't know for sure.  But as
>      we get working state, perhaps merge into trunk.

When you have a GObject derived class, even if doesn't follow the
automatic GObject's construction/destruction feature, you have
refcounting. Actually we can leave, and we must in order to keep the
changes SMALL, the QOF construction/destruction just keep in mind that
when create an object call g_object_new and when destroy call
g_object_unref.

>
>   3) Use gobject signaling.  Again, I think these can be done object by
>      object.
>
> But the point here is that these are SEPARATE tasks and should be done
> in separate steps.
>
> > STATE OF THE ART
> >
> [snip]
> >
> > STEPS TO GET GOBJECT
> >
> > In order to get GObject as the base class for the GC's objects and get
> > its functionalities, we can go though the following options:
> >
> >
> >
> >
> > ******OPTION 1: PORT QofEntity TO USE GObject AS BASE CLASS
> >
> > Step 1:
> > Setup QofEntity, QofInstance and ALL GC's objects to be GObjects in
> > order to have a correct construction/destruction process, this will
> > ensure a correct refcounting.
> >
> > **ADVANTAGES
> > Make all in one step and get GObject from the base QOF system.
> >
> > **DISADVANTAGES
> > Too many changes to be mergable in Trunk.
>
> I'm not sure I agree, but let's just say that I agree for now..
>
>
>
> > *******OPTION 2: PORT QofInstance TO USE GObject AS BASE CLASS
> >
> > Step 1:
> > Merge QofInstance and QofEntity. This allow to get a single class used
> > as the base for the GC's objects.
> >
> > Step 2:
> > Setup QofInstance and ALL GC's objects to be GObjects and be sure to
> > have a correct construction/destruction process, this will ensure a
> > correct refcounting.
> >
> > **ADVANTAGES
> > Make all in few steps and get GObject from the base QOF system.
> > Simplify the object class hierarchy.
> >
> > **DISADVANTAGES
> > Too many changes to be mergable in Trunk.
>
>
> I'm not sure I agree here.   I think that if you break it down
> into truly the smallest pieces then it WOULD be mergible.  See
> what I wrote above.
>
> For example, to GObjectize the GnuCash Account object in this way
> would require only minor changes xaccInitAccount(),
> xaccMallocAccount(), and xaccFreeAccount().  In particular:
>
> xaccInitAccount():
>   Remove qof_instance_init() because it's no longer needed.

if you want  SMALL changes you need it for the early steps.

>
> xaccMallocAccount():
>   change g_new0() to g_object_new() to create the "GncAccount" object
>

Ok and keep all the init process of this object.

> xaccFreeAccount():
>   remove qof_instance_release() because it's no longer needed
>   change g_free() to g_object_destroy() to destroy the gobject.
>
You need to remove g_free and the end of the object destruction, and
keep qof_instance_release to call there g_object_unref.

> That's it (well, except for the GncAccount GType hooks).  I think this
> is fairly straightforward and could be done with minimal impact.  I
> don't even think you need to change anything in the Account headers or
> account structure.  Once you change QofInstance to be based on GObject
> everything else is just inherited so only these minimal changes are
> required to "get it working".

Realy change GncAccount as a GObject isn't dificult, is just work, but
the real problem is QOF it selft.

>
> Now, you might argue that this really isn't using GObject properly,
> and I'd agree.  See above about doing it in multiple steps.  Doing it
> THIS way we get a working system sooner, and then we can migrate to
> each gobject feature over time, one feature at a time.  It means we
> have a small set of changes that we COULD merge into trunk and would
> reduce the risk of failure.
>
I can see that we can implement GObject as the base class and add
signals, but that's all, this features are "easy" just need code; all
other features in QOF like the type system, QofParamenters, Class
system and QofQuery will be realy dificult and may be imposible to
changes with out a great CHANGE in the base code, they will need a
COMPLETLY re-write, becouse they're far diferent from GObject, not
exactly, equivalent feature.

A great problem is the actual code; it uses its parent objects
directly, don't use functions, and they don't use the actual API even
when it is avairable, this make VERY SENSITIVE the code in any change
made in the access methods.

>
>
> > *******OPTION 3: PORT GC's OBJECT TO USE GObject AS BASE CLASS
> >
> > Step 1: (this step can be done Object by Object, don't need to work in
> > all objects at the same time)
> > Make the QofInstance member as a Pointer, and allow to create a
> > pointer to a QofInstance when the object is created using
> > g_object_new. This means:
> >
> >       - Add a new function in QofInstance to allow create an instance,
> > setup it and return a pointer to a QofInstance
> >       - No modification in the current QofInstance implementation
> >       - Will need to change all references (JUST in the currently changing
> > object) from 'object->inst.[someQofInstanceMember]' to
> > 'object->inst->[someQofInstanceMember]'
> >       - Needs to change the definition of QOF_INSTANCE macro to call a
> > functions witch returns the QofInstance pointer member of the GC's
> > object
>
> I suppose we could do this, but we'd need a forward pointer from
> the QofInstance back to the main object, so you can convert from a
> QofInstance TO an e.g. Account* or Transaction* or Split*.  We need
> to be able to convert back and forth...  And there are probably LOTS
> of places where we get a QofIstance and ASSUME that we can C-Cast it
> back to our primary type.   E.g., I'm sure there's lots of code that
> says:
>
>    gint foo(QofInstance* inst)
>    {
>       ...
>       Account* acc = (Account*) inst;
>       ...
>    }
>
> ALL of this code would be broken by this approach.
>

Un less for the Account object that's not a realy great problem, it
hasn't that cast, the code use direct access to the instance and use
QOF_INSTANCE when convert, I have done this changes for this object
and it compiles know with out warnings.

The changes in Account doesn't affect the other objects, becouse the
way it works with QOF is unchanged. I have added a function to create
a QofIntance and return a pointer and changed all the code for this
changes too, no too work represent it; I think we can TEST if it works
well in GC before continue to the next object, of course if this could
be a real alternative.

> > Step 2:
> > Setup the currently working object to be a GObject. This means:
> >       - The base class will be GObject not QofInstance
> >       - Other objects, not currently changing, will use the same
> > QofInstance base class and its current construction/destruction
> > process
> >
> > Step 3:
> > Merge QofInstance and QofEntity. This allow to get a single base class.
> >
> > Step 4:
> > Setup QofInstance to be a GObject and be sure to have a correct
> > construction/destruction process, this will ensure a correct
> > refcounting.
> >
> > Step 5:
> > Now we can change the base class from GObject to QofInstance in all
> > GC's objects.
> >
> > **ADVANTAGES
> > Get GObject features directly in GC's objects quickly.
> > Allows to delay the required modifications in QOF to later steps.
> > Allows to modify QOF WITH OUT modify the GC's objects; even is
> > possible to work on QOF with out modify the GC's objects, but this
> > delay to get GObject in GC
> > Once the process in QOF to GObject is finished we can change the base
> > class in GC's objects again to QofInstance
> > Simplify the object class hierarchy.
> >
> > **DISADVANTAGES
> > Require to change the base class of the GC's objects from QofInstance
> > to GObject.
> > Needs to change the code from direct access to the members in
> > QofInstance from '.' to '->'.
>
> I think these are some major disadvantanges.  I still like options
> #1 or #2 (tending towards #2) with the caveats that we make minimal
> changes like I point out above.  Enough to get it to work even
> though we don't use the full extent of gobject functionality right
> from the beginning.
>

I can see the point will be to work on QOF, but please see at the
code, it will be realy imposible to change to use GObject features in
the future becouse it is far to be compatible with GObject in many
ways.

We can continue in try to use GObject as the base class, taken any of
the steps above, but keep in mind that will be limited and maybe never
be completly changed to GObject.


I'm preparing the document where I'll describe a new way to get
advantages from GObject to get access to other external applications
to the GC's data in the actual XML format or databases, by creating a
GObject based library  .


-- 
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