According to the libevent book:
Deferred callbacks
By default, a bufferevent callbacks are executed immediately when the corresponding condition happens. (This is true of evbuffer callbacks too; we’ll get to those later.) This immediate invocation can make trouble when dependencies get complex. For example, suppose that there is a callback that moves data into evbuffer A when it grows empty, and another callback that processes data out of evbuffer A when it grows full. Since these calls are all happening on the stack, you might risk a stack overflow if the dependency grows nasty enough.
To solve this, you can tell a bufferevent (or an evbuffer) that its callbacks should be deferred. When the conditions are met for a deferred callback, rather than invoking it immediately, it is queued as part of the event_loop() call, and invoked after the regular events' callbacks.
As described above:
- The event loop fetches a batch of events, and processes them one by one immediately.
- Before the fetched events are processed, any new event won't be fetched and processed.
- If an event was marked as
BEV_OPT_DEFER_CALLBACKS
, then it will be processed after all other events in the same batch are processed.
Provided two callbacks ca
and cb
. First, ca
is called, ca
finds evbuffer_A
is empty, then writes a message into it.
Then, cb
is called, and cb
finds evbuffer_A
contains a message, then fetch and send it out.
When cb
is called, ca
's stack has been released. I think there won't be a stack overflow in such a scenario.
So, my question is:
What's the purpose of deferred callbacks in libevent?