File: node_base.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (265 lines) | stat: -rw-r--r-- 10,661 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
// Copyright 2017 The Chromium Authors
// 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_NODE_BASE_H_
#define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_NODE_BASE_H_

#include <stdint.h>

#include "base/check_op.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "components/performance_manager/graph/graph_impl.h"
#include "components/performance_manager/graph/properties.h"
#include "components/performance_manager/public/graph/node_state.h"
#include "components/performance_manager/public/graph/node_type.h"

namespace performance_manager {

class Node;

// NodeBase implements shared functionality among different types of graph
// nodes. A specific type of graph node will derive from this class and can
// override shared functionality when needed.
// All node classes allow construction on one sequence and subsequent use from
// another sequence.
// All methods not documented otherwise are single-threaded.
class NodeBase {
 public:
  // Used as a unique key to safely allow downcasting from a public node type
  // to NodeBase via "GetImplType" and "GetImpl". The implementations are
  // provided by PublicNodeImpl below.
  static const uintptr_t kNodeBaseType;

  NodeBase();

  NodeBase(const NodeBase&) = delete;
  NodeBase& operator=(const NodeBase&) = delete;

  virtual ~NodeBase();

  // May be called on any sequence.
  NodeTypeEnum GetNodeType() const { return ToNode()->GetNodeType(); }

  // The state of this node.
  NodeState GetNodeState() const {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    if (!graph_) {
      return NodeState::kNotInGraph;
    }
    return graph_->GetNodeState(this);
  }

  // Returns the graph that contains this node. Only valid after JoinGraph() and
  // before LeaveGraph().
  GraphImpl* graph() const {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    DCHECK(graph_);
    return graph_;
  }

  // Helper functions for casting from a node type to its underlying NodeBase.
  // This CHECKs that the cast is valid. These functions work happily with
  // public and private node class inputs.
  static const NodeBase* FromNode(const Node* node);
  static NodeBase* FromNode(Node* node);

  // For converting from NodeBase to Node. This is implemented by
  // TypedNodeBase.
  virtual const Node* ToNode() const = 0;

  // Satisfies part of the contract expected by ObservedProperty.
  // GetObservers is implemented by TypedNodeImpl.
  bool CanSetProperty() const;
  bool CanSetAndNotifyProperty() const;

 protected:
  friend class GraphImpl;

  // Helper function for TypedNodeBase to access the list of typed observers
  // stored in the graph.
  template <typename Observer>
  const GraphImpl::ObserverList<Observer>& GetObservers(
      const GraphImpl* graph) const {
    DCHECK(CanSetAndNotifyProperty());
    return graph->GetObservers<Observer>();
  }

  // Node lifecycle:

  // Step 0: A node is constructed. Node state is kNotInGraph. Outgoing edges
  // are set but not publicly visible.

  // Step 1:
  // Initializes the `graph_` pointer. Node must be in the kNotInGraph state.
  void SetGraphPointer(GraphImpl* graph);

  // Step 2:
  // Node enters kInitializingNotInGraph state: nodes may modify their
  // properties that don't affect the graph topology but *not* cause any
  // notifications to be emitted that refer to the node, since public observers
  // have not been notified that the node was added to the graph via
  // OnBeforeNodeAdded and OnNodeAdded yet.

  // Called after `graph_` is set, a good opportunity to initialize node state.
  virtual void OnInitializingProperties();

  // Step 3:
  // OnBeforeNodeAdded notifications are dispatched. The public observer method
  // can read and update the node state, but sees no incoming or outgoing edges.
  // The graph is in a consistent state that doesn't include this node.

  // Step 4:
  // Node enters kInitializingEdges state: nodes may modify their properties
  // that link to other nodes but *not* cause any notifications to be emitted
  // that refer to the node, since public observers have not been notified that
  // the node was added to the graph via OnNodeAdded yet.

  // Called after properties are initialized, for nodes to update incoming edges
  // to fully join the graph.
  virtual void OnInitializingEdges();

  // Step 5:
  // Node enters kJoiningGraph state: the node must not be modified, since
  // observers will now be notified of its initial state in the graph, and each
  // observer should see the same state.

  // OnNodeAdded notifications are dispatched.

  // Step 6:
  // Node enters kActiveInGraph state: the node may make property changes, and
  // these changes may cause notifications to be dispatched.

  // Called just after sending OnNodeAdded notifications, for nodes to perform
  // initialization that causes notifications to be dispatched. For example,
  // this could be used to set up an "opener" relationship between a PageNode
  // and FrameNode: when OnPageNodeAdded() was called, the graph was in the
  // valid state where both FrameNode and PageNode exist but the PageNode has
  // no opener. Then this function sets the FrameNode as the opener and sends
  // the OnOpenerFrameNodeChanged notification.
  virtual void OnAfterJoiningGraph();

  // The node lives in the graph normally at this point, in the kActiveInGraph
  // state.

