[Cs22800] enlightenment style question
Benjamin Johnson
bsjohnso at midway.uchicago.edu
Sat Nov 16 19:06:22 CST 2002
I would agree with what Jon says. I think he's got some good stuff in
his message. As I stated in my message last night, I myself have to
come up with some solutions with various audiences in mind, so I guess
we're in similar boats.
See ya,
Ben
Jon Trowbridge wrote:
>Here are my 2 cents, along with some random observations about C API
>aesthetics.
>
>First and most important: if there is a convention used by the rest of
>the Enlightenment APIs, follow it. Sometimes being consistent is a
>greater virtue than being perfectly engineered.
>
>OK, now that I've gotten that disclaimer out of the way, here are a
>few thoughts on how to be perfectly engineered.
>
>In my experience, the first thing to think about when returning
>complex data objects[1] are life-cycle issues. Since C is one step
>above flint knives and bearskins, the poor user has to correctly
>manage any chunks of memory that you hand back to him. You want to
>make this task as easy as possible for the user --- hence the benefit
>of consistency.
>
>
>
>>hypothetical taskbar writer consists of a list of names, each with a
>>number and a pointer.
>>
>>
>
>You almost certainly want to assemble some kind of struct that
>contains the window information, and then hand the user a sequence of
>them. Don't hand back N lists (a name list, a number list, a pointer
>list, etc.), since that is a giant pain in the ass to iterate over.
>
>So you'd have something like:
>
>/* Typing 'struct' all of the time is very passe./
>typedef struct _TaskbarInfo {
> char *name;
> int *a_number;
> void *a_pointer; /* or whatever... */
>} TaskbarInfo;
>
>Hmm... but there is a string inside of the struct -- so whoever frees
>the structure has to make sure to also free the name. Please don't
>expect the user to do something like
>
> free (my_taskbar_info->name)
> free (my_taskbar);
>
>because that would lead to pain and memory leaks when someone adds
>another allocated field to the struct six months from now. So be
>polite and provide some sort of explicit destructor. IMO a destructor
>should always be provided in this kind of situation, even if it just
>ends up being a wrapper around a call to free: it is best to be
>defensive. This makes things pretty simple for the user; they just
>have to remember to call taskbar_info_free on any TaskbarInfo items
>they need to dispose of.
>
>Of course, there is another layer to the problem that I've ignored so
>far: you aren't returning just one of these guys, but you have a bunch
>of structs to deal with.
>
>I'd be surprised if E didn't have some library full of typical data
>structures like lists and hashes already coded up in C. I'd advise
>you not to use them, except maybe if:
> * They are smart and let you attach destructors for the data
> objects, so that freeing the list doesn't leak all of the objects
> in the list.
> * The Enlightenment convention is to return these kinds of objects.
> * There is absolutely no other way to do what you want to do in a
> clean way.
>
>In the GNOME, there is a library full of data structures called glib,
>but some people[2] considered it bad form to return them from any
>user-visible API --- the argument generally boil down to life-cycle
>questions or the lack of type safety, but in the end it is primarily a
>aesthetic/religious question[3].
>
>A simple alternative is to return a NULL-pointer-terminated array of
>pointers. These are easy to iterate over, though it is still good
>manners to provide a whole-array destructor.
>
>Though it is probably beyond the scope of what you'd want to do here,
>sometimes it is nice to abstract away all of the memory management
>issues, particularly if the semantics are complicated[4] or you think
>they may change. I really like using a functional programming-type
>idiom --- which works just fine in C. Your API would look something
>like this:
>
>typedef void (*TaskbarInfoFn) (const char *name,
> int a_number,
> void *a_pointer,
> void *closure);
>
>void get_taskbar_info (TaskbarInfoFn fn, void *closure);
>
>All memory-management questions are now gone: the get_taskbar_info
>function can manage all of the memory and clean up after itself as
>necessary.
>
>In case you are confused, here is an example of using this kind of
>API to write the window info to a file:
>
>static void
>write_info_callback (const char *name,
> int a_number,
> void *a_pointer,
> void *closure)
>{
> FILE *out = closure;
> fprintf (out, "%s (id=%d)\n", name, a_number);
>}
>
>void
>write_taskbar_info_to_stream (FILE *out)
>{
> get_taskbar_info (write_info_callback, out);
>}
>
>Warning: C programmers tend to freak out when you do this sort of
>thing. They are usually the same misguided people who don't like
>Lisp. But if you are stuck working in C, this idiom can be a
>life-saver.
>
>-JT
>
>
>[1] i.e., something other than an int, double, etc.
>
>[2] Here when I say "some people", I really mean "I", but I'm not
> the only person who feels this way. Honest.
>
>[3] However, that doesn't mean it isn't important. If your code is
> aesthetically pleasing, it is more likely to be well-thought-out
> and correct. And it will also be more readable, which vastly
> simplifies future maintenance.
>
>[4] Classic example: when you are caching data and you don't want to
> let the user decide when to free it. And you also don't feel like
> adding full-blown reference counting to your objects, which would
> be overkill in many cases.
>
>
>
>_______________________________________________
>CS22800 mailing list
>CS22800 at cs.uchicago.edu
>http://mailman.cs.uchicago.edu/mailman/listinfo/cs22800
>
>
>
>
--
Benjamin Johnson <bsjohnso at midway.uchicago.edu>
"I know not with what weapons World War III will be fought, but World War IV will be fought with sticks and stones." -- Albert Einstein
More information about the CS22800
mailing list