Re: A couple of suggestions




Lauri Alanko <la@la.iki.fi> writes:

[...]

> >Using unions would not only break every GTK program, it would break
> >them in a really obnoxious manner - because in 99.9 % of all
> >cases what is really being used is pointers - and casting from
> >Foo * to void * and back is 100% legitimate. (In fact, even without
> >the casts - in ANSI C)
> 
> Firstly, what I said was propose the addition of a type to glib. I
> didn't demand any changes to gtk, I just said that could be one
> possible use for that. At the very least, it could be used in new code.

The trouble is that GTK uses the GLIB generic data structures
extensively, as do GTK programs such as the GIMP. So you can't
make the distinction between changing GLIB and changing GTK.
 
> >void
> >callback (GtkWidget *widget, GtkWidget *some_other_widget)
> >{
> >....
> >}
> >
> >gtk_signal_connect (GTK_OBJECT (button), "clicked",
> >callback, widget_x);
> >
> >Is _not_ better written as:
> >
> >void
> >callback (GtkWidget *widget, GAny any)
> >{
> >GtkWidget *widget = any.p;
> >}
> >
> >GAny any;
> >any.p = widget_x;
> >gtk_signal_connect (GTK_OBJECT (button), "clicked",
> >callback, any);
> 
> How is that worse? Demands a little more writing?

"Demands more writing" is definitely a problem when the code
is one of the most frequent things done in a GTK program.

It also is is less clear - not only are there more complexities
to deal with, but the important stuff is spread out.

[...]
 
> >>Then a real primitive hash would be useful, ie one which just stored objects
> >>in the hash without any mandated key/value pairing..
> >
> >Could you eloborate? key/value pairing seems like a pretty
> >essential part of a hash to me... (Without that 
> 
> Sometimes the key is a part of the value, or for other reasons the
> default pairing doesn't suit you. And sometimes you just want
> a set, from which you can check if a particular object is there.

How about just using the same pointer for the key and the value?
(It takes up a bit more memory than a new data type, but has
the advantage of already being implemented)
 
> >>And even the current hash should have a function to retrieve the key.
> >>Otherwise, what's the use of GCompareFunc, if you get into memory allocation
> >> problems if the key exists just in the hash and you can't free it..
> >
> >g_hash_foreach will get you all the keys in the structure. I
> >can't see any meaningful way of looking up a single key in
> >a hash table. 
> 
> Any way? You just return the key of the node instead of the value,
> when you have looked it up.
> 
> >The normal case would be that your keys are being stored elsewhere as
> >well so they aren't "owned" by the hash table. What would be the point
> >of having a key/value pair in a hash table if you couldn't look
> >up the value because your key was _only_ in the hash table?
> 
> That particular object would be only in the hash. That doesn't mean
> you couldn't get other objects to look up with which would compare as
> the same to the key object.
> 
> Like strings. Your key could be one string, and you would look
> something up from the table with another string that is stringwise
> equivalent but a different object. To be able to free the key when you 
> remove something from the table, you currently have to store all the
> key pointers somewhere when adding something to the table. This is silly.
> 
> Or for the case when you want to use ints the "right way", having
> pointers to ints. Then you need to allocate an int for each of your
> keys. Then how are you supposed to remove it? All that's needed is a
> way to get the actual key object in the hash.

OK, I see your point now. Currently, you'd have to store a pointer
to the key in your value, if you wanted to be able to remove
single entries from the hash table.

Something like:

gboolean    g_hash_table_lookup_entry (GHashTable     *hash_table,
                                       const gpointer  key,
                                       const gpointer *key_return,
                                       const gpointer *val_return);

would probably be useful in such circumstances.
 
> >I suppose in both this and the above you are asking for a data
> >structure which is an unordered collection - a GBag, so to speak.
> >Not being a data structure wizard, I'm not quite sure what
> >advantages that would have over just using GSList.

OK, that wasn't what you were asking for. You were simply asking
for hash tables where key == val.

 g_hash_table_insert (hash_table, key, key);

:-)

> >> In addition, converting to this will make it easier to some day change the
> >> type of the signal ids.
> >
> >I can't really see that ever being necessary. (More than 2**32
> >types of signals?)
> 
> You never know of the future. Isn't it conceivable that some day, for
> efficiency reasons, you don't get an id but a direct pointer to a
> signal structure?

I suppose it is conceivable.
 
> >> And finally, you can define signals without having to add a vtable entry to
> >> the class object. That is good. It'd be nice to have a way to have virtual
> >> methods without the overhead of signals, as well.
> >
> >That certainly is possible. Just put a function pointer in the
> >class structure and don't create a signal. (See the GtkRange
> >and GtkEditable classes for examples where this is done).
> 
> Yes, I know it is possible manually, but
> 
> GTK_FOO_CLASS(GTK_OBJECT(foo)->klass)->method(foo, arg)
> 
> is a bit ugly.. and it requires access to the object structure. What I 
> meant (I think) is a gtk_signal_emit that doesn't have the signal
> part.
> 
> Yes, I know it's slow. Just an idea.

My opinion is that in doing this you'd already have most of
the overhead of signals, so the advantages would be pretty
minimal. IMO, effort would better spent trying to speed up
real signals.
 
> >Well, GAny would break just about everything... Other than that,
> >what you are saying sounds reasonable.
> 
> Well, just the addition of one type to glib.h can't hurt anyone, at
> least. :)

No, but if it isn't used for Lists, Hashes, etc., I don't
really see the point.

> Oh, one more idea: a list that keeps track of both its
> ends. Basically:
> 
> struct _GDList{
> 	GList *head;
> 	GList *tail;
> };
> 
> And a similar one for GSLists. What's the use? Both access to head and 
> tail become O(1) operations, and you could use these without the
> bothersome list=g_list_foo(list) syntax.

I've occasionally wanted something like that. The only real downside
would be a fair amount of code duplication in GLIB. And you 
could in most cases simply wrap the g_list functions. 

(I don't see that much of a point in the GDSList, though - having the
tail isn't much use if you have to traverse the whole list to 
get the element before it)

> Oh, one more thing. Why not have 
> 
> typedef void (*GtkSignalFunc) ();
> 
> This better represents the fact that the arguments that GtkSignalFunc
> takes are unknown, and it also means you don't need to cast to that
> any more (which means you will get warnings if you try to pass a
> pointer to a function that has a return value). The same for all other 
> callback function types whose arguments can vary.

Sounds like a good suggestion to me. Though note that a large
fraction of GTK signals (all the _event ones, plus some others)
_do_ have return values. So the GTK_SIGNAL_FUNC() casts would
still be needed in many places.

It doesn't help things for people using C++, where the empty
parens are equivalent to (void) but it doesn't make things worse
for them either.

Regards,
                                        Owen




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