blob: 14e7d1d4028765a39e352462f540288bb353f501 [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"
13#include "base/ranges/algorithm.h"
14#include "base/stl_util.h"
15
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.
22// This class and base::ScopedObservation replace ScopedObserver.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1723//
Sigurdur Asgeirsson11031652020-11-12 17:44:2524// When ScopedMultiSourceObservation is destroyed, it removes the object as an
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1725// observer from all sources it has been added to.
26// Basic example (as a member variable):
27//
28// class MyFooObserver : public FooObserver {
29// ...
30// private:
Sigurdur Asgeirsson11031652020-11-12 17:44:2531// ScopedMultiSourceObservation<Foo, FooObserver> foo_observations_{this};
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1732// };
33//
Sigurdur Asgeirsson11031652020-11-12 17:44:2534// MyFooObserver::OnFooCreated(Foo* foo) {
35// foo_observations_.AddObservation(foo);
36// }
37//
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1738// For cases with methods not named AddObserver/RemoveObserver:
39//
40// class MyFooStateObserver : public FooStateObserver {
41// ...
42// private:
Sigurdur Asgeirsson11031652020-11-12 17:44:2543// ScopedMultiSourceObservation<Foo,
44// FooStateObserver,
45// &Foo::AddStateObserver,
46// &Foo::RemoveStateObserver>
47// foo_observations_{this};
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1748// };
49template <class Source,
50 class Observer,
51 void (Source::*AddObsFn)(Observer*) = &Source::AddObserver,
52 void (Source::*RemoveObsFn)(Observer*) = &Source::RemoveObserver>
53class ScopedMultiSourceObservation {
54 public:
55 explicit ScopedMultiSourceObservation(Observer* observer)
56 : observer_(observer) {}
57 ScopedMultiSourceObservation(const ScopedMultiSourceObservation&) = delete;
58 ScopedMultiSourceObservation& operator=(const ScopedMultiSourceObservation&) =
59 delete;
60 ~ScopedMultiSourceObservation() { RemoveAllObservations(); }
61
62 // Adds the object passed to the constructor as an observer on |source|.
63 void AddObservation(Source* source) {
64 sources_.push_back(source);
65 (source->*AddObsFn)(observer_);
66 }
67
68 // Remove the object passed to the constructor as an observer from |source|.
69 void RemoveObservation(Source* source) {
70 auto it = base::ranges::find(sources_, source);
71 DCHECK(it != sources_.end());
72 sources_.erase(it);
73 (source->*RemoveObsFn)(observer_);
74 }
75
Sigurdur Asgeirsson11031652020-11-12 17:44:2576 // Remove the object passed to the constructor as an observer from all sources
77 // it's observing.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1778 void RemoveAllObservations() {
79 for (Source* source : sources_)
80 (source->*RemoveObsFn)(observer_);
81 sources_.clear();
82 }
83
Sigurdur Asgeirsson11031652020-11-12 17:44:2584 // Returns true if any source is being observed.
85 bool IsObservingAnySource() const { return !sources_.empty(); }
86
87 // Returns true if |source| is being observed.
Sigurdur Asgeirsson1a164fd2020-11-05 20:13:1788 bool IsObservingSource(Source* source) const {
89 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_