[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