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<Result()>. 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 <noreply+kokoro@google.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
Gabe Black
2020-08-18 20:48:06 -07:00
parent f0e63088ab
commit e020184843
2 changed files with 50 additions and 13 deletions

View File

@@ -791,7 +791,7 @@ class ValueProxy : public ProxyInfo
Result total() const { return *scalar; }
};
template <class T>
template <class T, class Enabled=void>
class FunctorProxy : public ProxyInfo
{
private:
@@ -804,6 +804,27 @@ class FunctorProxy : public ProxyInfo
Result total() const { return (*functor)(); }
};
/**
* Template specialization for type std::function<Result()> 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 T>
class FunctorProxy<T,
typename std::enable_if<std::is_constructible<std::function<Result()>,
const T &>::value>::type> : public ProxyInfo
{
private:
std::function<Result()> 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<Derived, ScalarInfoProxy>
return this->self();
}
template <class T>
Derived &
functor(const T &func)
{
proxy = new FunctorProxy<T>(func);
this->setInit();
return this->self();
}
template <class T>
Derived &
functor(T &func)