1 // Copyright 2020 The Chromium Authors 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/containers/contains.h" 14 #include "base/memory/raw_ptr.h" 15 #include "base/ranges/algorithm.h" 16 #include "base/scoped_observation_traits.h" 17 18 namespace base { 19 20 // ScopedMultiSourceObservation is used to keep track of plural observation, 21 // e.g. where an observer observes more than a single source. 22 // 23 // Use base::ScopedObservation for objects that observe only a single source. 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> foo_observations_{this}; 33 // }; 34 // 35 // MyFooObserver::OnFooCreated(Foo* foo) { 36 // foo_observations_.AddObservation(foo); 37 // } 38 // 39 //////////////////////////////////////////////////////////////////////////////// 40 // 41 // 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) 44 // by tailoring ScopedObservationTraits<> for the given Source and Observer -- 45 // see `base/scoped_observation_traits.h` for details. 46 // 47 48 template <class Source, class Observer> 49 class ScopedMultiSourceObservation { 50 public: ScopedMultiSourceObservation(Observer * observer)51 explicit ScopedMultiSourceObservation(Observer* observer) 52 : observer_(observer) {} 53 ScopedMultiSourceObservation(const ScopedMultiSourceObservation&) = delete; 54 ScopedMultiSourceObservation& operator=(const ScopedMultiSourceObservation&) = 55 delete; ~ScopedMultiSourceObservation()56 ~ScopedMultiSourceObservation() { RemoveAllObservations(); } 57 58 // Adds the object passed to the constructor as an observer on |source|. AddObservation(Source * source)59 void AddObservation(Source* source) { 60 sources_.push_back(source); 61 Traits::AddObserver(source, observer_); 62 } 63 64 // Remove the object passed to the constructor as an observer from |source|. RemoveObservation(Source * source)65 void RemoveObservation(Source* source) { 66 auto it = base::ranges::find(sources_, source); 67 CHECK(it != sources_.end()); 68 sources_.erase(it); 69 Traits::RemoveObserver(source, observer_); 70 } 71 72 // Remove the object passed to the constructor as an observer from all sources 73 // it's observing. RemoveAllObservations()74 void RemoveAllObservations() { 75 for (Source* source : sources_) { 76 Traits::RemoveObserver(source, observer_); 77 } 78 sources_.clear(); 79 } 80 81 // Returns true if any source is being observed. IsObservingAnySource()82 bool IsObservingAnySource() const { return !sources_.empty(); } 83 84 // Returns true if |source| is being observed. IsObservingSource(Source * source)85 bool IsObservingSource(Source* source) const { 86 DCHECK(source); 87 return base::Contains(sources_, source); 88 } 89 90 // Returns the number of sources being observed. GetSourcesCount()91 size_t GetSourcesCount() const { return sources_.size(); } 92 93 private: 94 using Traits = ScopedObservationTraits<Source, Observer>; 95 96 const raw_ptr<Observer> observer_; 97 98 std::vector<raw_ptr<Source>> sources_; 99 }; 100 101 } // namespace base 102 103 #endif // BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_ 104