blob: e450d39a5f1cb6c7402025725637d605d8a08f2f [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
18// ScopedMultiSourceObservation is used to keep track of the set of sources an
19// object has attached itself to as an observer.
20//
21// For objects that observe only a single source, use base::ScopedObservation
22// rather than this class. This class and base::ScopedObservation replace
23// ScopedObserver.
24//
25// When ScopedMultiSourceObservation is destroyed it removes the object as an
26// 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:
32// ScopedMultiSourceObservation<Foo, FooObserver> observed_foo_{this};
33// };
34//
35// For cases with methods not named AddObserver/RemoveObserver:
36//
37// class MyFooStateObserver : public FooStateObserver {
38// ...
39// private:
40// ScopedMultiSourceObservation<Foo,
41// FooStateObserver,
42// &Foo::AddStateObserver,
43// &Foo::RemoveStateObserver>
44// observed_foo_{this};
45// };
46template <class Source,
47 class Observer,
48 void (Source::*AddObsFn)(Observer*) = &Source::AddObserver,
49 void (Source::*RemoveObsFn)(Observer*) = &Source::RemoveObserver>
50class ScopedMultiSourceObservation {
51 public:
52 explicit ScopedMultiSourceObservation(Observer* observer)
53 : observer_(observer) {}
54 ScopedMultiSourceObservation(const ScopedMultiSourceObservation&) = delete;
55 ScopedMultiSourceObservation& operator=(const ScopedMultiSourceObservation&) =
56 delete;
57 ~ScopedMultiSourceObservation() { RemoveAllObservations(); }
58
59 // Adds the object passed to the constructor as an observer on |source|.
60 void AddObservation(Source* source) {
61 sources_.push_back(source);
62 (source->*AddObsFn)(observer_);
63 }
64
65 // Remove the object passed to the constructor as an observer from |source|.
66 void RemoveObservation(Source* source) {
67 auto it = base::ranges::find(sources_, source);
68 DCHECK(it != sources_.end());
69 sources_.erase(it);
70 (source->*RemoveObsFn)(observer_);
71 }
72
73 void RemoveAllObservations() {
74 for (Source* source : sources_)
75 (source->*RemoveObsFn)(observer_);
76 sources_.clear();
77 }
78
79 bool IsObservingSource(Source* source) const {
80 return base::Contains(sources_, source);
81 }
82
83 bool IsObservingAnySource() const { return !sources_.empty(); }
84
85 size_t GetSourcesCount() const { return sources_.size(); }
86
87 private:
88 Observer* observer_;
89
90 std::vector<Source*> sources_;
91};
92
93} // namespace base
94
95#endif // BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_