Re: instance-private-data issue



On Wed, 2003-08-06 at 12:28, Tim Janik wrote:

> > > 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.
> 
> well, if you indeed disallow passing objects around in init() functions,
> (or at least, disallow passing them around *without* a memory barrier in
> the remote thread (there's one in the local thread already with releasing
> the write-lock)), you're perfectly save with just:
> 
> if (lookup_table)
>   {
>     read-lock, patchup, etc...
>   }
> 
> since lookup_table can't be NULL if any instance is in init,
> and your thread figures it being non-NULL because it was either
> this thread that appended the current instance, or you got the
> updated non-NULL value due to the memory barrier.

Hmm, so your plan is essentially (suppressing storing the
classes for each object for simplicity):
 
 G_LOCK_DEFINE_STATIC (initializing_instances);
 GSList *initializing_instances = NULL;
 gboolean initializing_intances_empty = TRUE;
 
 static void
 add_initializing_instance (gpointer instance)
 {
   G_LOCK (initializing_instances);
   initializing_instances = g_slist_prepend (initializing_instances, instance);
   initializing_instances_empty = FALSE;
   G_UNLOCK (initializing_instances);
 }

 static void
 remove_initializing_instance (gpointer instance)
 {
   G_LOCK (initializing_instances);
   initializing_instances = g_slist_remove (initializing_instances, instance);
   initializing_instances_empty = initializing_instances == NULL;
   G_UNLOCK (initializing_instances);
 }

 static gboolean
 instance_is_initializing (gpointer instance)
 {
   gboolean found;
  
   if (!initializing_instances_empty)
     {
       G_LOCK (initializing_instances);
       found = g_slist_find (initializing_instances, instances) != NULL;
       G_UNLOCK (initializing_instances)'
     }
 }

(The initializing_instances_empty variable is actually superfluous, but 
would be needed if you were using an array.)

and the claim is that:
 
 * If there are any objects being initialized in this thread, then 
   this thread must see initializing_instances_empty as TRUE, since

   *) After add_initializing_instance, it will be seen as TRUE
      by this thread
   *) No thread can set it FALSE until after this thread calls
      remove_initializing_instance on the object

Yeah, I think that does work. It's not as quite as good as 
ultra-fast thread-private-data (__thread) because it's certainly 
possible to have an object that in its init does something slow
(reads in a big file fom disk, say), but probably good enough.

Regards,
					Owen

[ 
  Does it make sense to use a separate lock rather than the 
  global gtype reader-writer lock? I think it might, since 
  avoiding write-locks when not actually modifying the type 
  data is a good thing. 
]





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