1 // 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 16 namespace base { 17 18 // ScopedMultiSourceObservation is used to keep track of plural observation, 19 // e.g. where an observer observes more than a single source. 20 // 21 // Use base::ScopedObservation for objects that observe only a single source. 22 // This class and base::ScopedObservation replace ScopedObserver. 23 // 24 // When ScopedMultiSourceObservation is destroyed, it removes the object as an 25 // 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: 31 // ScopedMultiSourceObservation<Foo, FooObserver> foo_observations_{this}; 32 // }; 33 // 34 // MyFooObserver::OnFooCreated(Foo* foo) { 35 // foo_observations_.AddObservation(foo); 36 // } 37 // 38 // For cases with methods not named AddObserver/RemoveObserver: 39 // 40 // class MyFooStateObserver : public FooStateObserver { 41 // ... 42 // private: 43 // ScopedMultiSourceObservation<Foo, 44 // FooStateObserver, 45 // &Foo::AddStateObserver, 46 // &Foo::RemoveStateObserver> 47 // foo_observations_{this}; 48 // }; 49 template <class Source, 50 class Observer, 51 void (Source::*AddObsFn)(Observer*) = &Source::AddObserver, 52 void (Source::*RemoveObsFn)(Observer*) = &Source::RemoveObserver> 53 class ScopedMultiSourceObservation { 54 public: ScopedMultiSourceObservation(Observer * observer)55 explicit ScopedMultiSourceObservation(Observer* observer) 56 : observer_(observer) {} 57 ScopedMultiSourceObservation(const ScopedMultiSourceObservation&) = delete; 58 ScopedMultiSourceObservation& operator=(const ScopedMultiSourceObservation&) = 59 delete; ~ScopedMultiSourceObservation()60 ~ScopedMultiSourceObservation() { RemoveAllObservations(); } 61 62 // Adds the object passed to the constructor as an observer on |source|. AddObservation(Source * 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|. RemoveObservation(Source * 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 76 // Remove the object passed to the constructor as an observer from all sources 77 // it's observing. RemoveAllObservations()78 void RemoveAllObservations() { 79 for (Source* source : sources_) 80 (source->*RemoveObsFn)(observer_); 81 sources_.clear(); 82 } 83 84 // Returns true if any source is being observed. IsObservingAnySource()85 bool IsObservingAnySource() const { return !sources_.empty(); } 86 87 // Returns true if |source| is being observed. IsObservingSource(Source * source)88 bool IsObservingSource(Source* source) const { 89 return base::Contains(sources_, source); 90 } 91 92 // Returns the number of sources being observed. GetSourcesCount()93 size_t GetSourcesCount() const { return sources_.size(); } 94 95 private: 96 Observer* const observer_; 97 98 std::vector<Source*> sources_; 99 }; 100 101 } // namespace base 102 103 #endif // BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_ 104