  // Step 7:
  // Called just before sending OnBeforeNodeRemoved notifications, for nodes to
  // perform cleanup that causes notifications to be dispatched. This must leave
  // the node and the graph in a consistent state since the node is still in the
  // graph. For example if this is used to sever the "opener" relationship
  // between a PageNode and a FrameNode, it must send the
  // OnOpenerFrameNodeChanged notification, and leave the PageNode and FrameNode
  // in the valid state they would have when the page has no opener.
  virtual void OnBeforeLeavingGraph();

  // Step 8:
  // Node enters kLeavingGraph state: the node must not be modified, since it's
  // about to be deleted. Observers will commonly use OnBeforeNodeRemoved
  // notifications to clean up, and each observer should see the same state.

  // OnBeforeNodeRemoved notifications are dispatched.

  // Step 9:
  // Node enters kUninitializingEdges state: nodes may modify their properties
  // that link to other nodes but *not* cause any notifications to be emitted
  // that refer to the node, since public observers have already been notified
  // that the node is being removed from the graph via OnBeforeNodeRemoved.

  // Called while leaving `graph_`, to sever the node from the graph by updating
  // incoming edges.
  virtual void OnUninitializingEdges();

  // Step 10:
  // Node enters kLeftGraph state: the node must not be modified, since it's
  // about to be deleted. Any property changes would only be visible to other
  // OnNodeRemoved observers, and their effects shouldn't depend on the order
  // that observers are triggered.

  // OnNodeRemoved notifications are dispatched. The public observer method sees
  // the node's final properties but no incoming or outgoing edges. The graph is
  // in a consistent state that doesn't include this node.

  // Step 11:
  // Called after the node's edges have been severed from the graph, a good
  // opportunity to uninitialize node state. This is a pure virtual since almost
  // all node classes must implement it to destroy private node-attached data.
  virtual void CleanUpNodeState() = 0;

  // Step 12:
  // Resets the graph pointer. The node is in the kLeftGraph state during this
  // call, and will be in the kNotInGraph state immediately afterwards.
  void ClearGraphPointer();

  // Assigned when SetGraphPointer() is called, up until ClearGraphPointer() is
  // called, where it is reset to null.
  raw_ptr<GraphImpl> graph_ GUARDED_BY_CONTEXT(sequence_checker_) = nullptr;

  SEQUENCE_CHECKER(sequence_checker_);
};

// Helper for implementing the Node parent of a PublicNodeClass.
template <class NodeImplClass, class PublicNodeClass>
class PublicNodeImpl : public PublicNodeClass {
 public:
  // Node implementation:
  Graph* GetGraph() const override {
    return static_cast<const NodeImplClass*>(this)->graph();
  }
  uintptr_t GetImplType() const override { return NodeBase::kNodeBaseType; }
  const void* GetImpl() const override {
    // This exposes NodeBase, so that we can complete the triangle of casting
    // between all views of a node: NodeBase, FooNodeImpl, and FooNode.
    return static_cast<const NodeBase*>(
        static_cast<const NodeImplClass*>(this));
  }
};

template <class NodeImplClass, class NodeClass, class NodeObserverClass>
class TypedNodeBase : public NodeBase {
 public:
  using ObservedProperty =
      ObservedPropertyImpl<NodeImplClass, NodeClass, NodeObserverClass>;

  TypedNodeBase() = default;

  TypedNodeBase(const TypedNodeBase&) = delete;
  TypedNodeBase& operator=(const TypedNodeBase&) = delete;

  // Helper functions for casting from NodeBase to a concrete node type. This
  // CHECKs that the cast is valid.
  static const NodeImplClass* FromNodeBase(const NodeBase* node) {
    CHECK_EQ(NodeImplClass::Type(), node->GetNodeType());
    return static_cast<const NodeImplClass*>(node);
  }
  static NodeImplClass* FromNodeBase(NodeBase* node) {
    CHECK_EQ(NodeImplClass::Type(), node->GetNodeType());
    return static_cast<NodeImplClass*>(node);
  }

  // Helper functions for casting from a public node type to the private impl.
  // This also casts away const correctness, as it is intended to be used by
  // impl code that uses the public observer interface for a node type, where
  // all notifications are delivered with a const node pointer. This CHECKs that
  // the cast is valid.
  static NodeImplClass* FromNode(const Node* node) {
    NodeBase* node_base = const_cast<NodeBase*>(NodeBase::FromNode(node));
    return FromNodeBase(node_base);
  }

  // Convenience accessor to the per-node-class list of observers that is stored
  // in the graph. Satisfies the contract expected by ObservedProperty.
  const GraphImpl::ObserverList<NodeObserverClass>& GetObservers() const {
    // Mediate through NodeBase, as it's the class that is friended by the
    // GraphImpl in order to provide access.
    return NodeBase::GetObservers<NodeObserverClass>(graph());
  }

  const Node* ToNode() const override {
    return static_cast<const NodeImplClass*>(this);
  }
};

}  // namespace performance_manager

#endif  // COMPONENTS_PERFORMANCE_MANAGER_GRAPH_NODE_BASE_H_