blob: 44e656af10bb3c15bdba89af2d156e5f3fd805d8 [file] [log] [blame]
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:171// Copyright 2020 The Chromium Authors. All rights reserved.
2// 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
10#include <vector>
11
12#include "base/check.h"
Jan Wilken Dörrieb5a41c32020-12-09 18:55:4713#include "base/containers/contains.h"
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1714#include "base/ranges/algorithm.h"
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1715
16namespace base {
17
Sigurdur Asgeirsson11031652020-11-12 17:44:2518// ScopedMultiSourceObservation is used to keep track of plural observation,
19// e.g. where an observer observes more than a single source.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1720//
Sigurdur Asgeirsson11031652020-11-12 17:44:2521// Use base::ScopedObservation for objects that observe only a single source.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1722//
Sigurdur Asgeirsson11031652020-11-12 17:44:2523// When ScopedMultiSourceObservation is destroyed, it removes the object as an
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1724// observer from all sources it has been added to.
25// Basic example (as a member variable):
26//
27// class MyFooObserver : public FooObserver {
28// ...
29// private:
Sigurdur Asgeirsson11031652020-11-12 17:44:2530// ScopedMultiSourceObservation<Foo, FooObserver> foo_observations_{this};
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1731// };
32//
Sigurdur Asgeirsson11031652020-11-12 17:44:2533// MyFooObserver::OnFooCreated(Foo* foo) {
34// foo_observations_.AddObservation(foo);
35// }
36//
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1737// For cases with methods not named AddObserver/RemoveObserver:
38//
39// class MyFooStateObserver : public FooStateObserver {
40// ...
41// private:
Sigurdur Asgeirsson11031652020-11-12 17:44:2542// ScopedMultiSourceObservation<Foo,
43// FooStateObserver,
44// &Foo::AddStateObserver,
45// &Foo::RemoveStateObserver>
46// foo_observations_{this};
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1747// };
48template <class Source,
49 class Observer,
50 void (Source::*AddObsFn)(Observer*) = &Source::AddObserver,
51 void (Source::*RemoveObsFn)(Observer*) = &Source::RemoveObserver>
52class ScopedMultiSourceObservation {
53 public:
54 explicit ScopedMultiSourceObservation(Observer* observer)
55 : observer_(observer) {}
56 ScopedMultiSourceObservation(const ScopedMultiSourceObservation&) = delete;
57 ScopedMultiSourceObservation& operator=(const ScopedMultiSourceObservation&) =
58 delete;
59 ~ScopedMultiSourceObservation() { RemoveAllObservations(); }
60
61 // Adds the object passed to the constructor as an observer on |source|.
62 void AddObservation(Source* source) {
63 sources_.push_back(source);
64 (source->*AddObsFn)(observer_);
65 }
66
67 // Remove the object passed to the constructor as an observer from |source|.
68 void RemoveObservation(Source* source) {
69 auto it = base::ranges::find(sources_, source);
70 DCHECK(it != sources_.end());
71 sources_.erase(it);
72 (source->*RemoveObsFn)(observer_);
73 }
74
Sigurdur Asgeirsson11031652020-11-12 17:44:2575 // Remove the object passed to the constructor as an observer from all sources
76 // it's observing.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1777 void RemoveAllObservations() {
78 for (Source* source : sources_)
79 (source->*RemoveObsFn)(observer_);
80 sources_.clear();
81 }
82
Sigurdur Asgeirsson11031652020-11-12 17:44:2583 // Returns true if any source is being observed.
84 bool IsObservingAnySource() const { return !sources_.empty(); }
85
86 // Returns true if |source| is being observed.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1787 bool IsObservingSource(Source* source) const {
Sigurdur Asgeirsson61cc21542020-11-19 00:12:0788 DCHECK(source);
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1789 return base::Contains(sources_, source);
90 }
91
Sigurdur Asgeirsson11031652020-11-12 17:44:2592 // Returns the number of sources being observed.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1793 size_t GetSourcesCount() const { return sources_.size(); }
94
95 private:
Sigurdur Asgeirsson11031652020-11-12 17:44:2596 Observer* const observer_;
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1797
98 std::vector<Source*> sources_;
99};
100
101} // namespace base
102
103#endif // BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_