$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: eric_at_[hidden]
Date: 2008-03-05 20:56:58
Author: eric_niebler
Date: 2008-03-05 20:56:57 EST (Wed, 05 Mar 2008)
New Revision: 43523
URL: http://svn.boost.org/trac/boost/changeset/43523
Log:
fix documentation about droppable, replace accumulator_set_wrapper example with bind() and ref()
Text files modified: 
   trunk/libs/accumulators/doc/accumulators.qbk |   165 +++++++++++++++++++++++---------------- 
   1 files changed, 97 insertions(+), 68 deletions(-)
Modified: trunk/libs/accumulators/doc/accumulators.qbk
==============================================================================
--- trunk/libs/accumulators/doc/accumulators.qbk	(original)
+++ trunk/libs/accumulators/doc/accumulators.qbk	2008-03-05 20:56:57 EST (Wed, 05 Mar 2008)
@@ -247,34 +247,8 @@
 This works, but some accumulators are not cheap to copy. For
 example, the _tail_ and _tail_variate_ accumulators must store a `std::vector<>`, so copying
 these accumulators involves a dynamic allocation. We might be better off in this
-case to define a wrapper that stores a reference to an _accumulator_set_ and forwards the
-function call operator to it. See below:
-
-    template< typename Sample, typename Features, typename Weight >
-    struct accumulator_set_wrapper
-      : std::unary_function< Sample, void >
-    {
-        accumulator_set_wrapper( accumulator_set< Sample, Features, Weight > & acc )
-          : acc_(acc)
-        {
-        }
-        
-        void operator()( Sample const & sample )
-        {
-            this->acc_( sample );
-        }
-    private:
-        accumulator_set< Sample, Features, Weight > & acc_;
-    };
-
-    template< typename Sample, typename Features, typename Weight >
-    accumulator_set_wrapper< typename Sample, typename Features, typename Weight >
-    make_accumulator_set_wrapper( accumulator_set< Sample, Features, Weight > & acc )
-    {
-        return acc;
-    }
-
-You might use such an `accumulator_set_wrapper<>` as follows:
+case passing the accumulator by reference, with the help of `boost::bind()` and
+`boost::ref()`. See below:
 
     // The data for which we wish to calculate statistical properties:
     std::vector< double > data( /* stuff */ );
@@ -284,10 +258,13 @@
         tag::tail<left>::cache_size = 4 );
 
     // Use std::for_each to accumulate the statistical properties:
-    std::for_each( data.begin(), data.end(), make_accumulator_set_wrapper( acc ) );
+    std::for_each( data.begin(), data.end(), bind<void>( ref(acc), _1 ) );
+
+Notice now that we don't care about the return value of `std::for_each()` anymore because
+`std::for_each()` is modifying `acc` directly.
 
-Notice now that we don't care about the return value of `std::for_each` anymore because
-`std::for_each` is modifying `acc` directly.
+[note To use `boost::bind()` and `boost::ref()`, you must `#include` [^<boost/bind.hpp>]
+and [^<boost/ref.hpp>]]
 
 [endsect]
 
@@ -598,54 +575,106 @@
 [h3 Droppable Accumulators]
 
 The term "droppable" refers to an accumulator that can be removed from the _accumulator_set_.
-You can request that an accumulator be made droppable by using the _droppable_ class template,
-as follows:
+You can request that an accumulator be made droppable by using the _droppable_ class template.
+
+    // calculate sum and count, make sum droppable:
+    accumulator_set< double, features< tag::count, droppable<tag::sum> > > acc;
 
-    // calculate sum and mean, make mean droppable
-    accumulator_set< double, features< tag::sum, droppable<tag::mean> > > acc;
-    
     // add some data
-    acc(1.0);
+    acc(3.0);
     acc(2.0);
 
-    // drop the mean (mean is 1.5 here)
-    acc.drop<tag::mean>();
+    // drop the sum (sum is 5 here)
+    acc.drop<tag::sum>();
     
     // add more data
-    acc(3.0);
+    acc(1.0);
     
-    // This will display "6" and "1.5"
-    std::cout << sum(acc) << '\n' << mean(acc);    
+    // This will display "3" and "5"
+    std::cout << count(acc) << ' ' << sum(acc);    
+
+Any accumulators that get added to an accumulator set in order to satisfy
+dependencies on droppable accumulators are themselves droppable. Consider
+the following accumulator:
 
