statistics.hh revision 6128:fdfbd4c6e449
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31/** @file
32 * Declaration of Statistics objects.
33 */
34
35/**
36* @todo
37*
38* Generalized N-dimensinal vector
39* documentation
40* key stats
41* interval stats
42*   -- these both can use the same function that prints out a
43*   specific set of stats
44* VectorStandardDeviation totals
45* Document Namespaces
46*/
47#ifndef __BASE_STATISTICS_HH__
48#define __BASE_STATISTICS_HH__
49
50#include <algorithm>
51#include <cassert>
52#ifdef __SUNPRO_CC
53#include <math.h>
54#endif
55#include <cmath>
56#include <functional>
57#include <iosfwd>
58#include <list>
59#include <string>
60#include <vector>
61
62#include "base/cast.hh"
63#include "base/cprintf.hh"
64#include "base/intmath.hh"
65#include "base/refcnt.hh"
66#include "base/str.hh"
67#include "base/stats/flags.hh"
68#include "base/stats/visit.hh"
69#include "base/stats/types.hh"
70#include "sim/host.hh"
71
72class Callback;
73
74/** The current simulated tick. */
75extern Tick curTick;
76
77/* A namespace for all of the Statistics */
78namespace Stats {
79
80struct StorageParams
81{
82    virtual ~StorageParams();
83};
84
85//////////////////////////////////////////////////////////////////////
86//
87// Statistics Framework Base classes
88//
89//////////////////////////////////////////////////////////////////////
90class Info
91{
92  public:
93    /** The name of the stat. */
94    std::string name;
95    /** The description of the stat. */
96    std::string desc;
97    /** The formatting flags. */
98    StatFlags flags;
99    /** The display precision. */
100    int precision;
101    /** A pointer to a prerequisite Stat. */
102    const Info *prereq;
103    /**
104     * A unique stat ID for each stat in the simulator.
105     * Can be used externally for lookups as well as for debugging.
106     */
107    static int id_count;
108    int id;
109
110  public:
111    const StorageParams *storageParams;
112
113  public:
114    Info();
115    virtual ~Info();
116
117    /** Set the name of this statistic */
118    void setName(const std::string &name);
119
120    /**
121     * Check that this stat has been set up properly and is ready for
122     * use
123     * @return true for success
124     */
125    virtual bool check() const = 0;
126    bool baseCheck() const;
127
128    /**
129     * Enable the stat for use
130     */
131    virtual void enable();
132
133    /**
134     * Prepare the stat for dumping.
135     */
136    virtual void prepare() = 0;
137
138    /**
139     * Reset the stat to the default state.
140     */
141    virtual void reset() = 0;
142
143    /**
144     * @return true if this stat has a value and satisfies its
145     * requirement as a prereq
146     */
147    virtual bool zero() const = 0;
148
149    /**
150     * Visitor entry for outputing statistics data
151     */
152    virtual void visit(Visit &visitor) = 0;
153
154    /**
155     * Checks if the first stat's name is alphabetically less than the second.
156     * This function breaks names up at periods and considers each subname
157     * separately.
158     * @param stat1 The first stat.
159     * @param stat2 The second stat.
160     * @return stat1's name is alphabetically before stat2's
161     */
162    static bool less(Info *stat1, Info *stat2);
163};
164struct StorageParams;
165
166template <class Stat, class Base>
167class InfoProxy : public Base
168{
169  protected:
170    Stat &s;
171
172  public:
173    InfoProxy(Stat &stat) : s(stat) {}
174
175    bool check() const { return s.check(); }
176    void prepare() { s.prepare(); }
177    void reset() { s.reset(); }
178    void
179    visit(Visit &visitor)
180    {
181        visitor.visit(*static_cast<Base *>(this));
182    }
183    bool zero() const { return s.zero(); }
184};
185
186class ScalarInfo : public Info
187{
188  public:
189    virtual Counter value() const = 0;
190    virtual Result result() const = 0;
191    virtual Result total() const = 0;
192};
193
194template <class Stat>
195class ScalarInfoProxy : public InfoProxy<Stat, ScalarInfo>
196{
197  public:
198    ScalarInfoProxy(Stat &stat) : InfoProxy<Stat, ScalarInfo>(stat) {}
199
200    Counter value() const { return this->s.value(); }
201    Result result() const { return this->s.result(); }
202    Result total() const { return this->s.total(); }
203};
204
205class VectorInfo : public Info
206{
207  public:
208    /** Names and descriptions of subfields. */
209    std::vector<std::string> subnames;
210    std::vector<std::string> subdescs;
211
212  public:
213    void enable();
214
215  public:
216    virtual size_type size() const = 0;
217    virtual const VCounter &value() const = 0;
218    virtual const VResult &result() const = 0;
219    virtual Result total() const = 0;
220};
221
222template <class Stat>
223class VectorInfoProxy : public InfoProxy<Stat, VectorInfo>
224{
225  protected:
226    mutable VCounter cvec;
227    mutable VResult rvec;
228
229  public:
230    VectorInfoProxy(Stat &stat) : InfoProxy<Stat, VectorInfo>(stat) {}
231
232    size_type size() const { return this->s.size(); }
233
234    VCounter &
235    value() const
236    {
237        this->s.value(cvec);
238        return cvec;
239    }
240
241    const VResult &
242    result() const
243    {
244        this->s.result(rvec);
245        return rvec;
246    }
247
248    Result total() const { return this->s.total(); }
249};
250
251struct DistData
252{
253    Counter min_val;
254    Counter max_val;
255    Counter underflow;
256    Counter overflow;
257    VCounter cvec;
258    Counter sum;
259    Counter squares;
260    Counter samples;
261};
262
263class DistInfo : public Info
264{
265  public:
266    /** Local storage for the entry values, used for printing. */
267    DistData data;
268};
269
270template <class Stat>
271class DistInfoProxy : public InfoProxy<Stat, DistInfo>
272{
273  public:
274    DistInfoProxy(Stat &stat) : InfoProxy<Stat, DistInfo>(stat) {}
275};
276
277class VectorDistInfo : public Info
278{
279  public:
280    std::vector<DistData> data;
281
282    /** Names and descriptions of subfields. */
283    std::vector<std::string> subnames;
284    std::vector<std::string> subdescs;
285    void enable();
286
287  protected:
288    /** Local storage for the entry values, used for printing. */
289    mutable VResult rvec;
290
291  public:
292    virtual size_type size() const = 0;
293};
294
295template <class Stat>
296class VectorDistInfoProxy : public InfoProxy<Stat, VectorDistInfo>
297{
298  public:
299    VectorDistInfoProxy(Stat &stat) : InfoProxy<Stat, VectorDistInfo>(stat) {}
300
301    size_type size() const { return this->s.size(); }
302};
303
304class Vector2dInfo : public Info
305{
306  public:
307    /** Names and descriptions of subfields. */
308    std::vector<std::string> subnames;
309    std::vector<std::string> subdescs;
310    std::vector<std::string> y_subnames;
311
312    size_type x;
313    size_type y;
314
315    /** Local storage for the entry values, used for printing. */
316    mutable VCounter cvec;
317
318    void enable();
319};
320
321template <class Stat>
322class Vector2dInfoProxy : public InfoProxy<Stat, Vector2dInfo>
323{
324  public:
325    Vector2dInfoProxy(Stat &stat) : InfoProxy<Stat, Vector2dInfo>(stat) {}
326};
327
328class InfoAccess
329{
330  protected:
331    /** Set up an info class for this statistic */
332    void setInfo(Info *info);
333    /** Save Storage class parameters if any */
334    void setParams(const StorageParams *params);
335    /** Save Storage class parameters if any */
336    void setInit();
337
338    /** Grab the information class for this statistic */
339    Info *info();
340    /** Grab the information class for this statistic */
341    const Info *info() const;
342
343  public:
344    /**
345     * Reset the stat to the default state.
346     */
347    void reset() { }
348
349    /**
350     * @return true if this stat has a value and satisfies its
351     * requirement as a prereq
352     */
353    bool zero() const { return true; }
354
355    /**
356     * Check that this stat has been set up properly and is ready for
357     * use
358     * @return true for success
359     */
360    bool check() const { return true; }
361};
362
363template <class Derived, template <class> class InfoProxyType>
364class DataWrap : public InfoAccess
365{
366  public:
367    typedef InfoProxyType<Derived> Info;
368
369  protected:
370    Derived &self() { return *static_cast<Derived *>(this); }
371
372  protected:
373    Info *
374    info()
375    {
376        return safe_cast<Info *>(InfoAccess::info());
377    }
378
379  public:
380    const Info *
381    info() const
382    {
383        return safe_cast<const Info *>(InfoAccess::info());
384    }
385
386  protected:
387    /**
388     * Copy constructor, copies are not allowed.
389     */
390    DataWrap(const DataWrap &stat);
391
392    /**
393     * Can't copy stats.
394     */
395    void operator=(const DataWrap &);
396
397  public:
398    DataWrap()
399    {
400        this->setInfo(new Info(self()));
401    }
402
403    /**
404     * Set the name and marks this stat to print at the end of simulation.
405     * @param name The new name.
406     * @return A reference to this stat.
407     */
408    Derived &
409    name(const std::string &name)
410    {
411        Info *info = this->info();
412        info->setName(name);
413        info->flags |= print;
414        return this->self();
415    }
416    const std::string &name() const { return this->info()->name; }
417
418    /**
419     * Set the description and marks this stat to print at the end of
420     * simulation.
421     * @param desc The new description.
422     * @return A reference to this stat.
423     */
424    Derived &
425    desc(const std::string &_desc)
426    {
427        this->info()->desc = _desc;
428        return this->self();
429    }
430
431    /**
432     * Set the precision and marks this stat to print at the end of simulation.
433     * @param _precision The new precision
434     * @return A reference to this stat.
435     */
436    Derived &
437    precision(int _precision)
438    {
439        this->info()->precision = _precision;
440        return this->self();
441    }
442
443    /**
444     * Set the flags and marks this stat to print at the end of simulation.
445     * @param f The new flags.
446     * @return A reference to this stat.
447     */
448    Derived &
449    flags(StatFlags _flags)
450    {
451        this->info()->flags |= _flags;
452        return this->self();
453    }
454
455    /**
456     * Set the prerequisite stat and marks this stat to print at the end of
457     * simulation.
458     * @param prereq The prerequisite stat.
459     * @return A reference to this stat.
460     */
461    template <class Stat>
462    Derived &
463    prereq(const Stat &prereq)
464    {
465        this->info()->prereq = prereq.info();
466        return this->self();
467    }
468};
469
470template <class Derived, template <class> class InfoProxyType>
471class DataWrapVec : public DataWrap<Derived, InfoProxyType>
472{
473  public:
474    typedef InfoProxyType<Derived> Info;
475
476    // The following functions are specific to vectors.  If you use them
477    // in a non vector context, you will get a nice compiler error!
478
479    /**
480     * Set the subfield name for the given index, and marks this stat to print
481     * at the end of simulation.
482     * @param index The subfield index.
483     * @param name The new name of the subfield.
484     * @return A reference to this stat.
485     */
486    Derived &
487    subname(off_type index, const std::string &name)
488    {
489        Derived &self = this->self();
490        Info *info = self.info();
491
492        std::vector<std::string> &subn = info->subnames;
493        if (subn.size() <= index)
494            subn.resize(index + 1);
495        subn[index] = name;
496        return self;
497    }
498
499    // The following functions are specific to 2d vectors.  If you use
500    // them in a non vector context, you will get a nice compiler
501    // error because info doesn't have the right variables.
502
503    /**
504     * Set the subfield description for the given index and marks this stat to
505     * print at the end of simulation.
506     * @param index The subfield index.
507     * @param desc The new description of the subfield
508     * @return A reference to this stat.
509     */
510    Derived &
511    subdesc(off_type index, const std::string &desc)
512    {
513        Info *info = this->info();
514
515        std::vector<std::string> &subd = info->subdescs;
516        if (subd.size() <= index)
517            subd.resize(index + 1);
518        subd[index] = desc;
519
520        return this->self();
521    }
522
523    void
524    prepare()
525    {
526        Derived &self = this->self();
527        Info *info = this->info();
528
529        size_t size = self.size();
530        for (off_type i = 0; i < size; ++i)
531            self.data(i)->prepare(info);
532    }
533
534    void
535    reset()
536    {
537        Derived &self = this->self();
538        Info *info = this->info();
539
540        size_t size = self.size();
541        for (off_type i = 0; i < size; ++i)
542            self.data(i)->reset(info);
543    }
544};
545
546template <class Derived, template <class> class InfoProxyType>
547class DataWrapVec2d : public DataWrapVec<Derived, InfoProxyType>
548{
549  public:
550    typedef InfoProxyType<Derived> Info;
551
552    /**
553     * @warning This makes the assumption that if you're gonna subnames a 2d
554     * vector, you're subnaming across all y
555     */
556    Derived &
557    ysubnames(const char **names)
558    {
559        Derived &self = this->self();
560        Info *info = this->info();
561
562        info->y_subnames.resize(self.y);
563        for (off_type i = 0; i < self.y; ++i)
564            info->y_subnames[i] = names[i];
565        return self;
566    }
567
568    Derived &
569    ysubname(off_type index, const std::string subname)
570    {
571        Derived &self = this->self();
572        Info *info = this->info();
573
574        assert(index < self.y);
575        info->y_subnames.resize(self.y);
576        info->y_subnames[index] = subname.c_str();
577        return self;
578    }
579};
580
581//////////////////////////////////////////////////////////////////////
582//
583// Simple Statistics
584//
585//////////////////////////////////////////////////////////////////////
586
587/**
588 * Templatized storage and interface for a simple scalar stat.
589 */
590class StatStor
591{
592  private:
593    /** The statistic value. */
594    Counter data;
595
596  public:
597    struct Params : public StorageParams {};
598
599  public:
600    /**
601     * Builds this storage element and calls the base constructor of the
602     * datatype.
603     */
604    StatStor(Info *info)
605        : data(Counter())
606    { }
607
608    /**
609     * The the stat to the given value.
610     * @param val The new value.
611     */
612    void set(Counter val) { data = val; }
613    /**
614     * Increment the stat by the given value.
615     * @param val The new value.
616     */
617    void inc(Counter val) { data += val; }
618    /**
619     * Decrement the stat by the given value.
620     * @param val The new value.
621     */
622    void dec(Counter val) { data -= val; }
623    /**
624     * Return the value of this stat as its base type.
625     * @return The value of this stat.
626     */
627    Counter value() const { return data; }
628    /**
629     * Return the value of this stat as a result type.
630     * @return The value of this stat.
631     */
632    Result result() const { return (Result)data; }
633    /**
634     * Prepare stat data for dumping or serialization
635     */
636    void prepare(Info *info) { }
637    /**
638     * Reset stat value to default
639     */
640    void reset(Info *info) { data = Counter(); }
641
642    /**
643     * @return true if zero value
644     */
645    bool zero() const { return data == Counter(); }
646};
647
648/**
649 * Templatized storage and interface to a per-tick average stat. This keeps
650 * a current count and updates a total (count * ticks) when this count
651 * changes. This allows the quick calculation of a per tick count of the item
652 * being watched. This is good for keeping track of residencies in structures
653 * among other things.
654 */
655class AvgStor
656{
657  private:
658    /** The current count. */
659    Counter current;
660    /** The total count for all tick. */
661    mutable Result total;
662    /** The tick that current last changed. */
663    mutable Tick last;
664
665  public:
666    struct Params : public StorageParams {};
667
668  public:
669    /**
670     * Build and initializes this stat storage.
671     */
672    AvgStor(Info *info)
673        : current(0), total(0), last(0)
674    { }
675
676    /**
677     * Set the current count to the one provided, update the total and last
678     * set values.
679     * @param val The new count.
680     */
681    void
682    set(Counter val)
683    {
684        total += current * (curTick - last);
685        last = curTick;
686        current = val;
687    }
688
689    /**
690     * Increment the current count by the provided value, calls set.
691     * @param val The amount to increment.
692     */
693    void inc(Counter val) { set(current + val); }
694
695    /**
696     * Deccrement the current count by the provided value, calls set.
697     * @param val The amount to decrement.
698     */
699    void dec(Counter val) { set(current - val); }
700
701    /**
702     * Return the current count.
703     * @return The current count.
704     */
705    Counter value() const { return current; }
706
707    /**
708     * Return the current average.
709     * @return The current average.
710     */
711    Result
712    result() const
713    {
714        assert(last == curTick);
715        return (Result)(total + current) / (Result)(curTick + 1);
716    }
717
718    /**
719     * @return true if zero value
720     */
721    bool zero() const { return total == 0.0; }
722
723    /**
724     * Prepare stat data for dumping or serialization
725     */
726    void
727    prepare(Info *info)
728    {
729        total += current * (curTick - last);
730        last = curTick;
731    }
732
733    /**
734     * Reset stat value to default
735     */
736    void
737    reset(Info *info)
738    {
739        total = 0.0;
740        last = curTick;
741    }
742
743};
744
745/**
746 * Implementation of a scalar stat. The type of stat is determined by the
747 * Storage template.
748 */
749template <class Derived, class Stor>
750class ScalarBase : public DataWrap<Derived, ScalarInfoProxy>
751{
752  public:
753    typedef Stor Storage;
754    typedef typename Stor::Params Params;
755
756  protected:
757    /** The storage of this stat. */
758    char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
759
760  protected:
761    /**
762     * Retrieve the storage.
763     * @param index The vector index to access.
764     * @return The storage object at the given index.
765     */
766    Storage *
767    data()
768    {
769        return reinterpret_cast<Storage *>(storage);
770    }
771
772    /**
773     * Retrieve a const pointer to the storage.
774     * for the given index.
775     * @param index The vector index to access.
776     * @return A const pointer to the storage object at the given index.
777     */
778    const Storage *
779    data() const
780    {
781        return reinterpret_cast<const Storage *>(storage);
782    }
783
784    void
785    doInit()
786    {
787        new (storage) Storage(this->info());
788        this->setInit();
789    }
790
791  public:
792    /**
793     * Return the current value of this stat as its base type.
794     * @return The current value.
795     */
796    Counter value() const { return data()->value(); }
797
798  public:
799    ScalarBase()
800    {
801        this->doInit();
802    }
803
804  public:
805    // Common operators for stats
806    /**
807     * Increment the stat by 1. This calls the associated storage object inc
808     * function.
809     */
810    void operator++() { data()->inc(1); }
811    /**
812     * Decrement the stat by 1. This calls the associated storage object dec
813     * function.
814     */
815    void operator--() { data()->dec(1); }
816
817    /** Increment the stat by 1. */
818    void operator++(int) { ++*this; }
819    /** Decrement the stat by 1. */
820    void operator--(int) { --*this; }
821
822    /**
823     * Set the data value to the given value. This calls the associated storage
824     * object set function.
825     * @param v The new value.
826     */
827    template <typename U>
828    void operator=(const U &v) { data()->set(v); }
829
830    /**
831     * Increment the stat by the given value. This calls the associated
832     * storage object inc function.
833     * @param v The value to add.
834     */
835    template <typename U>
836    void operator+=(const U &v) { data()->inc(v); }
837
838    /**
839     * Decrement the stat by the given value. This calls the associated
840     * storage object dec function.
841     * @param v The value to substract.
842     */
843    template <typename U>
844    void operator-=(const U &v) { data()->dec(v); }
845
846    /**
847     * Return the number of elements, always 1 for a scalar.
848     * @return 1.
849     */
850    size_type size() const { return 1; }
851
852    Counter value() { return data()->value(); }
853
854    Result result() { return data()->result(); }
855
856    Result total() { return result(); }
857
858    bool zero() { return result() == 0.0; }
859
860    void reset() { data()->reset(this->info()); }
861    void prepare() { data()->prepare(this->info()); }
862};
863
864class ProxyInfo : public ScalarInfo
865{
866  public:
867    std::string str() const { return to_string(value()); }
868    size_type size() const { return 1; }
869    bool check() const { return true; }
870    void prepare() { }
871    void reset() { }
872    bool zero() const { return value() == 0; }
873
874    void visit(Visit &visitor) { visitor.visit(*this); }
875};
876
877template <class T>
878class ValueProxy : public ProxyInfo
879{
880  private:
881    T *scalar;
882
883  public:
884    ValueProxy(T &val) : scalar(&val) {}
885    Counter value() const { return *scalar; }
886    Result result() const { return *scalar; }
887    Result total() const { return *scalar; }
888};
889
890template <class T>
891class FunctorProxy : public ProxyInfo
892{
893  private:
894    T *functor;
895
896  public:
897    FunctorProxy(T &func) : functor(&func) {}
898    Counter value() const { return (*functor)(); }
899    Result result() const { return (*functor)(); }
900    Result total() const { return (*functor)(); }
901};
902
903template <class Derived>
904class ValueBase : public DataWrap<Derived, ScalarInfoProxy>
905{
906  private:
907    ProxyInfo *proxy;
908
909  public:
910    ValueBase() : proxy(NULL) { }
911    ~ValueBase() { if (proxy) delete proxy; }
912
913    template <class T>
914    Derived &
915    scalar(T &value)
916    {
917        proxy = new ValueProxy<T>(value);
918        this->setInit();
919        return this->self();
920    }
921
922    template <class T>
923    Derived &
924    functor(T &func)
925    {
926        proxy = new FunctorProxy<T>(func);
927        this->setInit();
928        return this->self();
929    }
930
931    Counter value() { return proxy->value(); }
932    Result result() const { return proxy->result(); }
933    Result total() const { return proxy->total(); };
934    size_type size() const { return proxy->size(); }
935
936    std::string str() const { return proxy->str(); }
937    bool zero() const { return proxy->zero(); }
938    bool check() const { return proxy != NULL; }
939    void prepare() { }
940    void reset() { }
941};
942
943//////////////////////////////////////////////////////////////////////
944//
945// Vector Statistics
946//
947//////////////////////////////////////////////////////////////////////
948
949/**
950 * A proxy class to access the stat at a given index in a VectorBase stat.
951 * Behaves like a ScalarBase.
952 */
953template <class Stat>
954class ScalarProxy
955{
956  private:
957    /** Pointer to the parent Vector. */
958    Stat &stat;
959
960    /** The index to access in the parent VectorBase. */
961    off_type index;
962
963  public:
964    /**
965     * Return the current value of this stat as its base type.
966     * @return The current value.
967     */
968    Counter value() const { return stat.data(index)->value(); }
969
970    /**
971     * Return the current value of this statas a result type.
972     * @return The current value.
973     */
974    Result result() const { return stat.data(index)->result(); }
975
976  public:
977    /**
978     * Create and initialize this proxy, do not register it with the database.
979     * @param i The index to access.
980     */
981    ScalarProxy(Stat &s, off_type i)
982        : stat(s), index(i)
983    {
984    }
985
986    /**
987     * Create a copy of the provided ScalarProxy.
988     * @param sp The proxy to copy.
989     */
990    ScalarProxy(const ScalarProxy &sp)
991        : stat(sp.stat), index(sp.index)
992    {}
993
994    /**
995     * Set this proxy equal to the provided one.
996     * @param sp The proxy to copy.
997     * @return A reference to this proxy.
998     */
999    const ScalarProxy &
1000    operator=(const ScalarProxy &sp)
1001    {
1002        stat = sp.stat;
1003        index = sp.index;
1004        return *this;
1005    }
1006
1007  public:
1008    // Common operators for stats
1009    /**
1010     * Increment the stat by 1. This calls the associated storage object inc
1011     * function.
1012     */
1013    void operator++() { stat.data(index)->inc(1); }
1014    /**
1015     * Decrement the stat by 1. This calls the associated storage object dec
1016     * function.
1017     */
1018    void operator--() { stat.data(index)->dec(1); }
1019
1020    /** Increment the stat by 1. */
1021    void operator++(int) { ++*this; }
1022    /** Decrement the stat by 1. */
1023    void operator--(int) { --*this; }
1024
1025    /**
1026     * Set the data value to the given value. This calls the associated storage
1027     * object set function.
1028     * @param v The new value.
1029     */
1030    template <typename U>
1031    void
1032    operator=(const U &v)
1033    {
1034        stat.data(index)->set(v);
1035    }
1036
1037    /**
1038     * Increment the stat by the given value. This calls the associated
1039     * storage object inc function.
1040     * @param v The value to add.
1041     */
1042    template <typename U>
1043    void
1044    operator+=(const U &v)
1045    {
1046        stat.data(index)->inc(v);
1047    }
1048
1049    /**
1050     * Decrement the stat by the given value. This calls the associated
1051     * storage object dec function.
1052     * @param v The value to substract.
1053     */
1054    template <typename U>
1055    void
1056    operator-=(const U &v)
1057    {
1058        stat.data(index)->dec(v);
1059    }
1060
1061    /**
1062     * Return the number of elements, always 1 for a scalar.
1063     * @return 1.
1064     */
1065    size_type size() const { return 1; }
1066
1067  public:
1068    std::string
1069    str() const
1070    {
1071        return csprintf("%s[%d]", stat.info()->name, index);
1072    }
1073};
1074
1075/**
1076 * Implementation of a vector of stats. The type of stat is determined by the
1077 * Storage class. @sa ScalarBase
1078 */
1079template <class Derived, class Stor>
1080class VectorBase : public DataWrapVec<Derived, VectorInfoProxy>
1081{
1082  public:
1083    typedef Stor Storage;
1084    typedef typename Stor::Params Params;
1085
1086    /** Proxy type */
1087    typedef ScalarProxy<Derived> Proxy;
1088    friend class ScalarProxy<Derived>;
1089    friend class DataWrapVec<Derived, VectorInfoProxy>;
1090
1091  protected:
1092    /** The storage of this stat. */
1093    Storage *storage;
1094    size_type _size;
1095
1096  protected:
1097    /**
1098     * Retrieve the storage.
1099     * @param index The vector index to access.
1100     * @return The storage object at the given index.
1101     */
1102    Storage *data(off_type index) { return &storage[index]; }
1103
1104    /**
1105     * Retrieve a const pointer to the storage.
1106     * @param index The vector index to access.
1107     * @return A const pointer to the storage object at the given index.
1108     */
1109    const Storage *data(off_type index) const { return &storage[index]; }
1110
1111    void
1112    doInit(size_type s)
1113    {
1114        assert(s > 0 && "size must be positive!");
1115        assert(!storage && "already initialized");
1116        _size = s;
1117
1118        char *ptr = new char[_size * sizeof(Storage)];
1119        storage = reinterpret_cast<Storage *>(ptr);
1120
1121        for (off_type i = 0; i < _size; ++i)
1122            new (&storage[i]) Storage(this->info());
1123
1124        this->setInit();
1125    }
1126
1127  public:
1128    void
1129    value(VCounter &vec) const
1130    {
1131        vec.resize(size());
1132        for (off_type i = 0; i < size(); ++i)
1133            vec[i] = data(i)->value();
1134    }
1135
1136    /**
1137     * Copy the values to a local vector and return a reference to it.
1138     * @return A reference to a vector of the stat values.
1139     */
1140    void
1141    result(VResult &vec) const
1142    {
1143        vec.resize(size());
1144        for (off_type i = 0; i < size(); ++i)
1145            vec[i] = data(i)->result();
1146    }
1147
1148    /**
1149     * Return a total of all entries in this vector.
1150     * @return The total of all vector entries.
1151     */
1152    Result
1153    total() const
1154    {
1155        Result total = 0.0;
1156        for (off_type i = 0; i < size(); ++i)
1157            total += data(i)->result();
1158        return total;
1159    }
1160
1161    /**
1162     * @return the number of elements in this vector.
1163     */
1164    size_type size() const { return _size; }
1165
1166    bool
1167    zero() const
1168    {
1169        for (off_type i = 0; i < size(); ++i)
1170            if (data(i)->zero())
1171                return false;
1172        return true;
1173    }
1174
1175    bool
1176    check() const
1177    {
1178        return storage != NULL;
1179    }
1180
1181  public:
1182    VectorBase()
1183        : storage(NULL)
1184    {}
1185
1186    ~VectorBase()
1187    {
1188        if (!storage)
1189            return;
1190
1191        for (off_type i = 0; i < _size; ++i)
1192            data(i)->~Storage();
1193        delete [] reinterpret_cast<char *>(storage);
1194    }
1195
1196    /**
1197     * Set this vector to have the given size.
1198     * @param size The new size.
1199     * @return A reference to this stat.
1200     */
1201    Derived &
1202    init(size_type size)
1203    {
1204        Derived &self = this->self();
1205        self.doInit(size);
1206        return self;
1207    }
1208
1209    /**
1210     * Return a reference (ScalarProxy) to the stat at the given index.
1211     * @param index The vector index to access.
1212     * @return A reference of the stat.
1213     */
1214    Proxy
1215    operator[](off_type index)
1216    {
1217        assert (index >= 0 && index < size());
1218        return Proxy(this->self(), index);
1219    }
1220};
1221
1222template <class Stat>
1223class VectorProxy
1224{
1225  private:
1226    Stat &stat;
1227    off_type offset;
1228    size_type len;
1229
1230  private:
1231    mutable VResult vec;
1232
1233    typename Stat::Storage *
1234    data(off_type index)
1235    {
1236        assert(index < len);
1237        return stat.data(offset + index);
1238    }
1239
1240    const typename Stat::Storage *
1241    data(off_type index) const
1242    {
1243        assert(index < len);
1244        return stat.data(offset + index);
1245    }
1246
1247  public:
1248    const VResult &
1249    result() const
1250    {
1251        vec.resize(size());
1252
1253        for (off_type i = 0; i < size(); ++i)
1254            vec[i] = data(i)->result();
1255
1256        return vec;
1257    }
1258
1259    Result
1260    total() const
1261    {
1262        Result total = 0.0;
1263        for (off_type i = 0; i < size(); ++i)
1264            total += data(i)->result();
1265        return total;
1266    }
1267
1268  public:
1269    VectorProxy(Stat &s, off_type o, size_type l)
1270        : stat(s), offset(o), len(l)
1271    {
1272    }
1273
1274    VectorProxy(const VectorProxy &sp)
1275        : stat(sp.stat), offset(sp.offset), len(sp.len)
1276    {
1277    }
1278
1279    const VectorProxy &
1280    operator=(const VectorProxy &sp)
1281    {
1282        stat = sp.stat;
1283        offset = sp.offset;
1284        len = sp.len;
1285        return *this;
1286    }
1287
1288    ScalarProxy<Stat>
1289    operator[](off_type index)
1290    {
1291        assert (index >= 0 && index < size());
1292        return ScalarProxy<Stat>(stat, offset + index);
1293    }
1294
1295    size_type size() const { return len; }
1296};
1297
1298template <class Derived, class Stor>
1299class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfoProxy>
1300{
1301  public:
1302    typedef Vector2dInfoProxy<Derived> Info;
1303    typedef Stor Storage;
1304    typedef typename Stor::Params Params;
1305    typedef VectorProxy<Derived> Proxy;
1306    friend class ScalarProxy<Derived>;
1307    friend class VectorProxy<Derived>;
1308    friend class DataWrapVec<Derived, Vector2dInfoProxy>;
1309    friend class DataWrapVec2d<Derived, Vector2dInfoProxy>;
1310
1311  protected:
1312    size_type x;
1313    size_type y;
1314    size_type _size;
1315    Storage *storage;
1316
1317  protected:
1318    Storage *data(off_type index) { return &storage[index]; }
1319    const Storage *data(off_type index) const { return &storage[index]; }
1320
1321  public:
1322    Vector2dBase()
1323        : storage(NULL)
1324    {}
1325
1326    ~Vector2dBase()
1327    {
1328        if (!storage)
1329            return;
1330
1331        for (off_type i = 0; i < _size; ++i)
1332            data(i)->~Storage();
1333        delete [] reinterpret_cast<char *>(storage);
1334    }
1335
1336    Derived &
1337    init(size_type _x, size_type _y)
1338    {
1339        assert(_x > 0 && _y > 0 && "sizes must be positive!");
1340        assert(!storage && "already initialized");
1341
1342        Derived &self = this->self();
1343        Info *info = this->info();
1344
1345        x = _x;
1346        y = _y;
1347        info->x = _x;
1348        info->y = _y;
1349        _size = x * y;
1350
1351        char *ptr = new char[_size * sizeof(Storage)];
1352        storage = reinterpret_cast<Storage *>(ptr);
1353
1354        for (off_type i = 0; i < _size; ++i)
1355            new (&storage[i]) Storage(info);
1356
1357        this->setInit();
1358
1359        return self;
1360    }
1361
1362    std::string ysubname(off_type i) const { return (*this->y_subnames)[i]; }
1363
1364    Proxy
1365    operator[](off_type index)
1366    {
1367        off_type offset = index * y;
1368        assert (index >= 0 && offset + index < size());
1369        return Proxy(this->self(), offset, y);
1370    }
1371
1372
1373    size_type
1374    size() const
1375    {
1376        return _size;
1377    }
1378
1379    bool
1380    zero() const
1381    {
1382        return data(0)->zero();
1383#if 0
1384        for (off_type i = 0; i < size(); ++i)
1385            if (!data(i)->zero())
1386                return false;
1387        return true;
1388#endif
1389    }
1390
1391    void
1392    prepare()
1393    {
1394        Info *info = this->info();
1395        size_type size = this->size();
1396
1397        for (off_type i = 0; i < size; ++i)
1398            data(i)->prepare(info);
1399
1400        info->cvec.resize(size);
1401        for (off_type i = 0; i < size; ++i)
1402            info->cvec[i] = data(i)->value();
1403    }
1404
1405    /**
1406     * Reset stat value to default
1407     */
1408    void
1409    reset()
1410    {
1411        Info *info = this->info();
1412        size_type size = this->size();
1413        for (off_type i = 0; i < size; ++i)
1414            data(i)->reset(info);
1415    }
1416
1417    bool
1418    check() const
1419    {
1420        return storage != NULL;
1421    }
1422};
1423
1424//////////////////////////////////////////////////////////////////////
1425//
1426// Non formula statistics
1427//
1428//////////////////////////////////////////////////////////////////////
1429
1430struct DistParams : public StorageParams
1431{
1432    const bool fancy;
1433
1434    /** The minimum value to track. */
1435    Counter min;
1436    /** The maximum value to track. */
1437    Counter max;
1438    /** The number of entries in each bucket. */
1439    Counter bucket_size;
1440    /** The number of buckets. Equal to (max-min)/bucket_size. */
1441    size_type buckets;
1442
1443    explicit DistParams(bool f) : fancy(f) {}
1444};
1445
1446/**
1447 * Templatized storage and interface for a distrbution stat.
1448 */
1449class DistStor
1450{
1451  public:
1452    /** The parameters for a distribution stat. */
1453    struct Params : public DistParams
1454    {
1455        Params() : DistParams(false) {}
1456    };
1457
1458  private:
1459    /** The minimum value to track. */
1460    Counter min_track;
1461    /** The maximum value to track. */
1462    Counter max_track;
1463    /** The number of entries in each bucket. */
1464    Counter bucket_size;
1465    /** The number of buckets. Equal to (max-min)/bucket_size. */
1466    size_type buckets;
1467
1468    /** The smallest value sampled. */
1469    Counter min_val;
1470    /** The largest value sampled. */
1471    Counter max_val;
1472    /** The number of values sampled less than min. */
1473    Counter underflow;
1474    /** The number of values sampled more than max. */
1475    Counter overflow;
1476    /** The current sum. */
1477    Counter sum;
1478    /** The sum of squares. */
1479    Counter squares;
1480    /** The number of samples. */
1481    Counter samples;
1482    /** Counter for each bucket. */
1483    VCounter cvec;
1484
1485  public:
1486    DistStor(Info *info)
1487        : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
1488    {
1489        reset(info);
1490    }
1491
1492    /**
1493     * Add a value to the distribution for the given number of times.
1494     * @param val The value to add.
1495     * @param number The number of times to add the value.
1496     */
1497    void
1498    sample(Counter val, int number)
1499    {
1500        if (val < min_track)
1501            underflow += number;
1502        else if (val > max_track)
1503            overflow += number;
1504        else {
1505            size_type index =
1506                (size_type)std::floor((val - min_track) / bucket_size);
1507            assert(index < size());
1508            cvec[index] += number;
1509        }
1510
1511        if (val < min_val)
1512            min_val = val;
1513
1514        if (val > max_val)
1515            max_val = val;
1516
1517        Counter sample = val * number;
1518        sum += sample;
1519        squares += sample * sample;
1520        samples += number;
1521    }
1522
1523    /**
1524     * Return the number of buckets in this distribution.
1525     * @return the number of buckets.
1526     */
1527    size_type size() const { return cvec.size(); }
1528
1529    /**
1530     * Returns true if any calls to sample have been made.
1531     * @return True if any values have been sampled.
1532     */
1533    bool
1534    zero() const
1535    {
1536        return samples == Counter();
1537    }
1538
1539    void
1540    prepare(Info *info, DistData &data)
1541    {
1542        const Params *params = safe_cast<const Params *>(info->storageParams);
1543
1544        data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
1545        data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
1546        data.underflow = underflow;
1547        data.overflow = overflow;
1548
1549        int buckets = params->buckets;
1550        data.cvec.resize(buckets);
1551        for (off_type i = 0; i < buckets; ++i)
1552            data.cvec[i] = cvec[i];
1553
1554        data.sum = sum;
1555        data.squares = squares;
1556        data.samples = samples;
1557    }
1558
1559    /**
1560     * Reset stat value to default
1561     */
1562    void
1563    reset(Info *info)
1564    {
1565        const Params *params = safe_cast<const Params *>(info->storageParams);
1566        min_track = params->min;
1567        max_track = params->max;
1568        bucket_size = params->bucket_size;
1569
1570        min_val = CounterLimits::max();
1571        max_val = CounterLimits::min();
1572        underflow = 0;
1573        overflow = 0;
1574
1575        size_type size = cvec.size();
1576        for (off_type i = 0; i < size; ++i)
1577            cvec[i] = Counter();
1578
1579        sum = Counter();
1580        squares = Counter();
1581        samples = Counter();
1582    }
1583};
1584
1585/**
1586 * Templatized storage and interface for a distribution that calculates mean
1587 * and variance.
1588 */
1589class FancyStor
1590{
1591  public:
1592    struct Params : public DistParams
1593    {
1594        Params() : DistParams(true) {}
1595    };
1596
1597  private:
1598    /** The current sum. */
1599    Counter sum;
1600    /** The sum of squares. */
1601    Counter squares;
1602    /** The number of samples. */
1603    Counter samples;
1604
1605  public:
1606    /**
1607     * Create and initialize this storage.
1608     */
1609    FancyStor(Info *info)
1610        : sum(Counter()), squares(Counter()), samples(Counter())
1611    { }
1612
1613    /**
1614     * Add a value the given number of times to this running average.
1615     * Update the running sum and sum of squares, increment the number of
1616     * values seen by the given number.
1617     * @param val The value to add.
1618     * @param number The number of times to add the value.
1619     */
1620    void
1621    sample(Counter val, int number)
1622    {
1623        Counter value = val * number;
1624        sum += value;
1625        squares += value * value;
1626        samples += number;
1627    }
1628
1629    /**
1630     * Return the number of entries in this stat, 1
1631     * @return 1.
1632     */
1633    size_type size() const { return 1; }
1634
1635    /**
1636     * Return true if no samples have been added.
1637     * @return True if no samples have been added.
1638     */
1639    bool zero() const { return samples == Counter(); }
1640
1641    void
1642    prepare(Info *info, DistData &data)
1643    {
1644        data.sum = sum;
1645        data.squares = squares;
1646        data.samples = samples;
1647    }
1648
1649    /**
1650     * Reset stat value to default
1651     */
1652    void
1653    reset(Info *info)
1654    {
1655        sum = Counter();
1656        squares = Counter();
1657        samples = Counter();
1658    }
1659};
1660
1661/**
1662 * Templatized storage for distribution that calculates per tick mean and
1663 * variance.
1664 */
1665class AvgFancy
1666{
1667  public:
1668    struct Params : public DistParams
1669    {
1670        Params() : DistParams(true) {}
1671    };
1672
1673  private:
1674    /** Current total. */
1675    Counter sum;
1676    /** Current sum of squares. */
1677    Counter squares;
1678
1679  public:
1680    /**
1681     * Create and initialize this storage.
1682     */
1683    AvgFancy(Info *info)
1684        : sum(Counter()), squares(Counter())
1685    {}
1686
1687    /**
1688     * Add a value to the distribution for the given number of times.
1689     * Update the running sum and sum of squares.
1690     * @param val The value to add.
1691     * @param number The number of times to add the value.
1692     */
1693    void
1694    sample(Counter val, int number)
1695    {
1696        Counter value = val * number;
1697        sum += value;
1698        squares += value * value;
1699    }
1700
1701    /**
1702     * Return the number of entries, in this case 1.
1703     * @return 1.
1704     */
1705    size_type size() const { return 1; }
1706
1707    /**
1708     * Return true if no samples have been added.
1709     * @return True if the sum is zero.
1710     */
1711    bool zero() const { return sum == Counter(); }
1712
1713    void
1714    prepare(Info *info, DistData &data)
1715    {
1716        data.sum = sum;
1717        data.squares = squares;
1718        data.samples = curTick;
1719    }
1720
1721    /**
1722     * Reset stat value to default
1723     */
1724    void
1725    reset(Info *info)
1726    {
1727        sum = Counter();
1728        squares = Counter();
1729    }
1730};
1731
1732/**
1733 * Implementation of a distribution stat. The type of distribution is
1734 * determined by the Storage template. @sa ScalarBase
1735 */
1736template <class Derived, class Stor>
1737class DistBase : public DataWrap<Derived, DistInfoProxy>
1738{
1739  public:
1740    typedef DistInfoProxy<Derived> Info;
1741    typedef Stor Storage;
1742    typedef typename Stor::Params Params;
1743
1744  protected:
1745    /** The storage for this stat. */
1746    char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
1747
1748  protected:
1749    /**
1750     * Retrieve the storage.
1751     * @return The storage object for this stat.
1752     */
1753    Storage *
1754    data()
1755    {
1756        return reinterpret_cast<Storage *>(storage);
1757    }
1758
1759    /**
1760     * Retrieve a const pointer to the storage.
1761     * @return A const pointer to the storage object for this stat.
1762     */
1763    const Storage *
1764    data() const
1765    {
1766        return reinterpret_cast<const Storage *>(storage);
1767    }
1768
1769    void
1770    doInit()
1771    {
1772        new (storage) Storage(this->info());
1773        this->setInit();
1774    }
1775
1776  public:
1777    DistBase() { }
1778
1779    /**
1780     * Add a value to the distribtion n times. Calls sample on the storage
1781     * class.
1782     * @param v The value to add.
1783     * @param n The number of times to add it, defaults to 1.
1784     */
1785    template <typename U>
1786    void sample(const U &v, int n = 1) { data()->sample(v, n); }
1787
1788    /**
1789     * Return the number of entries in this stat.
1790     * @return The number of entries.
1791     */
1792    size_type size() const { return data()->size(); }
1793    /**
1794     * Return true if no samples have been added.
1795     * @return True if there haven't been any samples.
1796     */
1797    bool zero() const { return data()->zero(); }
1798
1799    void
1800    prepare()
1801    {
1802        Info *info = this->info();
1803        data()->prepare(info, info->data);
1804    }
1805
1806    /**
1807     * Reset stat value to default
1808     */
1809    void
1810    reset()
1811    {
1812        data()->reset(this->info());
1813    }
1814};
1815
1816template <class Stat>
1817class DistProxy;
1818
1819template <class Derived, class Stor>
1820class VectorDistBase : public DataWrapVec<Derived, VectorDistInfoProxy>
1821{
1822  public:
1823    typedef VectorDistInfoProxy<Derived> Info;
1824    typedef Stor Storage;
1825    typedef typename Stor::Params Params;
1826    typedef DistProxy<Derived> Proxy;
1827    friend class DistProxy<Derived>;
1828    friend class DataWrapVec<Derived, VectorDistInfoProxy>;
1829
1830  protected:
1831    Storage *storage;
1832    size_type _size;
1833
1834  protected:
1835    Storage *
1836    data(off_type index)
1837    {
1838        return &storage[index];
1839    }
1840
1841    const Storage *
1842    data(off_type index) const
1843    {
1844        return &storage[index];
1845    }
1846
1847    void
1848    doInit(size_type s)
1849    {
1850        assert(s > 0 && "size must be positive!");
1851        assert(!storage && "already initialized");
1852        _size = s;
1853
1854        char *ptr = new char[_size * sizeof(Storage)];
1855        storage = reinterpret_cast<Storage *>(ptr);
1856
1857        Info *info = this->info();
1858        for (off_type i = 0; i < _size; ++i)
1859            new (&storage[i]) Storage(info);
1860
1861        this->setInit();
1862    }
1863
1864  public:
1865    VectorDistBase()
1866        : storage(NULL)
1867    {}
1868
1869    ~VectorDistBase()
1870    {
1871        if (!storage)
1872            return ;
1873
1874        for (off_type i = 0; i < _size; ++i)
1875            data(i)->~Storage();
1876        delete [] reinterpret_cast<char *>(storage);
1877    }
1878
1879    Proxy operator[](off_type index);
1880
1881    size_type
1882    size() const
1883    {
1884        return _size;
1885    }
1886
1887    bool
1888    zero() const
1889    {
1890        return false;
1891#if 0
1892        for (off_type i = 0; i < size(); ++i)
1893            if (!data(i)->zero())
1894                return false;
1895        return true;
1896#endif
1897    }
1898
1899    void
1900    prepare()
1901    {
1902        Info *info = this->info();
1903        size_type size = this->size();
1904        info->data.resize(size);
1905        for (off_type i = 0; i < size; ++i)
1906            data(i)->prepare(info, info->data[i]);
1907    }
1908
1909    bool
1910    check() const
1911    {
1912        return storage != NULL;
1913    }
1914};
1915
1916template <class Stat>
1917class DistProxy
1918{
1919  private:
1920    Stat *stat;
1921    off_type index;
1922
1923  protected:
1924    typename Stat::Storage *data() { return stat->data(index); }
1925    const typename Stat::Storage *data() const { return stat->data(index); }
1926
1927  public:
1928    DistProxy(Stat *s, off_type i)
1929        : stat(s), index(i)
1930    {}
1931
1932    DistProxy(const DistProxy &sp)
1933        : stat(sp.stat), index(sp.index)
1934    {}
1935
1936    const DistProxy &
1937    operator=(const DistProxy &sp)
1938    {
1939        stat = sp.stat;
1940        index = sp.index;
1941        return *this;
1942    }
1943
1944  public:
1945    template <typename U>
1946    void
1947    sample(const U &v, int n = 1)
1948    {
1949        data()->sample(v, n);
1950    }
1951
1952    size_type
1953    size() const
1954    {
1955        return 1;
1956    }
1957
1958    bool
1959    zero() const
1960    {
1961        return data()->zero();
1962    }
1963
1964    /**
1965     * Proxy has no state.  Nothing to reset.
1966     */
1967    void reset() { }
1968};
1969
1970template <class Derived, class Stor>
1971inline typename VectorDistBase<Derived, Stor>::Proxy
1972VectorDistBase<Derived, Stor>::operator[](off_type index)
1973{
1974    assert (index >= 0 && index < size());
1975    typedef typename VectorDistBase<Derived, Stor>::Proxy Proxy;
1976    return Proxy(this, index);
1977}
1978
1979#if 0
1980template <class Storage>
1981Result
1982VectorDistBase<Storage>::total(off_type index) const
1983{
1984    Result total = 0.0;
1985    for (off_type i = 0; i < x_size(); ++i)
1986        total += data(i)->result();
1987}
1988#endif
1989
1990//////////////////////////////////////////////////////////////////////
1991//
1992//  Formula Details
1993//
1994//////////////////////////////////////////////////////////////////////
1995
1996/**
1997 * Base class for formula statistic node. These nodes are used to build a tree
1998 * that represents the formula.
1999 */
2000class Node : public RefCounted
2001{
2002  public:
2003    /**
2004     * Return the number of nodes in the subtree starting at this node.
2005     * @return the number of nodes in this subtree.
2006     */
2007    virtual size_type size() const = 0;
2008    /**
2009     * Return the result vector of this subtree.
2010     * @return The result vector of this subtree.
2011     */
2012    virtual const VResult &result() const = 0;
2013    /**
2014     * Return the total of the result vector.
2015     * @return The total of the result vector.
2016     */
2017    virtual Result total() const = 0;
2018
2019    /**
2020     *
2021     */
2022    virtual std::string str() const = 0;
2023};
2024
2025/** Reference counting pointer to a function Node. */
2026typedef RefCountingPtr<Node> NodePtr;
2027
2028class ScalarStatNode : public Node
2029{
2030  private:
2031    const ScalarInfo *data;
2032    mutable VResult vresult;
2033
2034  public:
2035    ScalarStatNode(const ScalarInfo *d) : data(d), vresult(1) {}
2036
2037    const VResult &
2038    result() const
2039    {
2040        vresult[0] = data->result();
2041        return vresult;
2042    }
2043
2044    Result total() const { return data->result(); };
2045
2046    size_type size() const { return 1; }
2047
2048    /**
2049     *
2050     */
2051    std::string str() const { return data->name; }
2052};
2053
2054template <class Stat>
2055class ScalarProxyNode : public Node
2056{
2057  private:
2058    const ScalarProxy<Stat> proxy;
2059    mutable VResult vresult;
2060
2061  public:
2062    ScalarProxyNode(const ScalarProxy<Stat> &p)
2063        : proxy(p), vresult(1)
2064    { }
2065
2066    const VResult &
2067    result() const
2068    {
2069        vresult[0] = proxy.result();
2070        return vresult;
2071    }
2072
2073    Result
2074    total() const
2075    {
2076        return proxy.result();
2077    }
2078
2079    size_type
2080    size() const
2081    {
2082        return 1;
2083    }
2084
2085    /**
2086     *
2087     */
2088    std::string
2089    str() const
2090    {
2091        return proxy.str();
2092    }
2093};
2094
2095class VectorStatNode : public Node
2096{
2097  private:
2098    const VectorInfo *data;
2099
2100  public:
2101    VectorStatNode(const VectorInfo *d) : data(d) { }
2102    const VResult &result() const { return data->result(); }
2103    Result total() const { return data->total(); };
2104
2105    size_type size() const { return data->size(); }
2106
2107    std::string str() const { return data->name; }
2108};
2109
2110template <class T>
2111class ConstNode : public Node
2112{
2113  private:
2114    VResult vresult;
2115
2116  public:
2117    ConstNode(T s) : vresult(1, (Result)s) {}
2118    const VResult &result() const { return vresult; }
2119    Result total() const { return vresult[0]; };
2120    size_type size() const { return 1; }
2121    std::string str() const { return to_string(vresult[0]); }
2122};
2123
2124template <class T>
2125class ConstVectorNode : public Node
2126{
2127  private:
2128    VResult vresult;
2129
2130  public:
2131    ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
2132    const VResult &result() const { return vresult; }
2133
2134    Result
2135    total() const
2136    {
2137        size_type size = this->size();
2138        Result tmp = 0;
2139        for (off_type i = 0; i < size; i++)
2140            tmp += vresult[i];
2141        return tmp;
2142    }
2143
2144    size_type size() const { return vresult.size(); }
2145    std::string
2146    str() const
2147    {
2148        size_type size = this->size();
2149        std::string tmp = "(";
2150        for (off_type i = 0; i < size; i++)
2151            tmp += csprintf("%s ",to_string(vresult[i]));
2152        tmp += ")";
2153        return tmp;
2154    }
2155};
2156
2157template <class Op>
2158struct OpString;
2159
2160template<>
2161struct OpString<std::plus<Result> >
2162{
2163    static std::string str() { return "+"; }
2164};
2165
2166template<>
2167struct OpString<std::minus<Result> >
2168{
2169    static std::string str() { return "-"; }
2170};
2171
2172template<>
2173struct OpString<std::multiplies<Result> >
2174{
2175    static std::string str() { return "*"; }
2176};
2177
2178template<>
2179struct OpString<std::divides<Result> >
2180{
2181    static std::string str() { return "/"; }
2182};
2183
2184template<>
2185struct OpString<std::modulus<Result> >
2186{
2187    static std::string str() { return "%"; }
2188};
2189
2190template<>
2191struct OpString<std::negate<Result> >
2192{
2193    static std::string str() { return "-"; }
2194};
2195
2196template <class Op>
2197class UnaryNode : public Node
2198{
2199  public:
2200    NodePtr l;
2201    mutable VResult vresult;
2202
2203  public:
2204    UnaryNode(NodePtr &p) : l(p) {}
2205
2206    const VResult &
2207    result() const
2208    {
2209        const VResult &lvec = l->result();
2210        size_type size = lvec.size();
2211
2212        assert(size > 0);
2213
2214        vresult.resize(size);
2215        Op op;
2216        for (off_type i = 0; i < size; ++i)
2217            vresult[i] = op(lvec[i]);
2218
2219        return vresult;
2220    }
2221
2222    Result
2223    total() const
2224    {
2225        const VResult &vec = this->result();
2226        Result total = 0.0;
2227        for (off_type i = 0; i < size(); i++)
2228            total += vec[i];
2229        return total;
2230    }
2231
2232    size_type size() const { return l->size(); }
2233
2234    std::string
2235    str() const
2236    {
2237        return OpString<Op>::str() + l->str();
2238    }
2239};
2240
2241template <class Op>
2242class BinaryNode : public Node
2243{
2244  public:
2245    NodePtr l;
2246    NodePtr r;
2247    mutable VResult vresult;
2248
2249  public:
2250    BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
2251
2252    const VResult &
2253    result() const
2254    {
2255        Op op;
2256        const VResult &lvec = l->result();
2257        const VResult &rvec = r->result();
2258
2259        assert(lvec.size() > 0 && rvec.size() > 0);
2260
2261        if (lvec.size() == 1 && rvec.size() == 1) {
2262            vresult.resize(1);
2263            vresult[0] = op(lvec[0], rvec[0]);
2264        } else if (lvec.size() == 1) {
2265            size_type size = rvec.size();
2266            vresult.resize(size);
2267            for (off_type i = 0; i < size; ++i)
2268                vresult[i] = op(lvec[0], rvec[i]);
2269        } else if (rvec.size() == 1) {
2270            size_type size = lvec.size();
2271            vresult.resize(size);
2272            for (off_type i = 0; i < size; ++i)
2273                vresult[i] = op(lvec[i], rvec[0]);
2274        } else if (rvec.size() == lvec.size()) {
2275            size_type size = rvec.size();
2276            vresult.resize(size);
2277            for (off_type i = 0; i < size; ++i)
2278                vresult[i] = op(lvec[i], rvec[i]);
2279        }
2280
2281        return vresult;
2282    }
2283
2284    Result
2285    total() const
2286    {
2287        const VResult &vec = this->result();
2288        Result total = 0.0;
2289        for (off_type i = 0; i < size(); i++)
2290            total += vec[i];
2291        return total;
2292    }
2293
2294    size_type
2295    size() const
2296    {
2297        size_type ls = l->size();
2298        size_type rs = r->size();
2299        if (ls == 1) {
2300            return rs;
2301        } else if (rs == 1) {
2302            return ls;
2303        } else {
2304            assert(ls == rs && "Node vector sizes are not equal");
2305            return ls;
2306        }
2307    }
2308
2309    std::string
2310    str() const
2311    {
2312        return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
2313    }
2314};
2315
2316template <class Op>
2317class SumNode : public Node
2318{
2319  public:
2320    NodePtr l;
2321    mutable VResult vresult;
2322
2323  public:
2324    SumNode(NodePtr &p) : l(p), vresult(1) {}
2325
2326    const VResult &
2327    result() const
2328    {
2329        const VResult &lvec = l->result();
2330        size_type size = lvec.size();
2331        assert(size > 0);
2332
2333        vresult[0] = 0.0;
2334
2335        Op op;
2336        for (off_type i = 0; i < size; ++i)
2337            vresult[0] = op(vresult[0], lvec[i]);
2338
2339        return vresult;
2340    }
2341
2342    Result
2343    total() const
2344    {
2345        const VResult &lvec = l->result();
2346        size_type size = lvec.size();
2347        assert(size > 0);
2348
2349        Result vresult = 0.0;
2350
2351        Op op;
2352        for (off_type i = 0; i < size; ++i)
2353            vresult = op(vresult, lvec[i]);
2354
2355        return vresult;
2356    }
2357
2358    size_type size() const { return 1; }
2359
2360    std::string
2361    str() const
2362    {
2363        return csprintf("total(%s)", l->str());
2364    }
2365};
2366
2367
2368//////////////////////////////////////////////////////////////////////
2369//
2370// Visible Statistics Types
2371//
2372//////////////////////////////////////////////////////////////////////
2373/**
2374 * @defgroup VisibleStats "Statistic Types"
2375 * These are the statistics that are used in the simulator.
2376 * @{
2377 */
2378
2379/**
2380 * This is a simple scalar statistic, like a counter.
2381 * @sa Stat, ScalarBase, StatStor
2382 */
2383class Scalar : public ScalarBase<Scalar, StatStor>
2384{
2385  public:
2386    using ScalarBase<Scalar, StatStor>::operator=;
2387};
2388
2389/**
2390 * A stat that calculates the per tick average of a value.
2391 * @sa Stat, ScalarBase, AvgStor
2392 */
2393class Average : public ScalarBase<Average, AvgStor>
2394{
2395  public:
2396    using ScalarBase<Average, AvgStor>::operator=;
2397};
2398
2399class Value : public ValueBase<Value>
2400{
2401};
2402
2403/**
2404 * A vector of scalar stats.
2405 * @sa Stat, VectorBase, StatStor
2406 */
2407class Vector : public VectorBase<Vector, StatStor>
2408{
2409};
2410
2411/**
2412 * A vector of Average stats.
2413 * @sa Stat, VectorBase, AvgStor
2414 */
2415class AverageVector : public VectorBase<AverageVector, AvgStor>
2416{
2417};
2418
2419/**
2420 * A 2-Dimensional vecto of scalar stats.
2421 * @sa Stat, Vector2dBase, StatStor
2422 */
2423class Vector2d : public Vector2dBase<Vector2d, StatStor>
2424{
2425};
2426
2427/**
2428 * A simple distribution stat.
2429 * @sa Stat, DistBase, DistStor
2430 */
2431class Distribution : public DistBase<Distribution, DistStor>
2432{
2433  public:
2434    /**
2435     * Set the parameters of this distribution. @sa DistStor::Params
2436     * @param min The minimum value of the distribution.
2437     * @param max The maximum value of the distribution.
2438     * @param bkt The number of values in each bucket.
2439     * @return A reference to this distribution.
2440     */
2441    Distribution &
2442    init(Counter min, Counter max, Counter bkt)
2443    {
2444        DistStor::Params *params = new DistStor::Params;
2445        params->min = min;
2446        params->max = max;
2447        params->bucket_size = bkt;
2448        params->buckets = (size_type)rint((max - min) / bkt + 1.0);
2449        this->setParams(params);
2450        this->doInit();
2451        return this->self();
2452    }
2453};
2454
2455/**
2456 * Calculates the mean and variance of all the samples.
2457 * @sa Stat, DistBase, FancyStor
2458 */
2459class StandardDeviation : public DistBase<StandardDeviation, FancyStor>
2460{
2461  public:
2462    /**
2463     * Construct and initialize this distribution.
2464     */
2465    StandardDeviation()
2466    {
2467        this->doInit();
2468    }
2469};
2470
2471/**
2472 * Calculates the per tick mean and variance of the samples.
2473 * @sa Stat, DistBase, AvgFancy
2474 */
2475class AverageDeviation : public DistBase<AverageDeviation, AvgFancy>
2476{
2477  public:
2478    /**
2479     * Construct and initialize this distribution.
2480     */
2481    AverageDeviation()
2482    {
2483        this->doInit();
2484    }
2485};
2486
2487/**
2488 * A vector of distributions.
2489 * @sa Stat, VectorDistBase, DistStor
2490 */
2491class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
2492{
2493  public:
2494    /**
2495     * Initialize storage and parameters for this distribution.
2496     * @param size The size of the vector (the number of distributions).
2497     * @param min The minimum value of the distribution.
2498     * @param max The maximum value of the distribution.
2499     * @param bkt The number of values in each bucket.
2500     * @return A reference to this distribution.
2501     */
2502    VectorDistribution &
2503    init(size_type size, Counter min, Counter max, Counter bkt)
2504    {
2505        DistStor::Params *params = new DistStor::Params;
2506        params->min = min;
2507        params->max = max;
2508        params->bucket_size = bkt;
2509        params->buckets = (size_type)rint((max - min) / bkt + 1.0);
2510        this->setParams(params);
2511        this->doInit(size);
2512        return this->self();
2513    }
2514};
2515
2516/**
2517 * This is a vector of StandardDeviation stats.
2518 * @sa Stat, VectorDistBase, FancyStor
2519 */
2520class VectorStandardDeviation
2521    : public VectorDistBase<VectorStandardDeviation, FancyStor>
2522{
2523  public:
2524    /**
2525     * Initialize storage for this distribution.
2526     * @param size The size of the vector.
2527     * @return A reference to this distribution.
2528     */
2529    VectorStandardDeviation &
2530    init(size_type size)
2531    {
2532        this->doInit(size);
2533        return this->self();
2534    }
2535};
2536
2537/**
2538 * This is a vector of AverageDeviation stats.
2539 * @sa Stat, VectorDistBase, AvgFancy
2540 */
2541class VectorAverageDeviation
2542    : public VectorDistBase<VectorAverageDeviation, AvgFancy>
2543{
2544  public:
2545    /**
2546     * Initialize storage for this distribution.
2547     * @param size The size of the vector.
2548     * @return A reference to this distribution.
2549     */
2550    VectorAverageDeviation &
2551    init(size_type size)
2552    {
2553        this->doInit(size);
2554        return this->self();
2555    }
2556};
2557
2558class FormulaInfo : public VectorInfo
2559{
2560  public:
2561    virtual std::string str() const = 0;
2562};
2563
2564template <class Stat>
2565class FormulaInfoProxy : public InfoProxy<Stat, FormulaInfo>
2566{
2567  protected:
2568    mutable VResult vec;
2569    mutable VCounter cvec;
2570
2571  public:
2572    FormulaInfoProxy(Stat &stat) : InfoProxy<Stat, FormulaInfo>(stat) {}
2573
2574    size_type size() const { return this->s.size(); }
2575
2576    const VResult &
2577    result() const
2578    {
2579        this->s.result(vec);
2580        return vec;
2581    }
2582    Result total() const { return this->s.total(); }
2583    VCounter &value() const { return cvec; }
2584
2585    std::string str() const { return this->s.str(); }
2586};
2587
2588class Temp;
2589/**
2590 * A formula for statistics that is calculated when printed. A formula is
2591 * stored as a tree of Nodes that represent the equation to calculate.
2592 * @sa Stat, ScalarStat, VectorStat, Node, Temp
2593 */
2594class Formula : public DataWrapVec<Formula, FormulaInfoProxy>
2595{
2596  protected:
2597    /** The root of the tree which represents the Formula */
2598    NodePtr root;
2599    friend class Temp;
2600
2601  public:
2602    /**
2603     * Create and initialize thie formula, and register it with the database.
2604     */
2605    Formula();
2606
2607    /**
2608     * Create a formula with the given root node, register it with the
2609     * database.
2610     * @param r The root of the expression tree.
2611     */
2612    Formula(Temp r);
2613
2614    /**
2615     * Set an unitialized Formula to the given root.
2616     * @param r The root of the expression tree.
2617     * @return a reference to this formula.
2618     */
2619    const Formula &operator=(Temp r);
2620
2621    /**
2622     * Add the given tree to the existing one.
2623     * @param r The root of the expression tree.
2624     * @return a reference to this formula.
2625     */
2626    const Formula &operator+=(Temp r);
2627    /**
2628     * Return the result of the Fomula in a vector.  If there were no Vector
2629     * components to the Formula, then the vector is size 1.  If there were,
2630     * like x/y with x being a vector of size 3, then the result returned will
2631     * be x[0]/y, x[1]/y, x[2]/y, respectively.
2632     * @return The result vector.
2633     */
2634    void result(VResult &vec) const;
2635
2636    /**
2637     * Return the total Formula result.  If there is a Vector
2638     * component to this Formula, then this is the result of the
2639     * Formula if the formula is applied after summing all the
2640     * components of the Vector.  For example, if Formula is x/y where
2641     * x is size 3, then total() will return (x[1]+x[2]+x[3])/y.  If
2642     * there is no Vector component, total() returns the same value as
2643     * the first entry in the VResult val() returns.
2644     * @return The total of the result vector.
2645     */
2646    Result total() const;
2647
2648    /**
2649     * Return the number of elements in the tree.
2650     */
2651    size_type size() const;
2652
2653    void prepare() { }
2654
2655    /**
2656     * Formulas don't need to be reset
2657     */
2658    void reset();
2659
2660    /**
2661     *
2662     */
2663    bool zero() const;
2664
2665    std::string str() const;
2666};
2667
2668class FormulaNode : public Node
2669{
2670  private:
2671    const Formula &formula;
2672    mutable VResult vec;
2673
2674  public:
2675    FormulaNode(const Formula &f) : formula(f) {}
2676
2677    size_type size() const { return formula.size(); }
2678    const VResult &result() const { formula.result(vec); return vec; }
2679    Result total() const { return formula.total(); }
2680
2681    std::string str() const { return formula.str(); }
2682};
2683
2684/**
2685 * Helper class to construct formula node trees.
2686 */
2687class Temp
2688{
2689  protected:
2690    /**
2691     * Pointer to a Node object.
2692     */
2693    NodePtr node;
2694
2695  public:
2696    /**
2697     * Copy the given pointer to this class.
2698     * @param n A pointer to a Node object to copy.
2699     */
2700    Temp(NodePtr n) : node(n) { }
2701
2702    /**
2703     * Return the node pointer.
2704     * @return the node pointer.
2705     */
2706    operator NodePtr&() { return node; }
2707
2708  public:
2709    /**
2710     * Create a new ScalarStatNode.
2711     * @param s The ScalarStat to place in a node.
2712     */
2713    Temp(const Scalar &s)
2714        : node(new ScalarStatNode(s.info()))
2715    { }
2716
2717    /**
2718     * Create a new ScalarStatNode.
2719     * @param s The ScalarStat to place in a node.
2720     */
2721    Temp(const Value &s)
2722        : node(new ScalarStatNode(s.info()))
2723    { }
2724
2725    /**
2726     * Create a new ScalarStatNode.
2727     * @param s The ScalarStat to place in a node.
2728     */
2729    Temp(const Average &s)
2730        : node(new ScalarStatNode(s.info()))
2731    { }
2732
2733    /**
2734     * Create a new VectorStatNode.
2735     * @param s The VectorStat to place in a node.
2736     */
2737    Temp(const Vector &s)
2738        : node(new VectorStatNode(s.info()))
2739    { }
2740
2741    /**
2742     *
2743     */
2744    Temp(const Formula &f)
2745        : node(new FormulaNode(f))
2746    { }
2747
2748    /**
2749     * Create a new ScalarProxyNode.
2750     * @param p The ScalarProxy to place in a node.
2751     */
2752    template <class Stat>
2753    Temp(const ScalarProxy<Stat> &p)
2754        : node(new ScalarProxyNode<Stat>(p))
2755    { }
2756
2757    /**
2758     * Create a ConstNode
2759     * @param value The value of the const node.
2760     */
2761    Temp(signed char value)
2762        : node(new ConstNode<signed char>(value))
2763    { }
2764
2765    /**
2766     * Create a ConstNode
2767     * @param value The value of the const node.
2768     */
2769    Temp(unsigned char value)
2770        : node(new ConstNode<unsigned char>(value))
2771    { }
2772
2773    /**
2774     * Create a ConstNode
2775     * @param value The value of the const node.
2776     */
2777    Temp(signed short value)
2778        : node(new ConstNode<signed short>(value))
2779    { }
2780
2781    /**
2782     * Create a ConstNode
2783     * @param value The value of the const node.
2784     */
2785    Temp(unsigned short value)
2786        : node(new ConstNode<unsigned short>(value))
2787    { }
2788
2789    /**
2790     * Create a ConstNode
2791     * @param value The value of the const node.
2792     */
2793    Temp(signed int value)
2794        : node(new ConstNode<signed int>(value))
2795    { }
2796
2797    /**
2798     * Create a ConstNode
2799     * @param value The value of the const node.
2800     */
2801    Temp(unsigned int value)
2802        : node(new ConstNode<unsigned int>(value))
2803    { }
2804
2805    /**
2806     * Create a ConstNode
2807     * @param value The value of the const node.
2808     */
2809    Temp(signed long value)
2810        : node(new ConstNode<signed long>(value))
2811    { }
2812
2813    /**
2814     * Create a ConstNode
2815     * @param value The value of the const node.
2816     */
2817    Temp(unsigned long value)
2818        : node(new ConstNode<unsigned long>(value))
2819    { }
2820
2821    /**
2822     * Create a ConstNode
2823     * @param value The value of the const node.
2824     */
2825    Temp(signed long long value)
2826        : node(new ConstNode<signed long long>(value))
2827    { }
2828
2829    /**
2830     * Create a ConstNode
2831     * @param value The value of the const node.
2832     */
2833    Temp(unsigned long long value)
2834        : node(new ConstNode<unsigned long long>(value))
2835    { }
2836
2837    /**
2838     * Create a ConstNode
2839     * @param value The value of the const node.
2840     */
2841    Temp(float value)
2842        : node(new ConstNode<float>(value))
2843    { }
2844
2845    /**
2846     * Create a ConstNode
2847     * @param value The value of the const node.
2848     */
2849    Temp(double value)
2850        : node(new ConstNode<double>(value))
2851    { }
2852};
2853
2854
2855/**
2856 * @}
2857 */
2858
2859inline Temp
2860operator+(Temp l, Temp r)
2861{
2862    return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
2863}
2864
2865inline Temp
2866operator-(Temp l, Temp r)
2867{
2868    return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
2869}
2870
2871inline Temp
2872operator*(Temp l, Temp r)
2873{
2874    return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
2875}
2876
2877inline Temp
2878operator/(Temp l, Temp r)
2879{
2880    return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
2881}
2882
2883inline Temp
2884operator-(Temp l)
2885{
2886    return NodePtr(new UnaryNode<std::negate<Result> >(l));
2887}
2888
2889template <typename T>
2890inline Temp
2891constant(T val)
2892{
2893    return NodePtr(new ConstNode<T>(val));
2894}
2895
2896template <typename T>
2897inline Temp
2898constantVector(T val)
2899{
2900    return NodePtr(new ConstVectorNode<T>(val));
2901}
2902
2903inline Temp
2904sum(Temp val)
2905{
2906    return NodePtr(new SumNode<std::plus<Result> >(val));
2907}
2908
2909/**
2910 * Enable the statistics package.  Before the statistics package is
2911 * enabled, all statistics must be created and initialized and once
2912 * the package is enabled, no more statistics can be created.
2913 */
2914void enable();
2915
2916/**
2917 * Prepare all stats for data access.  This must be done before
2918 * dumping and serialization.
2919 */
2920void prepare();
2921
2922/**
2923 * Dump all statistics data to the registered outputs
2924 */
2925void dump();
2926
2927/**
2928 * Reset all statistics to the base state
2929 */
2930void reset();
2931/**
2932 * Register a callback that should be called whenever statistics are
2933 * reset
2934 */
2935void registerResetCallback(Callback *cb);
2936
2937std::list<Info *> &statsList();
2938
2939/* namespace Stats */ }
2940
2941#endif // __BASE_STATISTICS_HH__
2942