blob: 44d571516e220db543824fe90ffafe7d66f16627 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PERFORMANCE_MANAGER_GRAPH_PROPERTIES_H_
#define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_PROPERTIES_H_
#include <utility>
namespace performance_manager {
// TODO(chrisha): Deprecate the private observer type and have everyone use the
// public observers!
// Helper classes for setting properties and invoking observer callbacks based
// on the value change. Note that by contract the NodeType must have a member
// function "observers()" that returns an iterable collection of
// ObserverType pointers. This is templated on the observer type to allow
// easy testing.
template <typename NodeImplType, typename NodeType, typename ObserverType>
class ObservedPropertyImpl {
public:
// Helper class for node properties that represent measurements that are taken
// periodically, and for which a notification should be sent every time a
// new sample is recorded, even if identical in value to the last.
template <typename PropertyType,
void (ObserverType::*NotifyFunctionPtr)(const NodeType*)>
class NotifiesAlways {
public:
NotifiesAlways() = default;
template <typename U = PropertyType>
explicit NotifiesAlways(U&& initial_value)
: value_(std::forward<U>(initial_value)) {}
~NotifiesAlways() = default;
// Sets the property and sends a notification.
template <typename U = PropertyType>
void SetAndNotify(NodeImplType* node, U&& value) {
value_ = std::forward<U>(value);
for (auto* observer : node->GetObservers())
((observer)->*(NotifyFunctionPtr))(node);
}
const PropertyType& value() const { return value_; }
private:
PropertyType value_;
};
// Helper class for node properties that represent states, for which
// notifications should only be sent when the value of the property actually
// changes. Calls to SetAndMaybeNotify do not notify if the provided value is
// the same as the current value.
template <typename PropertyType,
void (ObserverType::*NotifyFunctionPtr)(const NodeType*)>
class NotifiesOnlyOnChanges {
public:
NotifiesOnlyOnChanges() = default;
template <typename U = PropertyType>
explicit NotifiesOnlyOnChanges(U&& initial_value)
: value_(std::forward<U>(initial_value)) {}
~NotifiesOnlyOnChanges() = default;
// Sets the property and sends a notification if needed. Returns true if a
// notification was sent, false otherwise.
template <typename U = PropertyType>
bool SetAndMaybeNotify(NodeImplType* node, U&& value) {
if (value_ == value)
return false;
value_ = std::forward<U>(value);
for (auto* observer : node->GetObservers())
((observer)->*(NotifyFunctionPtr))(node);
return true;
}
const PropertyType& value() const { return value_; }
private:
PropertyType value_;
};
// Same as NotifiesOnlyOnChanges, but provides the previous value when
// notifying observers.
template <typename PropertyType,
void (ObserverType::*NotifyFunctionPtr)(
const NodeType* node,
const PropertyType& previous_value)>
class NotifiesOnlyOnChangesWithPreviousValue {
public:
NotifiesOnlyOnChangesWithPreviousValue() = default;
template <typename U = PropertyType>
explicit NotifiesOnlyOnChangesWithPreviousValue(U&& initial_value)
: value_(std::forward<U>(initial_value)) {}
~NotifiesOnlyOnChangesWithPreviousValue() = default;
// Sets the property and sends a notification if needed. Returns true if a
// notification was sent, false otherwise.
template <typename U = PropertyType>
bool SetAndMaybeNotify(NodeImplType* node, U&& value) {
if (value_ == value)
return false;
PropertyType previous_value = std::move(value_);
value_ = std::forward<U>(value);
for (auto* observer : node->GetObservers())
((observer)->*(NotifyFunctionPtr))(node, previous_value);
return true;
}
const PropertyType& value() const { return value_; }
private:
PropertyType value_;
};
};
} // namespace performance_manager
#endif // COMPONENTS_PERFORMANCE_MANAGER_GRAPH_PROPERTIES_H_