-Dropping an accumulator essentially freezes it in its current state. It no longer gets
-updates. For many accumulators, not receiving updates is sufficient to freeze their
-states. But for the `mean_accumulator` defined above, that's not the case. Its
-result depends on the `sum` and `count` accumulators, which are not frozen. Instead,
-it needs to save its result at the point it is dropped. The Accumulators Framework
-provides some utilities to make this simple. Simply create the following
-specialization of _droppable_accumulator_:
+    // Sum is not droppable. Mean is droppable. Count, brought in to 
+    // satisfy mean's dependencies, is implicitly droppable, too.
+    accumulator_set< double, features< tag::sum, droppable<tag::mean> > > acc;
 
-    namespace boost { namespace accumulators {
+`mean` depends on `sum` and `count`. Since `mean` is droppable, so too is `count`.
+However, we have explictitly requested that `sum` be not droppable, so it isn't. Had
+we left `tag::sum` out of the above declaration, the `sum` accumulator would have
+been implicitly droppable.
+
+A droppable accumulator is reference counted, and is only really dropped after all the
+accumulators that depend on it have been dropped. This can lead to some surprising
+behavior in some situations. 
     
-    // cache the result at the point the accumulator is dropped.
-    template<typename Sample>
-    struct droppable_accumulator<impl::mean_accumulator<Sample> >
-      : droppable_accumulator_base<
-            with_cached_result<impl::mean_accumulator<Sample> >
-        >
-    {
-        template<typename Args>
-        droppable_accumulator(Args const & args)
-          : droppable_accumulator::base(args)
-        {
-        }
-    };
+    // calculate sum and mean, make mean droppable. 
+    accumulator_set< double, features< tag::sum, droppable<tag::mean> > > acc;
     
-    }}
-
-This specialization will get used whenever `mean_accumulator<>` is made droppable.
-The `with_cached_result<>` utility causes the result to be cached at the point
-the accumulator is dropped by implementing `on_drop(Args)` appropriately.
+    // add some data
+    acc(1.0);
+    acc(2.0);
+    
+    // drop the mean. mean's reference count
+    // drops to 0, so it's really dropped. So
+    // too, count's reference count drops to 0
+    // and is really dropped.
+    acc.drop<tag::mean>();
+    
+    // add more data. Sum continues to accumulate!
+    acc(3.0);
+    
+    // This will display "6 2 3"
+    std::cout << sum(acc) << ' '
+              << count(acc) << ' '    
+              << mean(acc);
+
+Note that at the point at which `mean` is dropped, `sum` is 3, `count` is 2, and
+therefore `mean` is 1.5. But since `sum` continues to accumulate even after `mean`
+has been dropped, the value of `mean` continues to change. If you want to remember
+the value of `mean` at the point it is dropped, you should save its value into
+a local variable.
+
+The following rules more precisely specify how droppable and non-droppable
+accumulators behave within an accumulator set.
+
+* There are two types of accumulators: droppable and non-droppable.
+  The default is non-droppable.
+* For any feature `X`, both `X` and `droppable<X>` satisfy the `X` dependency.
+* If feature `X` depends on `Y` and `Z`, then `droppable<X>` depends on
+  `droppable<Y>` and `droppable<Z>`.
+* All accumulators have `add_ref()` and `drop()` member functions.
+* For non-droppable accumulators, `drop()` is a no-op, and `add_ref()`
+  invokes `add_ref()` on all accumulators corresponding to the features
+  upon which the current accumulator depends.
+* Droppable accumulators have a reference count and define `add_ref()`
+  and `drop()` to manipulate the reference count.
+* For droppable accumulators, `add_ref()` increments the accumulator's
+  reference count, and also `add_ref()`'s the accumulators corresponding
+  to the features upon which the current accumulator depends.
+* For droppable accumulators, `drop()` decrements the accumulator's
+  reference count, and also `drop()`'s the accumulators corresponding to
+  the features upon which the current accumulator depends.
+* The accumulator_set constructor walks the list of *user-specified*
+  features and `add_ref()`'s the accumulator that corresponds to each of
+  them. (Note: that means that an accumulator that is not user-specified
+  but in the set merely to satisfy a dependency will be dropped as soon
+  as all its dependencies have been dropped. Ones that have been user
+  specified are not dropped until their dependencies have been
+  dropped *and* the user has explicitly dropped the accumulator.)
+* Droppable accumulators check their reference count in their
+  accumulate member function. If the reference count is 0, the function
+  is a no-op.
+* Users are not allowed to drop a feature that is not user-specified and
+  marked as droppable.
+
+And as an optimization:
+
+* If the user specifies the non-droppable feature `X`, which depends on `Y`
+  and `Z`, then the accumulators for `Y` and `Z` can be safely made
+  non-droppable, as well as any accumulators on which they depend.
 
 [endsect]