Re: closure summary



On 5 Oct 2000, Havoc Pennington wrote:

> For me the clinching argument is that the simpler closure API is a
> subset of the more complex one; we can implement the complex API
> later, retaining backward compatibility with the simpler one, if the
> complex API turns out to be needed.

what exactly is that simplification you envision about?

initially, you wrote:

> This is implemented as follows: the closure stores an allocated array
> of notifiers, with a type tag on each notifier indicating whether it's
> an invalid notifier, destroy notifier, etc. The notifiers are sorted
> by type.

the notifiers don't have a type tag.

> If you need multiple instances of _any_ notifier type, then, you can
> get multiple instances of all of them "for free." There's no penalty
> for allowing multiple destroy notifiers, for example, if you need
> invalidity notifiers already.
> 
> However, if we can get away with only one instance of each notifier
> type, then we can lose the whole allocated array, making GClosure
> lighter-weight; and we can also simplify the system as a whole, since
> you only have to think about one chunk of user data with one destroy
> notifier, one invalid notifier, etc., and maybe more importantly each
> closure can only be connected to one signal.

this is simply not true, following your suggestion, we end up with:

struct _GClosureNotifier
{
  gpointer notify_func;
  gpointer notify_data;
};
struct _GClosure
{
  [...]
  GClosureNotifier destroy_notifier;
  GClosureNotifier invalidate_notifier;
  GClosureNotifier pre_marshal_notifier;
  GClosureNotifier post_marshal_notifier;
  [...]
};

which is obvisouly less leight weight than what i proposed:

struct _GClosure
{
  guint n_destroy_notifiers : 8;
  guint n_invalidate_notifiers : 8;
  guint n_pre_marshal_notifiers : 8;
  guint n_post_marshal_notifiers : 8;
  GClosureNotifier *notifiers; /* sorted! */
};

consider that most signal connections are _not_ while-alive connections,
most of them don't even need a destroy notifier, so you end up with
4*2*sizeof(pointer) wasted bytes with your approach, while mine will
cost us sizeof(int)+sizeof(pointer).
beyond that, using an array scales to any amount of notifiers that could
be required at any later point (ok, limited to the amount of bits i assign
to each ntoifier type, but that's an implementation detail), and even if
there's only going to be 1 of each for 99.999% of the cases, it doesn't
change things a bit.
this is not a question of 1 or many, but 0 or many, and the 0 i think
we don't need to argue about.


getting back to the "simplification" you mentioned earlier, i'm not sure
i understand what you want to simplify. from the previous thread i could
only extract one significant suggestion, that is, have:

void g_closure_set_dnotifier      (GClosure      *closure,
                                   GDestroyNotify destroy_func,
                                   gpointer       data);
void g_closure_unset_dnotifier    (GClosure      *closure);
/* intimidating */
void g_closure_set_inotifier      (GClosure      *closure,
                                   GDestroyNotify invalidate_func,
                                   gpointer       data);
void g_closure_unset_inotifier    (GClosure      *closure=;
void g_closure_set_marshal_guards (GClosure      *closure,
                                   GDestroyNotify pre_marshal_func,
                                   gpointer       pre_marshal_data,
                                   GDestroyNotify post_marshal_func,
                                   gpointer       post_marshal_data);

instead of:

void g_closure_add_dnotifier      (GClosure      *closure,
                                   GDestroyNotify destroy_func,
                                   gpointer       data);
void g_closure_remove_dnotifier   (GClosure      *closure,
                                   GDestroyNotify destroy_func,
                                   gpointer       data);
/* intimidating */
void g_closure_add_inotifier      (GClosure      *closure,
                                   GDestroyNotify invalidate_func,
                                   gpointer       data);
void g_closure_remove_inotifier   (GClosure      *closure,
                                   GDestroyNotify invalidate_func,
                                   gpointer       data);
void g_closure_add_marshal_guards (GClosure      *closure,
                                   GDestroyNotify pre_marshal_func,
                                   gpointer       pre_marshal_data,
                                   GDestroyNotify post_marshal_func,
                                   gpointer       post_marshal_data);

/* note that marshal guards are only required for while-alive connections,
 * they simply do ref/unref data objects. removing them is of arguable
 * benefit, but could be added later on.
 */

so far, i only see you "simplifying" things in that you got rid of the
function arguments i have in g_closure_remove_dnotifier() and
g_closure_remove_inotifier(). ok, this would also simplify the closure
implementation to some extend, but you and end-users don't have to
deal with that anyways.
in my eyes, your "simplification" introduces severe cons, that are,
1) limiting notifiers of each type to 1 for no aparent reason
2) significantly bloating closure size for the common case

in the above, i put "simplification" into quotes, because i don't
consider "adding and removing notifiers" significantly more complex
than "set and unset a single notifier".

i have to admit, i don't quite get your point, i thought from the
extensive talks we have had on this topic so far, you'd be aware
of the pros and cons of the aproaches already?

maybe i'm wrong in guessing that you just want to "simplify" the
notifier interface, but in the ongoing thread, this is what i sense
most argument about. you keep asking for justification of going with
more than one notifier for each type. that question never really
appeared to me, i'd rather challenge you:
why should we limit the number of notifiers to exactly 1 instead of many
("many" being: some implementation defined number that can be adapted
in the future as needs arise)?
you may have a point when you say that more than 1 is probably going to
be a rare case scenario (and i'd like to agree here as far as my ability
to predict the future allowes), however, i'm unable to recognize any
significant advantage for us in that point.

> 
> Havoc
> 

---
ciaoTJ





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