blob: e440f592ff6737e073e9028b7da465fac812231e [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2020 The Chromium Authors
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:172// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_
6#define BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_
7
8#include <stddef.h>
9
Peter Kasting025a94252025-01-29 21:28:3710#include <algorithm>
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1711#include <vector>
12
13#include "base/check.h"
Jan Wilken Dörrieb5a41c32020-12-09 18:55:4714#include "base/containers/contains.h"
Keishi Hattori0e45c022021-11-27 09:25:5215#include "base/memory/raw_ptr.h"
Andrew Rayskiy799ce712022-11-04 22:42:5316#include "base/scoped_observation_traits.h"
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1717
18namespace base {
19
Sigurdur Asgeirsson11031652020-11-12 17:44:2520// ScopedMultiSourceObservation is used to keep track of plural observation,
21// e.g. where an observer observes more than a single source.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1722//
Sigurdur Asgeirsson11031652020-11-12 17:44:2523// Use base::ScopedObservation for objects that observe only a single source.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1724//
Sigurdur Asgeirsson11031652020-11-12 17:44:2525// When ScopedMultiSourceObservation is destroyed, it removes the object as an
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1726// observer from all sources it has been added to.
27// Basic example (as a member variable):
28//
29// class MyFooObserver : public FooObserver {
30// ...
31// private:
Sigurdur Asgeirsson11031652020-11-12 17:44:2532// ScopedMultiSourceObservation<Foo, FooObserver> foo_observations_{this};
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1733// };
34//
Sigurdur Asgeirsson11031652020-11-12 17:44:2535// MyFooObserver::OnFooCreated(Foo* foo) {
36// foo_observations_.AddObservation(foo);
37// }
38//
Andrew Rayskiy799ce712022-11-04 22:42:5339////////////////////////////////////////////////////////////////////////////////
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1740//
Andrew Rayskiy799ce712022-11-04 22:42:5341// By default `ScopedMultiSourceObservation` only works with sources that expose
42// `AddObserver` and `RemoveObserver`. However, it's also possible to
43// adapt it to custom function names (say `AddFoo` and `RemoveFoo` accordingly)
Andrew Rayskiy3cf073392022-11-11 00:31:4944// by tailoring ScopedObservationTraits<> for the given Source and Observer --
45// see `base/scoped_observation_traits.h` for details.
Andrew Rayskiy799ce712022-11-04 22:42:5346//
47
Andrew Rayskiy3cf073392022-11-11 00:31:4948template <class Source, class Observer>
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1749class ScopedMultiSourceObservation {
50 public:
51 explicit ScopedMultiSourceObservation(Observer* observer)
52 : observer_(observer) {}
53 ScopedMultiSourceObservation(const ScopedMultiSourceObservation&) = delete;
54 ScopedMultiSourceObservation& operator=(const ScopedMultiSourceObservation&) =
55 delete;
56 ~ScopedMultiSourceObservation() { RemoveAllObservations(); }
57
58 // Adds the object passed to the constructor as an observer on |source|.
59 void AddObservation(Source* source) {
Peter Kasting013e36452024-02-03 13:15:2860 CHECK(!IsObservingSource(source));
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1761 sources_.push_back(source);
Andrew Rayskiy799ce712022-11-04 22:42:5362 Traits::AddObserver(source, observer_);
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1763 }
64
65 // Remove the object passed to the constructor as an observer from |source|.
66 void RemoveObservation(Source* source) {
Peter Kasting025a94252025-01-29 21:28:3767 auto it = std::ranges::find(sources_, source);
Peter Boström1aec0b22023-02-24 00:33:0668 CHECK(it != sources_.end());
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1769 sources_.erase(it);
Andrew Rayskiy799ce712022-11-04 22:42:5370 Traits::RemoveObserver(source, observer_);
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1771 }
72
Sigurdur Asgeirsson11031652020-11-12 17:44:2573 // Remove the object passed to the constructor as an observer from all sources
74 // it's observing.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1775 void RemoveAllObservations() {
Andrew Rayskiy799ce712022-11-04 22:42:5376 for (Source* source : sources_) {
77 Traits::RemoveObserver(source, observer_);
78 }
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1779 sources_.clear();
80 }
81
Sigurdur Asgeirsson11031652020-11-12 17:44:2582 // Returns true if any source is being observed.
83 bool IsObservingAnySource() const { return !sources_.empty(); }
84
85 // Returns true if |source| is being observed.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1786 bool IsObservingSource(Source* source) const {
Sigurdur Asgeirsson61cc21542020-11-19 00:12:0787 DCHECK(source);
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1788 return base::Contains(sources_, source);
89 }
90
Sigurdur Asgeirsson11031652020-11-12 17:44:2591 // Returns the number of sources being observed.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1792 size_t GetSourcesCount() const { return sources_.size(); }
93
Theo Cristea09b94562024-09-04 08:07:3194 // Returns a pointer to the observer that observes the sources.
95 Observer* observer() { return observer_; }
96 const Observer* observer() const { return observer_; }
97
minch67592412024-01-05 17:20:5998 // Returns the sources being observed. Note: It is invalid to add or remove
99 // sources while iterating on it.
Julie Jeongeun Kim61027f82024-01-16 08:18:03100 const std::vector<raw_ptr<Source>>& sources() const { return sources_; }
minch67592412024-01-05 17:20:59101
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:17102 private:
Andrew Rayskiy3cf073392022-11-11 00:31:49103 using Traits = ScopedObservationTraits<Source, Observer>;
Andrew Rayskiy799ce712022-11-04 22:42:53104
Keishi Hattori0e45c022021-11-27 09:25:52105 const raw_ptr<Observer> observer_;
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:17106
Julie Jeongeun Kim61027f82024-01-16 08:18:03107 std::vector<raw_ptr<Source>> sources_;
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:17108};
109
110} // namespace base
111
112#endif // BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_