On 09 Sep 2014, at 10:58 AM, Nick Kew <n...@webthing.com> wrote:

>> Ideally, filters should do this, but generally they don’t:
>> 
>>    /* Do nothing if asked to filter nothing. */
>>    if (APR_BRIGADE_EMPTY(bb)) {
>>        return ap_pass_brigade(f->next, bb);
>>    }
> 
> Why on Earth should filters want to do that, as opposed to:
> 
>> Some filters, like mod_deflate, do this:
>> 
>>    /* Do nothing if asked to filter nothing. */
>>    if (APR_BRIGADE_EMPTY(bb)) {
>>        return APR_SUCCESS;
>>    }
> 
> or similar variants?

Because if they did, the compensation code in ap_pass_brigade() wouldn’t be 
necessary.

>> In these cases ap_pass_brigade() is never called, so we detect this by 
>> keeping a marker that is changed on every call to ap_pass_brigade(). If the 
>> marker wasn’t changed during the call to the filter, we compensate by 
>> calling each downstream filter until the marker is changed, or we run out of 
>> filters.
> 
> Yes.  The logic is that we call ap_pass_brigade when there's
> something to pass.  Not when there's nothing: that would just
> look like superfluous overhead.
> 
> If you have a reason to propagate an immediate event regardless
> of that logic, surely that's the business of a FLUSH bucket.
> Then the question becomes, is it ever right to absorb (or buffer)
> and fail to propagate a FLUSH?  You seem instead to be ascribing
> FLUSH semantics to an empty brigade!

To be clear, an empty brigade does _not_ mean flush, not even slightly.

Flush means “stop everything and perform this potentially expensive task to 
completion right now”, and is the exact opposite of what we’re trying to 
achieve.

> As a filter developer, it's my business to pass a brigade when:
> 1) I'm ready to pass data.
> 2) I encounter EOS, when I must finish up and propagate it.
> 3) I am explicitly signalled to FLUSH whatever I can.
> What am I missing?  Do we have a need to refine the FLUSH
> bucket type?  Maybe an EVENT bucket carrying an event descriptor?

In a synchronous world where it doesn’t matter how long a unit of work takes, 
sure.

In an async world you need to break up long running tasks into short running 
ones, so that others get a chance to have their data sent in the same thread, 
then this doesn’t work. Filters need to be able to yield and setaside data when 
they’re given too much data to process just like the core filter can - but 
right now they can’t, because that filter will never get called again, because 
upstream has no data to send.

Regards,
Graham
—

Reply via email to