On Wed, Aug 13, 2008 at 11:00:13PM +0100, Dirk-Willem van Gulik wrote: > Having a daemon working absolutely fine with libevents - no problems > with the basic use case. > > However for a somewhat more complex handler where I need to wait for > another event to happen _within_ an event handler - as that determines > how I return from that hanlder. I.e. the function I am calling returns > immediately - and I need to wait up to X seconds for another handler > to be called:
To be called or to return? One of the easiest pitfalls to find oneself in when writing code which heavily depends on callbacks is that at some point you have to decide when the incomprehensible tangle of callbacks should be tamed with a state machine. This sounds like one of those times. > event_init(); > register xxx handler on socket 1 with REST interface > register zzz handler on socket 2 which gets OK/NOK callbacks from > a backend system. > event_dispatch(). > done. > > xxx_handler() { > call a function which > ultimately causes a callback > > wait for zzz_handler() to be called > with some timeout. > > if (success) > ... buf write OK > if (timeout) > ... buff write timeout > else > ... buff write errrr %x > } > > zzz_hander() { > parse results > -> know success or fail > } > > How is this best done ? Can I safely call event_loop (once) within an > event ? Yes and no. If you call event_loop, you have no idea which handlers will get called. If one of your callbacks detects EOF on a socket (or all sockets), and frees the resources, when event_loop returns, you may find yourself accessing invalid memory. A good rule of thumb is to never, ever, ever call a possibly recursive function (like event_loop) from a handler unless your next statement is `return', and `return' all the way down your code stack. (When you must, you either need to closely audit your code to ensure some related handler can't invalidate your resources, or implement some simple synchronization or signaling mechanism.) However, calling event_loop is safe from libevent's standpoint. A few quicker answers: (1) just serialize xxx and zzz handlers, if possible. libevent lets you run many tasks concurrently, but sometimes its best to serialize/pipeline related tasks (at the expense of likely unnoticeable latency). For instance, a simple protocol proxy has two streams (east-west and west-east). Serialize I/O within each stream (read from one socket, then write to its counter-part; buffering data or messages is usually not worth the complexity). (2) keep a third timer event outstanding, and some logic in the timeout handler to detect the case that xxx finished but zzz is [relatively] late. Similarly, if I understand your problem, create a really simple message/job queue which postpones the buf write OK, etc. Either zzz or the timer triggers execution of the job. Really, the example psuedo-code you've written betrays that you're wanting to have your cake and eat it to--no threads, but ability to leverage the call stack for storing state. Lua and libevent make a good combination ;) _______________________________________________ Libevent-users mailing list Libevent-users@monkey.org http://monkeymail.org/mailman/listinfo/libevent-users