X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=base%2Fstatistics.cc;h=eaefd5f15a69ed0f754adfd11d8e075e1dc33e97;hb=5aa71721193c49016ffa69934b44ce38672e4eed;hp=69b663dbb9d403033eaa07ec802f3412ec605298;hpb=790d1da2fac71aeda1e3df16d9136ee209b51392;p=gem5.git diff --git a/base/statistics.cc b/base/statistics.cc index 69b663dbb..eaefd5f15 100644 --- a/base/statistics.cc +++ b/base/statistics.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 The Regents of The University of Michigan + * Copyright (c) 2003-2005 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,7 +27,7 @@ */ #include -#include +#include #include #include #include @@ -35,297 +35,81 @@ #include "base/callback.hh" #include "base/cprintf.hh" +#include "base/hostinfo.hh" #include "base/misc.hh" #include "base/statistics.hh" #include "base/str.hh" -#include "sim/universe.hh" - -#ifdef __M5_NAN -float -__nan() -{ - union { - uint32_t ui; - float f; - } nan; - - nan.ui = 0x7fc00000; - return nan.f; -} -#endif - -#ifdef STAT_DEBUG -static int total_stats = 0; -#endif +#include "base/time.hh" +#include "base/trace.hh" +#include "base/stats/statdb.hh" +#include "config/stats_binning.hh" using namespace std; -// This is a hack to get this parameter from the old stats package. -namespace Statistics { -bool PrintDescriptions = true; - -namespace Detail { -/** - * Struct to contain a name and description of statistic subfield. - */ -struct SubData -{ - /** Subfield name. */ - string name; - /** Subfield desc. */ - string desc; -}; - -/** - * Struct to contain print data of a Stat. - */ -struct StatData -{ - /** - * Create this struct. - */ - StatData(); - /** - * Destructor. - */ - ~StatData(); - - /** True if the stat has been initialized. */ - bool init; - /** True if the stat should be printed. */ - bool print; - /** The name of the stat. */ - string name; - /** Names and descriptions of subfields. */ - vector *subdata; - /** The description of the stat. */ - string desc; - /** The display precision. */ - int precision; - /** The formatting flags. */ - FormatFlags flags; - /** A pointer to a prerequisite Stat. */ - const Stat *prereq; -}; +namespace Stats { -StatData::StatData() - : init(false), print(false), subdata(NULL), precision(-1), flags(none), - prereq(NULL) +StatData * +DataAccess::find() const { + return Database::find(const_cast((const void *)this)); } -StatData::~StatData() +const StatData * +getStatData(const void *stat) { - if (subdata) - delete subdata; + return Database::find(const_cast(stat)); } -class Database -{ - private: - Database(const Database &) {} - - private: - typedef list list_t; - typedef map map_t; - - list bins; - map bin_names; - list_t binnedStats; - - list_t allStats; - list_t printStats; - map_t statMap; - - public: - Database(); - ~Database(); - - void dump(ostream &stream); - - StatData *find(const Stat *stat); - void check(); - void reset(); - void regStat(Stat *stat); - StatData *print(Stat *stat); - void regBin(GenBin *bin, std::string name); -}; - -Database::Database() -{} - -Database::~Database() -{} - void -Database::dump(ostream &stream) +DataAccess::map(StatData *data) { -#ifndef FS_MEASURE - list_t::iterator i = printStats.begin(); - list_t::iterator end = printStats.end(); - while (i != end) { - Stat *stat = *i; - if (stat->binned()) - binnedStats.push_back(stat); - ++i; - } -#endif //FS_MEASURE - - list::iterator j = bins.begin(); - list::iterator bins_end=bins.end(); - - if (!bins.empty()) { - ccprintf(stream, "PRINTING BINNED STATS\n"); - while (j != bins_end) { - (*j)->activate(); - map::const_iterator iter; - iter = bin_names.find(*j); - if (iter == bin_names.end()) - panic("a binned stat not found in names map!"); - ccprintf(stream,"---%s Bin------------\n", (*iter).second); - -#ifdef FS_MEASURE - list_t::iterator i = printStats.begin(); - list_t::iterator end = printStats.end(); -#else - list_t::iterator i = binnedStats.begin(); - list_t::iterator end = binnedStats.end(); -#endif - while (i != end) { - Stat *stat = *i; - if (stat->dodisplay()) - stat->display(stream); - ++i; - } - ++j; - ccprintf(stream, "---------------------------------\n"); - } -#ifndef FS_MEASURE - ccprintf(stream, "**************ALL STATS************\n"); -#endif - } - -/** - * get bin totals working, then print the stat here (as total), even if - * its' binned. (this is only for the case you selectively bin a few stats - */ -#ifndef FS_MEASURE - list_t::iterator k = printStats.begin(); - list_t::iterator endprint = printStats.end(); - while (k != endprint) { - Stat *stat = *k; - if (stat->dodisplay() && !stat->binned()) - stat->display(stream); - ++k; - } -#endif + Database::regStat(this, data); } StatData * -Database::find(const Stat *stat) +DataAccess::statData() { - map_t::const_iterator i = statMap.find(stat); - - if (i == statMap.end()) - return NULL; - - return (*i).second; + StatData *ptr = find(); + assert(ptr); + return ptr; } -void -Database::check() +const StatData * +DataAccess::statData() const { - list_t::iterator i = allStats.begin(); - list_t::iterator end = allStats.end(); - - while (i != end) { - Stat *stat = *i; - StatData *data = find(stat); - if (!data || !data->init) { -#ifdef STAT_DEBUG - cprintf("this is stat number %d\n",(*i)->number); -#endif - panic("Not all stats have been initialized"); - } - - if (data->print) { - if (data->name.empty()) - panic("all printable stats must be named"); - - list_t::iterator j = printStats.insert(printStats.end(), *i); - inplace_merge(printStats.begin(), j, - printStats.end(), Stat::less); - } - - ++i; - } + const StatData *ptr = find(); + assert(ptr); + return ptr; } void -Database::reset() +DataAccess::setInit() { - list_t::iterator i = allStats.begin(); - list_t::iterator end = allStats.end(); - while (i != end) { - Stat *stat = *i; - stat->reset(); - ++i; - } - - MainBin *orig = MainBin::current(); - - list::iterator bi = bins.begin(); - list::iterator be = bins.end(); - while (bi != be) { - GenBin *bin = *bi; - bin->activate(); - - i = allStats.begin(); - while (i != end) { - Stat *stat = *i; - stat->reset(); - ++i; - } - ++bi; - } - - orig->activate(); + statData()->flags |= init; } void -Database::regStat(Stat *stat) +DataAccess::setPrint() { - if (statMap.find(stat) != statMap.end()) - panic("shouldn't register stat twice!"); - - allStats.push_back(stat); - - StatData *data = new StatData; - bool success = (statMap.insert(make_pair(stat, data))).second; - assert(statMap.find(stat) != statMap.end()); - assert(success && "this should never fail"); + Database::regPrint(this); } -void -Database::regBin(GenBin *bin, std::string name) +StatData::StatData() + : flags(none), precision(-1), prereq(0) { - if (bin_names.find(bin) != bin_names.end()) - panic("shouldn't register bin twice"); - - bins.push_back(bin); - - bool success = (bin_names.insert(make_pair(bin,name))).second; - assert(bin_names.find(bin) != bin_names.end()); - assert(success && "this should not fail"); + static int count = 0; + id = count++; +} - cprintf("registering %s\n", name); +StatData::~StatData() +{ } bool -Stat::less(Stat *stat1, Stat *stat2) +StatData::less(StatData *stat1, StatData *stat2) { - const string &name1 = stat1->myname(); - const string &name2 = stat2->myname(); + const string &name1 = stat1->name; + const string &name2 = stat2->name; vector v1; vector v2; @@ -347,623 +131,227 @@ Stat::less(Stat *stat1, Stat *stat2) return false; } -StatData * -Database::print(Stat *stat) -{ - StatData *data = find(stat); - assert(data); - - data->print = true; - - return data; -} - -Database & -StatDB() -{ - static Database db; - return db; -} - -Stat::Stat(bool reg) +bool +StatData::baseCheck() const { -#if 0 - // This assert can help you find that pesky stat. - assert(this != (void *)0xbffff5c0); + if (!(flags & init)) { +#ifdef DEBUG + cprintf("this is stat number %d\n", id); #endif + panic("Not all stats have been initialized"); + return false; + } - if (reg) - StatDB().regStat(this); + if ((flags & print) && name.empty()) { + panic("all printable stats must be named"); + return false; + } -#ifdef STAT_DEBUG - number = ++total_stats; - cprintf("I'm stat number %d\n",number); -#endif + return true; } -void -Stat::setInit() -{ mydata()->init = true; } - -StatData * -Stat::mydata() -{ - StatData *data = StatDB().find(this); - assert(data); - - return data; -} -const StatData * -Stat::mydata() const +void +FormulaBase::result(VResult &vec) const { - StatData *data = StatDB().find(this); - assert(data); - - return data; + if (root) + vec = root->result(); } -const SubData * -Stat::mysubdata(int index) const +Result +FormulaBase::total() const { - assert(index >= 0); - if (index >= size()) - return NULL; - - const StatData *data = this->mydata(); - if (!data->subdata || data->subdata->size() <= index) - return NULL; - - return &(*data->subdata)[index]; + return root ? root->total() : 0.0; } -SubData * -Stat::mysubdata_create(int index) +size_t +FormulaBase::size() const { - int size = this->size(); - assert(index >= 0 && (size == 0 || size > 0 && index < size)); - - StatData *data = this->mydata(); - if (!data->subdata) { - if (!data->subdata) { - if (size == 0) - size = index + 1; - - data->subdata = new vector(size); - } - } else if (data->subdata->size() <= index) - data->subdata->resize(index + 1); - - SubData *sd = &(*data->subdata)[index]; - assert(sd); - - return sd; + if (!root) + return 0; + else + return root->size(); } -string -Stat::myname() const -{ return mydata()->name; } - -string -Stat::mysubname(int index) const +bool +FormulaBase::binned() const { - const SubData *sd = mysubdata(index); - return sd ? sd->name : ""; + return root && root->binned(); } -string -Stat::mydesc() const -{ return mydata()->desc; } - -string -Stat::mysubdesc(int index) const +void +FormulaBase::reset() { - const SubData *sd = mysubdata(index); - return sd ? sd->desc : ""; } -int -Stat::myprecision() const -{ return mydata()->precision; } - -FormatFlags -Stat::myflags() const -{ return mydata()->flags; } - bool -Stat::dodisplay() const -{ return !mydata()->prereq || !mydata()->prereq->zero(); } - -StatData * -Stat::print() +FormulaBase::zero() const { - StatData *data = StatDB().print(this); - assert(data && data->init); - - return data; + VResult vec; + result(vec); + for (int i = 0; i < vec.size(); ++i) + if (vec[i] != 0.0) + return false; + return true; } -Stat & -Stat::name(const string &name) +void +FormulaBase::update(StatData *) { - print()->name = name; - return *this; } -Stat & -Stat::desc(const string &desc) +string +FormulaBase::str() const { - print()->desc = desc; - return *this; + return root ? root->str() : ""; } -Stat & -Stat::precision(int precision) +Formula::Formula() { - print()->precision = precision; - return *this; + setInit(); } -Stat & -Stat::flags(FormatFlags flags) +Formula::Formula(Temp r) { - if (flags & __reserved) - panic("Cannot set reserved flags!\n"); - - print()->flags |= flags; - return *this; + root = r; + assert(size()); } -Stat & -Stat::prereq(const Stat &prereq) +const Formula & +Formula::operator=(Temp r) { - print()->prereq = &prereq; + assert(!root && "Can't change formulas"); + root = r; + assert(size()); return *this; } -Stat & -Stat::subname(int index, const string &name) -{ - print(); - mysubdata_create(index)->name = name; - return *this; -} -Stat & -Stat::subdesc(int index, const string &desc) +const Formula & +Formula::operator+=(Temp r) { - print(); - mysubdata_create(index)->desc = desc; + if (root) + root = NodePtr(new BinaryNode >(root, r)); + else + root = r; + assert(size()); return *this; } -bool -ScalarStat::zero() const -{ - return val() == 0.0; -} - -bool -VectorStat::zero() const +MainBin::MainBin(const string &name) + : _name(name), mem(NULL), memsize(-1) { - return val()[0] == 0.0; + Database::regBin(this, name); } -string -ValueToString(result_t value, int precision) -{ - stringstream val; - - if (!isnan(value)) { - if (precision != -1) - val.precision(precision); - else if (value == rint(value)) - val.precision(0); - - val.unsetf(ios::showpoint); - val.setf(ios::fixed); - val << value; - } else { -#ifndef STAT_DISPLAY_COMPAT - val << "no value"; -#else - val << ""; -#endif - } - - return val.str(); -} - -void -PrintOne(ostream &stream, result_t value, - const string &name, const string &desc, int precision, - FormatFlags flags, result_t pdf = NAN, result_t cdf = NAN) -{ - if (flags & nozero && value == 0.0 || - flags & nonan && isnan(value)) - return; - - stringstream pdfstr, cdfstr; - - if (!isnan(pdf)) - ccprintf(pdfstr, "%.2f%%", pdf * 100.0); - - if (!isnan(cdf)) - ccprintf(cdfstr, "%.2f%%", cdf * 100.0); - -#ifdef STAT_DISPLAY_COMPAT - if (flags & __substat) { - ccprintf(stream, "%32s %12s %10s %10s", name, - ValueToString(value, precision), - pdfstr, cdfstr); - } else -#endif - { - ccprintf(stream, "%-40s %12s %10s %10s", name, - ValueToString(value, precision), pdfstr, cdfstr); - } - - if (PrintDescriptions) { - if (!desc.empty()) - ccprintf(stream, " # %s", desc); - } - stream << endl; -} - -void -ScalarStat::display(ostream &stream) const +MainBin::~MainBin() { - PrintOne(stream, val(), myname(), mydesc(), myprecision(), myflags()); + if (mem) + delete [] mem; } -void -VectorStat::display(ostream &stream) const +char * +MainBin::memory(off_t off) { - bool have_subname = false; - bool have_subdesc = false; - int size = this->size(); - for (int i = 0; i < size; ++i) { - if (!mysubname(i).empty()) - have_subname = true; - if (!mysubdesc(i).empty()) - have_subdesc = true; - } + if (memsize == -1) + memsize = CeilPow2((size_t) offset()); - vector *subnames = 0; - vector *subdescs = 0; - if (have_subname) { - subnames = new vector(size); - for (int i = 0; i < size; ++i) - (*subnames)[i] = mysubname(i); - } - if (have_subdesc) { - subdescs = new vector(size); - for (int i = 0; i < size; ++i) - (*subdescs)[i] = mysubdesc(i); + if (!mem) { + mem = new char[memsize]; + memset(mem, 0, memsize); } - VectorDisplay(stream, myname(), subnames, mydesc(), subdescs, - myprecision(), myflags(), val(), total()); + assert(offset() <= size()); + return mem + off; } -#ifndef STAT_DISPLAY_COMPAT -#define NAMESEP "::" -#else -#define NAMESEP "_" -#endif - -#ifndef STAT_DISPLAY_COMPAT void -VectorDisplay(std::ostream &stream, - const std::string &myname, - const std::vector *mysubnames, - const std::string &mydesc, - const std::vector *mysubdescs, - int myprecision, FormatFlags myflags, - const rvec_t &vec, result_t mytotal) +check() { - int _size = vec.size(); - result_t _total = 0.0; - result_t _pdf, _cdf = 0.0; + typedef Database::stat_list_t::iterator iter_t; - if (myflags & (pdf | cdf)) { - for (int i = 0; i < _size; ++i) { - _total += vec[i]; - } + iter_t i, end = Database::stats().end(); + for (i = Database::stats().begin(); i != end; ++i) { + StatData *data = *i; + assert(data); + if (!data->check() || !data->baseCheck()) + panic("stat check failed for %s\n", data->name); } - if (_size == 1) { - PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags); - } else { - for (int i = 0; i < _size; ++i) { - string subname; - if (mysubnames) { - subname = (*mysubnames)[i]; - if (subname.empty()) - continue; - } else { - subname = to_string(i); - } - - string name = myname + NAMESEP + subname; - if (!(myflags & pdf)) - PrintOne(stream, vec[i], name, mydesc, myprecision, myflags); - else { - _pdf = vec[i] / _total; - _cdf += _pdf; - PrintOne(stream, vec[i], name, mydesc, myprecision, myflags, - _pdf, _cdf); - } - } - - if (myflags & total) - PrintOne(stream, mytotal, myname + NAMESEP + "total", - mydesc, myprecision, myflags); + int j = 0; + for (i = Database::stats().begin(); i != end; ++i) { + StatData *data = *i; + if (!(data->flags & print)) + data->name = "__Stat" + to_string(j++); } -} -#else -void -VectorDisplay(std::ostream &stream, - const std::string &myname, - const std::vector *mysubnames, - const std::string &mydesc, - const std::vector *mysubdescs, - int myprecision, FormatFlags myflags, - const rvec_t &vec, result_t mytotal) -{ - int _size = vec.size(); - result_t _total = 0.0; - result_t _pdf, _cdf = 0.0; - if (myflags & (pdf | cdf)) { - for (int i = 0; i < _size; ++i) { - _total += vec[i]; - } - } + Database::stats().sort(StatData::less); - if (_size == 1) { - PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags); - } else { - if (myflags & total) - PrintOne(stream, mytotal, myname, mydesc, myprecision, myflags); - - if (myflags & dist) { - ccprintf(stream, "%s.start_dist\n", myname); - for (int i = 0; i < _size; ++i) { - string subname, subdesc; - subname = to_string(i); - if (mysubnames) { - if (!subname.empty()) { - subname = (*mysubnames)[i]; - } - } - if (mysubdescs) { - subdesc = (*mysubdescs)[i]; - } - if (!(myflags & (pdf | cdf))) { - PrintOne(stream, vec[i], subname, subdesc, myprecision, - myflags | __substat); - } else { - if (_total) { - _pdf = vec[i] / _total; - _cdf += _pdf; - } else { - _pdf = _cdf = NAN; - } - if (!(myflags & cdf)) { - PrintOne(stream, vec[i], subname, subdesc, myprecision, - myflags | __substat, _pdf); - } else { - PrintOne(stream, vec[i], subname, subdesc, myprecision, - myflags | __substat, _pdf, _cdf); - } - } - } - ccprintf(stream, "%s.end_dist\n", myname); - } else { - for (int i = 0; i < _size; ++i) { - string subname; - if (mysubnames) { - subname = (*mysubnames)[i]; - if (subname.empty()) - continue; - } else { - subname = to_string(i); - } - - string name = myname + NAMESEP + subname; - if (!(myflags & pdf)) { - PrintOne(stream, vec[i], name, mydesc, myprecision, - myflags); - } else { - if (_total) { - _pdf = vec[i] / _total; - _cdf += _pdf; - } else { - _pdf = _cdf = NAN; - } - PrintOne(stream, vec[i], name, mydesc, myprecision, - myflags, _pdf, _cdf); - } - } - } +#if STATS_BINNING + if (MainBin::curBin() == NULL) { + static MainBin mainBin("main bin"); + mainBin.activate(); } -} #endif -#ifndef STAT_DISPLAY_COMPAT -void -DistDisplay(ostream &stream, const string &name, const string &desc, - int precision, FormatFlags flags, - result_t min_val, result_t max_val, - result_t underflow, result_t overflow, - const rvec_t &vec, int min, int max, int bucket_size, int size); -{ - assert(size == vec.size()); - - result_t total = 0.0; - result_t pdf, cdf = 0.0; - - total += underflow; - for (int i = 0; i < size; ++i) - total += vec[i]; - total += overflow; - - pdf = underflow / total; - cdf += pdf; - - PrintOne(stream, underflow, name + NAMESEP + "underflow", desc, - precision, myflags, pdf, cdf); + if (i == end) + return; - for (int i = 0; i < size; ++i) { - stringstream namestr; - namestr << name; + iter_t last = i; + ++i; - int low = i * bucket_size + min; - int high = ::std::min((i + 1) * bucket_size + min - 1, max); - namestr << low; - if (low < high) - namestr << "-" << high; + for (i = Database::stats().begin(); i != end; ++i) { + if ((*i)->name == (*last)->name) + panic("same name used twice! name=%s\n", (*i)->name); - pdf = vec[i] / total; - cdf += pdf; - PrintOne(stream, vec[i], namestr.str(), desc, precision, myflags, - pdf, cdf); + last = i; } - - pdf = overflow / total; - cdf += pdf; - PrintOne(stream, overflow, name + NAMESEP + "overflow", desc, - precision, myflags, pdf, cdf); - PrintOne(stream, total, name + NAMESEP + "total", desc, - precision, myflags); } -#else -void -DistDisplay(ostream &stream, const string &name, const string &desc, - int precision, FormatFlags flags, - result_t min_val, result_t max_val, - result_t underflow, result_t overflow, - const rvec_t &vec, int min, int max, int bucket_size, int size) -{ - assert(size == vec.size()); - string blank; - - result_t total = 0.0; - - total += underflow; - for (int i = 0; i < size; ++i) - total += vec[i]; - total += overflow; - - ccprintf(stream, "%-42s", name + ".start_dist"); - if (PrintDescriptions && !desc.empty()) - ccprintf(stream, " # %s", desc); - stream << endl; - - PrintOne(stream, total, name + ".samples", blank, precision, flags); - PrintOne(stream, min_val, name + ".min_value", blank, precision, flags); - - if (underflow > 0) - PrintOne(stream, min_val, name + ".underflows", blank, precision, - flags); - - int _min; - result_t _pdf, _cdf, mypdf, mycdf; - _cdf = 0.0; - for (int i = 0; i < size; ++i) { - if (flags & nozero && vec[i] == 0.0 || - flags & nonan && isnan(vec[i])) - continue; - - _min = i * bucket_size + min; - _pdf = vec[i] / total * 100.0; - _cdf += _pdf; - - mypdf = (flags & pdf) ? _pdf : NAN; - mycdf = (flags & cdf) ? _cdf : NAN; - - PrintOne(stream, vec[i], ValueToString(_min, 0), blank, precision, - flags | __substat, mypdf, mycdf); - } - - if (overflow > 0) - PrintOne(stream, overflow, name + ".overflows", blank, precision, - flags); - PrintOne(stream, max_val, name + ".max_value", blank, precision, flags); - ccprintf(stream, "%s.end_dist\n\n", name); -} -#endif +CallbackQueue resetQueue; -/** - * @todo get rid of the ugly hack **Ignore for total - */ void -FancyDisplay(ostream &stream, const string &name, const string &desc, - int precision, FormatFlags flags, result_t mean, - result_t variance, result_t total) -{ - result_t stdev = isnan(variance) ? NAN : sqrt(variance); - PrintOne(stream, mean, name + NAMESEP + "mean", desc, precision, flags); - PrintOne(stream, stdev, name + NAMESEP + "stdev", desc, precision, flags); - PrintOne(stream, total, "**Ignore: " + name + NAMESEP + "TOT", desc, precision, flags); -} - -BinBase::BinBase() - : mem(NULL), memsize(-1) -{ -} - -BinBase::~BinBase() -{ - if (mem) - delete [] mem; -} - -char * -BinBase::memory() +reset() { - if (!mem) { - mem = new char[memsize]; - memset(mem, 0, memsize); + // reset non-binned stats + Database::stat_list_t::iterator i = Database::stats().begin(); + Database::stat_list_t::iterator end = Database::stats().end(); + while (i != end) { + StatData *data = *i; + if (!data->binned()) + data->reset(); + ++i; } - return mem; -} + // save the bin so we can go back to where we were + MainBin *orig = MainBin::curBin(); -void -GenBin::regBin(GenBin *bin, std::string name) -{ - Detail::StatDB().regBin(bin, name); -} + // reset binned stats + Database::bin_list_t::iterator bi = Database::bins().begin(); + Database::bin_list_t::iterator be = Database::bins().end(); + while (bi != be) { + MainBin *bin = *bi; + bin->activate(); -} // namespace Detail + i = Database::stats().begin(); + while (i != end) { + StatData *data = *i; + if (data->binned()) + data->reset(); + ++i; + } + ++bi; + } -void -check() -{ - Detail::StatDB().check(); -} + // restore bin + MainBin::curBin() = orig; -void -dump(ostream &stream) -{ - Detail::StatDB().dump(stream); + resetQueue.process(); } -CallbackQueue resetQueue; - void -RegResetCallback(Callback *cb) +registerResetCallback(Callback *cb) { resetQueue.add(cb); } -void -reset() -{ - Detail::StatDB().reset(); - resetQueue.process(); -} - -} // namespace Statistics +/* namespace Stats */ }