On Mon, Apr 25, 2005 at 06:12:04PM -0500, Rici Lake wrote:
> I guess that depends on whether most filters use and recycle pass 
> brigades. I suspect that most internal filters don't (and possibly have 
> the model which Joe Schaefer describes, where the brigade is simply 
> passed through), whereas most third-party filters probably either do or 
> should. Having now looked at quite a few output filters, I've come to 
> the conclusion that the normal model is to create and destroy brigades 
> on every invocation, which I can't help but think is a lot less 
> efficient than it could be.
> 
> But I actually disagree with the premise: the issue is not how 
> prevalent the case is, it is how likely it is to create a bug which is 
> triggered by an interaction between unrelated modules. Mitigating the 
> creation of such bugs is, in my mind, an important part of component 
> API design; particularly if the mitigation is low-cost. Of course, 
> everyone has their own concept of beauty, and mine is probably the 
> least important of anyone participating in this debate.

This is really just a "should we provide extra API guarantees to prevent
users shooting themselves in the foot" debate, right?  Let's agree to
disagree :)

> In any event, a draft docstring. This does not reflect my view, and I 
> don't know if there is actually a consensus view, but it may reflect 
> the current state of affairs:

It got linewrapped (format=flowed?) but otherwise I think this looks
good - thanks a lot.  Final chance for any dissenter to object? Else
I'll commit this...

(attached un-line-wrapped version)
Index: util_filter.h
===================================================================
--- util_filter.h       (revision 158730)
+++ util_filter.h       (working copy)
@@ -103,8 +103,8 @@
  * @name Filter callbacks
  *
  * This function type is used for filter callbacks. It will be passed a
- * pointer to "this" filter, and a "bucket" containing the content to be
- * filtered.
+ * pointer to "this" filter, and a "bucket brigade" containing the content
+ * to be filtered.
  *
  * In filter->ctx, the callback will find its context. This context is
  * provided here, so that a filter may be installed multiple times, each
@@ -120,10 +120,15 @@
  * or output filter chains and before any data is generated to allow the
  * filter to prepare for processing.
  *
- * The *bucket structure (and all those referenced by ->next and ->prev)
- * should be considered "const". The filter is allowed to modify the
- * next/prev to insert/remove/replace elements in the bucket list, but
- * the types and values of the individual buckets should not be altered.
+ * The bucket brigade always belongs to the caller, but the filter
+ * is free to use the buckets within it as it sees fit. Normally,
+ * the brigade will be returned empty. Buckets *may not* be retained
+ * between successive calls to the filter unless they have been
+ * "set aside" with a call apr_bucket_setaside. Typically this will
+ * be done with ap_save_brigade(). Buckets removed from the brigade
+ * become the responsibility of the filter, which must arrange for
+ * them to be deleted, either by doing so directly or by inserting
+ * them in a brigade which will subsequently be destroyed.
  *
  * For the input and output filters, the return value of a filter should be
  * an APR status value.  For the init function, the return value should
@@ -299,9 +304,13 @@
  * Pass the current bucket brigade down to the next filter on the filter
  * stack.  The filter returns an apr_status_t value.  If the bottom-most
  * filter doesn't write to the network, then ::AP_NOBODY_WROTE is returned.
- * The caller relinquishes ownership of the brigade.
  * @param filter The next filter in the chain
  * @param bucket The current bucket brigade
+ *
+ * @remark Ownership of the brigade is retained by the caller. On return,
+ *         the contents of the brigade are UNDEFINED, and the caller must
+ *         either call apr_brigade_cleanup or apr_brigade_destroy on
+ *         the brigade.
  */
 AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *filter,
                                          apr_bucket_brigade *bucket);

Reply via email to