Re: A couple of suggestions




>>A GAny type, which would be an union of all the primitive types in glib.
>>This could be used as a "general" argument, where gpointer is used
>>currently. (Such as in gtk callbacks, hashes etc..) The current practice,
>>casting ints to gpointers and back, for instance, is not guaranteed to have
>>any consistent behavior. Though it appears to work on most systems, it is
>>still unreliable and ugly. Casting is a _conversion_ operation. Using an
>>union is cleaner.
>
>Although the C standard leaves casting between pointers and integers
>undefined (except for saying that it is allowed), I'll stick to
>my guns and say that storing small integers by casting into pointers
>is safe on any platform that GTK is likely to run on.

This may well be possible, but it is still conceptually ugly.

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

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

>Or anything like that. If casting int <-> pointer offends you, don't
>use it: use pointers to the real objects instead. If the use of such
>casting in GTK bothers you - (it does me, but not enough to do
>anything about it) - then patches to fix it would be accepted.
>
>In might be nice to have macros that did the casting in a 
>way that didn't produce warnings. For instance, on 32 bit
>machines, and some 64 bit machines, the following
>
>#define GUINT32_TO_POINTER(x) ((gpointer)(long)(x))
>#define GPOINTER_TO_GUINT32(x) ((guint32)(long)(x))
>
>(these need to be different on machines with 64 bit longs
>and 32 bit pointers - I.e. SGI -n64)
>
>But I think we should be very hesitant to force changes
>all over GTK to accomodate the very rare cases where you
>want to store ints as callback arguments or in GLists.

Or in GHashTables, or in your own code...

>Unfortunately, one doesn't always have lvalues, and actually,
>your version looks somewhat _more_ dangerous to me. 

All right, granted. That was just a spontaneous thought.

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

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

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

Well, speed for starters. Otherwise, why doesn't everyone use alists
instead of hashes?

Secondly, the compare func makes it a bit more sensible. Like, a basic 
dictionary compare func would be:

gboolean comparefunc (GAny a, GAny b){
	GHashNode* x=a.p;
	GHashNode* y=b.p;
	return x->key == y->key;
}

Or something like that. The point is that this way the user can choose 
any way of keying the objects that is best.

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

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

>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.:)

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.

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.

That's about all for now..


Lauri Alanko
la@iki.fi



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