From e020184843e0e22d767c7562ec55f0c949b2c805 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 18 Aug 2020 20:48:06 -0700 Subject: [PATCH] base: Make the Value stat's functor method accept lambdas. This class can already accept a proxy variable and a "functor" which is a pointer to either a function or an instance of a class with the () operator overloaded. This change adds a FunctorProxy partial specialization which accepts anything that can be used to construct a std::function. The constructor argument is copied and stored in the proxy which makes it possible to define a lambda inline without having to keep a copy of it around for the proxy to point to. Also, the ValueBase stat's functor method now has a second version which accepts a const reference rather than just a reference to its argument. We need both because when accepting a reference to a lambda it needs to be a const reference, but when accepting a pointer to a functor object, we don't want it to be const because that would force the () operator to also be const. Change-Id: Icb1b3682d51b721f6e16614490ed0fe289cee094 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/32901 Tested-by: kokoro Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg --- src/base/statistics.hh | 32 +++++++++++++++++++++++++++++++- src/unittest/stattest.cc | 31 +++++++++++++++++++------------ 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/base/statistics.hh b/src/base/statistics.hh index 96cd43fec..c66454053 100644 --- a/src/base/statistics.hh +++ b/src/base/statistics.hh @@ -791,7 +791,7 @@ class ValueProxy : public ProxyInfo Result total() const { return *scalar; } }; -template +template class FunctorProxy : public ProxyInfo { private: @@ -804,6 +804,27 @@ class FunctorProxy : public ProxyInfo Result total() const { return (*functor)(); } }; +/** + * Template specialization for type std::function which holds a copy + * of its target instead of a pointer to it. This makes it possible to use a + * lambda or other type inline without having to keep track of an instance + * somewhere else. + */ +template +class FunctorProxy, + const T &>::value>::type> : public ProxyInfo +{ + private: + std::function functor; + + public: + FunctorProxy(const T &func) : functor(func) {} + Counter value() const { return functor(); } + Result result() const { return functor(); } + Result total() const { return functor(); } +}; + /** * A proxy similar to the FunctorProxy, but allows calling a method of a bound * object, instead of a global free-standing function. @@ -847,6 +868,15 @@ class ValueBase : public DataWrap return this->self(); } + template + Derived & + functor(const T &func) + { + proxy = new FunctorProxy(func); + this->setInit(); + return this->self(); + } + template Derived & functor(T &func) diff --git a/src/unittest/stattest.cc b/src/unittest/stattest.cc index 883185a1e..40307357c 100644 --- a/src/unittest/stattest.cc +++ b/src/unittest/stattest.cc @@ -88,6 +88,7 @@ struct StatTest Vector2d s16; Value s17; Value s18; + Value s19; Histogram h01; Histogram h02; Histogram h03; @@ -102,8 +103,8 @@ struct StatTest Histogram h12; SparseHistogram sh1; - Vector s19; Vector s20; + Vector s21; Formula f1; Formula f2; @@ -254,6 +255,12 @@ StatTest::init() .desc("this is stat 18") ; + s19 + .functor([]() { return 0; }) + .name("Stat19") + .desc("this is stat 19") + ; + h01 .init(11) .name("Histogram01") @@ -361,18 +368,18 @@ StatTest::init() .desc("this is formula 4") ; - s19 - .init(2) - .name("Stat19") - .desc("this is statistic 19 for vector op testing") - .flags(total | nozero | nonan) - ; s20 .init(2) .name("Stat20") .desc("this is statistic 20 for vector op testing") .flags(total | nozero | nonan) ; + s21 + .init(2) + .name("Stat21") + .desc("this is statistic 21 for vector op testing") + .flags(total | nozero | nonan) + ; f6 .name("vector_op_test_formula") @@ -386,7 +393,7 @@ StatTest::init() f4 += constant(10.0); f4 += s5[3]; f5 = constant(1); - f6 = s19/s20; + f6 = s20/s21; } void @@ -663,10 +670,10 @@ StatTest::run() sh1.sample(random() % 10000); } - s19[0] = 1; - s19[1] = 100000; - s20[0] = 100000; - s20[1] = 1; + s20[0] = 1; + s20[1] = 100000; + s21[0] = 100000; + s21[1] = 1; } -- 2.30.2