On 06 Oct 2015, at 12:36 PM, Yann Ylavic <ylavic....@gmail.com> wrote:
>> Although the brigade is empty, don't we need to prevent the brigade being >> used by multiple threads in parallel? >> Using one per connection prevents this. > > Hmm, the filters are also allocated per connection/request (on > c/r->pool), and shouldn't be called concurrently right? Yes. > BTW, I wonder if we can "reinstate" the filters in arbitrary order > like in the above loop (the order seems to depend on the calls to > ap_filter_setaside_brigade() and internal apr_hash_t ordering). > Don't we need to start from r->ouput_filters down to the last filter > and call ap_pass_brigade(f, c->empty) if f is in the hashtable? No - we don’t “reinstate” filters in any way, we just kick them. We kick each eligible filter exactly once on each pass, and the order doesn’t matter. Every filter with data in it gets a kick to ensure no filter is starved, all filters without data are silently ignored. When a kick arrives and the filter has something to write, the normal filter stack write order is preserved by ap_pass_brigade() and everything happens in the right order naturally without us having to do anything special. Typically only two filters at a time - the bottleneck and the network filter - will have data in it, all other filters will be empty. If mod_cache is present, then three filters are likely to have data in it (mod_cache, the bottleneck filter and the network filter), and three filters will get kicked. When I was investigating this I was originally looking at a skiplist to keep the ordering, but once I analysed it it turned out to be unnecessary. Regards, Graham —