Re: instance-private-data issue



On Wed, 2003-08-06 at 08:07, Tim Janik wrote:
> On 2 Aug 2003, Owen Taylor wrote:
> 
> > So, say you have classes MyA, MyB, MyB deriving from MyA. And
> > you have an instance init function for My:
> >
> > static void
> > my_a_init (MyA *a)
> > {
> >   MyAPrivate *priv =  G_TYPE_INSTANCE_GET_PRIVATE (a,
> >                                                    MY_TYPE_A,
> >                                                    MyA);
> >
> >   /* use priv */
> >
> > }
> >
> > All fine, right? Well, actually no. The problem is that
> > g_type_instance_get_private() looks at:
> >
> >  a->g_class->g_type
> >
> > to find out the type of a, and thus the offset to the private
> > data. Well, the way GObject works, a->g_class->g_type is
> > always MY_TYPE_A in my_a_instance_init(), even when we are
> > really initializing a MY_TYPE_B.
> 
> have you written a glib-only test case for this already?

Just checked in a change to testgobject to make it test this.

> > For those not in the know, the reason it works like this is that
> > the idea is to avoid ever accessing the virtual functions for
> > MyB until the instance_init for MyB is called. [*]
> >
> > So, how do we fix the problem? Two ideas I can come up with:
> >
> >  - increase GTypeInstance from 4 bytes to 8 bytes (on
> >    32 bits), caching the real type *before* the public g_class field.
> 
> i have to side with Mathieu here. i think this is an exceptionally
> good example for a bad trade-off. not only is private-data a
> recently introduced non-essential feature that hasn't correctly
> worked at all yet, the work-around is only required for a very short
> moment in an objects lifetime. yet, you're willing to sacrifice
> an extra pointer per every GObject used out there.

*) While the problem only occurs during object initialization,
   the cost of solving it occurs for every lookup of private
   data.

*) The fact that this is a "non-essential" feature really isn't
   relevant unless you are proposing removing it.

I'd love not to have to increase the size of GObject, but I
do think instance-private data is a valuable enough feature to
make it worth increasing the size of GObject, *if we can't
find a better way*.

> >  - Use thread-private data to keep track of a stack of
> >    currently-being-initialized objects with their real types, and
> >    have g_type_instance_get_private() check that.
> 
> while that's an interesting idea, and i'd definitely like to get
> into the problematics of using __thread with glib, i don't think
> we have to resort to this kind of hackery for solving the private-data
> issue.
> 
> we can simply store object pointers around init() in a lookup table
> and have g_type_instance_get_private() test that before resorting
> to its usual lookup. this will also work for szenarios where
> objects are passed around between threads during init().

I'd be perfectly willing to declare such passing around illegal...

> considering that most object trees don't create the majority of
> their children during init(), using a list as lookup table is
> probably good enough, though we could use a binary array if you
> expect more than 8 objects to show up there at a time.
> 
> for the common case (no object in init()), this means an additional
> !NULL lookup-table-pointer check for g_type_instance_get_private(),
> and in case of an object being in init(), the performance hit boils
> down to a read-lock plus the table lookup.

I don't see how you avoid the read lock on *every* lookup of instance
private data. Is that too slow? Without timing, I don't know.

> to give an idea, that's roughly as fast as some
>   g_type_is_a (OBJECT_TYPE, INTERFACE_TAPE);
> check, which every function does on entry.

Every public function. And 

 g_type_is_a (OBJECT_TYPE, ANOTHER_OBJECT_TYPE)

doesn't involve any locks.

Regards,
  				Owen





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