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

Reply via email to