[jlbec evilplan org: Enumeration patch]



Everyone,
	Ok, I put together a patch to provide opaque enumerations for
glib.  This is intended to look like java.util.Enumeration, because I've
found that functionality excellent.  I sent it to Tim, who recommends
that I get discussion here.
	Why this, when I can just return a GList* from a function?  I
find that returning lists is non-trivially obvious wrt memory handling.
We've already had a long discussion on whether to return values by
reference (don't free/change) or by copy (store in temp_var and free()
yourself).  This doesn't solve that problem.  But what of a _list_ of
values?
	Say you have a structure

struct Foo {
    ...
    GList *children;
    ...
};

	and a function

foo_get_children(struct Foo *foo);

what does this function do?  It can do any of these:

return(foo->children)                /* internal GList*, caller better not
                                        modify _anything_ */

return(foo->children)                /* internal GList*, caller better
                                        not modify the GList, but
                                        express permission is granted
                                        to modify list->data elements */

return(g_list_copy(foo->children))   /* the list->data elements are *still*
                                        internal.  Here the caller *must*
                                        free() the returned list, but
                                        must explicitly copy any ->data
                                        elements they wish to modify,
                                        and they had better not modify
                                        the originals */

return(foo_deep_copy(foo->children)) /* everything is a copy, and the
                                        caller *must* know to free()
                                        _everything_.  What a pain! */

	Of course, documentation can specify on what terms the returned
GList* must be handled.  But most of the GTK+/GNOME documentation that
I've seen doesn't.  Instead, you just have to read the source and see.
And heaven forbid the library change it on you (of course).
	With an Enumeration, the actual mechanism of how the items are
listed is hidden behind an opaque API.  There might be an internal list,
a copy of the list, or even a dynamicly generated next element.  It
doesn't matter.  The caller just knows how to get it.  The opaque API
generating the enumeration handles the internals.

from the caller's perspective: 

GEnumeration *foo_list = foo_enumerate_children(foo);
while (g_enumeration_has_more(foo_list))
{
    FooChild *child = (FooChild *)g_enumeration_get_next(foo_list);
    do_something(child);
}
g_enumeration_free(foo_list);


	Now, while there isn't much more/less code than a GList*, the
caller has no knowledge of how the Foo object is handling the
enumeration, and has no _need_ to.  Any every access to an enumerated
entity in the Foo object's API looks the same, no matter how the
internal of the Foo object is implementing each.  So when the caller
just wants a list of things, it is easy, consistent, and there is no
question of the enumeration's memory characterisics.
	I'm not advocating replacement of all GList* return values.  In
an internal API (within a module, say) there is no reason to hide the
characteristics, because it is a self-contained unit.  But when a
library is providing an opaque API, I think this is a win.  So when
evaluating it, please don't say "Ahh, we have GList", instead ask "Are
there cases where this is clearer than GList?"
	The attached patch contains the GEnumeration code, a quick
GEnumeration addition to GHashTable as an example, a go at RDP sgml,
and all the proper testglib examples, including a dynamically generated
enumeration.
	Questions, comments, improvements to gtk-devel.  Flames and
studlyCaps to me privately.

Joel


-- 

"But all my words come back to me
 In shades of mediocrity.
 Like emptiness in harmony
 I need someone to comfort me."

			http://www.jlbec.org/
			jlbec evilplan org
--- Begin Message ---
Tim,
	Hot on the heels of my recent query, I've cooked up a quick
patch to add opaque Enumerations to glib, ala java.util.Enumeration.
Since I personally find the "do I free this returned GList?" confusion a
headache, I like this interface better.  It also allows the flexibitiy
of dynamically iterated enumerations (see the patches to testglib).
	Included is the code to build in HEAD, testglib tests, and a
first shot at RDP SGML.  Note that diff(1) put the SGML at the front
of the diff, so some scrolling is required.
	For yuks I also added a g_hash_table_enumerate_keys() quickie to
example the idea.
	Oh, and while I hope I did the coding style ok, I'd really
prefer a publically available .indent.pro.
	Comments, hints, allegations, flames.  If you think it a bad
idea, fine.  If not, let me know and I'll hit gtk-devel with it.

Joel


-- 

Life's Little Instruction Book #347

	"Never waste the oppourtunity to tell someone you love them."

			http://www.jlbec.org/
			jlbec evilplan org

Attachment: genumeration.diff.gz
Description: Binary data


--- End Message ---


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