File: properties.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (172 lines) | stat: -rw-r--r-- 6,297 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
// Copyright 2019 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_PROPERTIES_H_
#define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_PROPERTIES_H_

#include <utility>

#include "base/check.h"
#include "components/performance_manager/public/graph/node_state.h"

namespace performance_manager {

// Helper classes for setting properties and invoking observer callbacks based
// on the value change. This is templated on the observer type to allow
// easy testing.
//
// Objects of NodeImplType are expected to fulfill the contract:
//
//   IterableCollection GetObservers() const;
//   bool NodeImplType::CanSetProperty() const;
//   bool NodeImplType::CanSetAndNotifyProperty() const;
//
// These are used in DCHECKs to assert that properties are only being modified
// at appropriate moments. If your code is blowing up in one of these DCHECKS
// you are trying to change a property while a node is being added or removed
// from the graph. When adding to the graph property changes should be done in a
// separate posted task. When removing from the graph, they should simply not be
// done. See class comments on node observers, NodeState, and NodeBase for full
// details.
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) {
      // If your code is blowing up here see the class comment!
      DCHECK(node->CanSetAndNotifyProperty());
      value_ = std::forward<U>(value);
      for (auto& observer : node->GetObservers()) {
        (observer.*NotifyFunctionPtr)(node);
      }
    }

    // Sets the property without sending a notification.
    template <typename U = PropertyType>
    void Set(NodeImplType* node, U&& value) {
      // If your code is blowing up here see the class comment!
      DCHECK(node->CanSetProperty());
      value_ = std::forward<U>(value);
    }

    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 your code is blowing up here see the class comment!
      DCHECK(node->CanSetAndNotifyProperty());
      if (value_ == value)
        return false;
      value_ = std::forward<U>(value);
      for (auto& observer : node->GetObservers()) {
        (observer.*NotifyFunctionPtr)(node);
      }
      return true;
    }

    // Sets the property without sending a notification.
    template <typename U = PropertyType>
    void Set(NodeImplType* node, U&& value) {
      // If your code is blowing up here see the class comment!
      DCHECK(node->CanSetProperty());
      value_ = std::forward<U>(value);
    }

    const PropertyType& value() const { return value_; }

   private:
    PropertyType value_;
  };

  // Same as NotifiesOnlyOnChanges, but provides the previous value when
  // notifying observers.
  // TODO(chrisha): When C++17 is available, deduce PreviousValueType via use of
  // an 'auto' placeholder non-type template parameter helper.
  template <typename PropertyType,
            typename PreviousValueType,
            void (ObserverType::*NotifyFunctionPtr)(
                const NodeType* node,
                PreviousValueType 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 your code is blowing up here see the class comment!
      DCHECK(node->CanSetAndNotifyProperty());
      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;
    }

    // Sets the property without sending a notification.
    template <typename U = PropertyType>
    void Set(NodeImplType* node, U&& value) {
      // If your code is blowing up here see the class comment!
      DCHECK(node->CanSetProperty());
      value_ = std::forward<U>(value);
    }

    const PropertyType& value() const { return value_; }

   private:
    PropertyType value_;
  };
};

}  // namespace performance_manager

#endif  // COMPONENTS_PERFORMANCE_MANAGER_GRAPH_PROPERTIES_H_