blob: 819c97d0f2018f705445450984410a8eba2c75d8 [file] [log] [blame]
// Copyright 2017 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 CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_NODE_BASE_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_NODE_BASE_H_
#include <map>
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "chrome/browser/performance_manager/graph/graph.h"
#include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/resource_coordinator/public/cpp/coordination_unit_types.h"
#include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h"
#include "services/resource_coordinator/public/mojom/coordination_unit_provider.mojom.h"
namespace performance_manager {
class Graph;
// NodeBase implements shared functionality among different types of
// coordination units. A specific type of coordination unit will derive from
// this class and can override shared funtionality when needed.
class NodeBase {
public:
NodeBase(const resource_coordinator::CoordinationUnitID& id, Graph* graph);
virtual ~NodeBase();
void BeforeDestroyed();
void AddObserver(GraphObserver* observer);
void RemoveObserver(GraphObserver* observer);
bool GetProperty(
const resource_coordinator::mojom::PropertyType property_type,
int64_t* result) const;
int64_t GetPropertyOrDefault(
const resource_coordinator::mojom::PropertyType property_type,
int64_t default_value) const;
// May be called on any thread.
const resource_coordinator::CoordinationUnitID& id() const { return id_; }
Graph* graph() const { return graph_; }
const base::ObserverList<GraphObserver>::Unchecked& observers() const {
return observers_;
}
void SetPropertyForTesting(int64_t value) {
SetProperty(resource_coordinator::mojom::PropertyType::kTest, value);
}
const std::map<resource_coordinator::mojom::PropertyType, int64_t>&
properties_for_testing() const {
return properties_;
}
protected:
// Helper function for setting a property, and notifying observers if the
// value has changed.
template <typename NodeType,
typename PropertyType,
typename NotifyFunctionPtr>
void SetPropertyAndNotifyObservers(NotifyFunctionPtr notify_function_ptr,
const PropertyType& value,
NodeType* node,
PropertyType* property) {
if (*property == value)
return;
*property = value;
for (auto& observer : observers_)
((observer).*(notify_function_ptr))(node);
}
virtual void OnEventReceived(resource_coordinator::mojom::Event event);
virtual void OnPropertyChanged(
resource_coordinator::mojom::PropertyType property_type,
int64_t value);
void SendEvent(resource_coordinator::mojom::Event event);
void SetProperty(resource_coordinator::mojom::PropertyType property_type,
int64_t value);
Graph* const graph_;
const resource_coordinator::CoordinationUnitID id_;
SEQUENCE_CHECKER(sequence_checker_);
private:
base::ObserverList<GraphObserver>::Unchecked observers_;
std::map<resource_coordinator::mojom::PropertyType, int64_t> properties_;
DISALLOW_COPY_AND_ASSIGN(NodeBase);
};
template <class CoordinationUnitClass,
class MojoInterfaceClass,
class MojoRequestClass>
class CoordinationUnitInterface : public NodeBase, public MojoInterfaceClass {
public:
static const CoordinationUnitClass* FromNodeBase(const NodeBase* cu) {
DCHECK(cu->id().type == CoordinationUnitClass::Type());
return static_cast<const CoordinationUnitClass*>(cu);
}
static CoordinationUnitClass* FromNodeBase(NodeBase* cu) {
DCHECK(cu->id().type == CoordinationUnitClass::Type());
return static_cast<CoordinationUnitClass*>(cu);
}
CoordinationUnitInterface(const resource_coordinator::CoordinationUnitID& id,
Graph* graph)
: NodeBase(id, graph), binding_(this) {}
~CoordinationUnitInterface() override = default;
void Bind(MojoRequestClass request) { binding_.Bind(std::move(request)); }
void GetID(typename MojoInterfaceClass::GetIDCallback callback) override {
std::move(callback).Run(id_);
}
void AddBinding(MojoRequestClass request) override {
bindings_.AddBinding(this, std::move(request));
}
mojo::Binding<MojoInterfaceClass>& binding() { return binding_; }
static CoordinationUnitClass* GetNodeByID(
Graph* graph,
const resource_coordinator::CoordinationUnitID cu_id) {
DCHECK(cu_id.type == CoordinationUnitClass::Type());
auto* cu = graph->GetNodeByID(cu_id);
if (!cu)
return nullptr;
CHECK_EQ(cu->id().type, CoordinationUnitClass::Type());
return static_cast<CoordinationUnitClass*>(cu);
}
private:
mojo::BindingSet<MojoInterfaceClass> bindings_;
mojo::Binding<MojoInterfaceClass> binding_;
DISALLOW_COPY_AND_ASSIGN(CoordinationUnitInterface);
};
} // namespace performance_manager
#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_GRAPH_NODE_BASE_H_