This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: Delegates (or something)


On Mon, Apr 20, 2009 at 10:30:50AM -0400, Anthony Green wrote:
> William Ahern wrote:
> >I'm curious of people's thoughts on this. Especially if somebody can point
> >out a bug, including the "you just got lucky that it works" kind.
> >  
> This is pretty clever use of gcc extensions!   However (and, forgive me, 
> as I haven't had my morning coffee yet), I'm not sure I understand where 
> this would be useful.  Could you perhaps give an example of why you'd 
> want to use this?

I use libevent quite a lot, and I got tired of writing stub functions to
marshal parameters and forward event callbacks.

Basically, the utility is in providing a generic callback interface in C.
But the concept is very similar to generators and closures in other
languages, and those need no defending ;) Yes, you can do it "by hand", but
sometimes you don't want to. It can be in the nature of the abstraction to
be more expressive to the reader.

> Libffi is mostly used for bridging between compiled and interpreted code. 
> In this case you're calling compiled code from compiled code through
> libffi.  If everything is known at compile time, why use libffi?  I am
> preparing my best "d'oh!" for when you clue me in.  :-)

Well, I'll admit it's mostly aethestic. But so far, it has definitely
improved the clarity of my code.

For instance, in my current proxy the daemon is functionally composed of two
processes, one of which forks the latter. If one exits, so should the other.
So how do I express that? Assuming I have a socketpair between the two, I
could write simply:

	event_delegate(&evdel, fd, EV_READ, 0, &raise, SIGTERM);

Now, it might not have been very time consuming to write a 3-line libevent
callback, for a total of 4 lines (plus any code commentary and whitespace).
But I definitely prefer this. I despise code clutter, and that single line
(to me) needs no commenting whatsoever; it speaks for itself. That, to me,
is very close to perfect code (in the context of my particular app).

Benchmarking, invoke() is at least 10x slower than a regular [non-inlined]
function call. But optimization comes later. I'm sure for some high-use
callbacks I'll stub things out, but only after primary development is
finished, and I'm not constantly asking myself, "what was I trying to do
here?" ;)

FYI, I have a new version which gets rid of the multi-megabyte pre-processor
token generation--by "storing" the object type in a tmp and then calling
typeof() on the tmp, and by using a recursive'ish macro expansion technique
rather than 7 fixed __builtin_constant_expr() statements--and which also
supports return values from invoke().

The only other issue remaining (for me), is passing parameters for which the
value is only known at forwarding time, and expressing which parameter that
is (for instance, w/ libevent, the parameter which says which event
triggered the callback). I have some ideas. But right now I'm just enjoying
this little interface as-is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]