1*6777b538SAndroid Build Coastguard Worker // Copyright 2020 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <stddef.h> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include <vector> 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker #include "base/check.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/containers/contains.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/scoped_observation_traits.h" 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker namespace base { 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker // ScopedMultiSourceObservation is used to keep track of plural observation, 21*6777b538SAndroid Build Coastguard Worker // e.g. where an observer observes more than a single source. 22*6777b538SAndroid Build Coastguard Worker // 23*6777b538SAndroid Build Coastguard Worker // Use base::ScopedObservation for objects that observe only a single source. 24*6777b538SAndroid Build Coastguard Worker // 25*6777b538SAndroid Build Coastguard Worker // When ScopedMultiSourceObservation is destroyed, it removes the object as an 26*6777b538SAndroid Build Coastguard Worker // observer from all sources it has been added to. 27*6777b538SAndroid Build Coastguard Worker // Basic example (as a member variable): 28*6777b538SAndroid Build Coastguard Worker // 29*6777b538SAndroid Build Coastguard Worker // class MyFooObserver : public FooObserver { 30*6777b538SAndroid Build Coastguard Worker // ... 31*6777b538SAndroid Build Coastguard Worker // private: 32*6777b538SAndroid Build Coastguard Worker // ScopedMultiSourceObservation<Foo, FooObserver> foo_observations_{this}; 33*6777b538SAndroid Build Coastguard Worker // }; 34*6777b538SAndroid Build Coastguard Worker // 35*6777b538SAndroid Build Coastguard Worker // MyFooObserver::OnFooCreated(Foo* foo) { 36*6777b538SAndroid Build Coastguard Worker // foo_observations_.AddObservation(foo); 37*6777b538SAndroid Build Coastguard Worker // } 38*6777b538SAndroid Build Coastguard Worker // 39*6777b538SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////// 40*6777b538SAndroid Build Coastguard Worker // 41*6777b538SAndroid Build Coastguard Worker // By default `ScopedMultiSourceObservation` only works with sources that expose 42*6777b538SAndroid Build Coastguard Worker // `AddObserver` and `RemoveObserver`. However, it's also possible to 43*6777b538SAndroid Build Coastguard Worker // adapt it to custom function names (say `AddFoo` and `RemoveFoo` accordingly) 44*6777b538SAndroid Build Coastguard Worker // by tailoring ScopedObservationTraits<> for the given Source and Observer -- 45*6777b538SAndroid Build Coastguard Worker // see `base/scoped_observation_traits.h` for details. 46*6777b538SAndroid Build Coastguard Worker // 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker template <class Source, class Observer> 49*6777b538SAndroid Build Coastguard Worker class ScopedMultiSourceObservation { 50*6777b538SAndroid Build Coastguard Worker public: ScopedMultiSourceObservation(Observer * observer)51*6777b538SAndroid Build Coastguard Worker explicit ScopedMultiSourceObservation(Observer* observer) 52*6777b538SAndroid Build Coastguard Worker : observer_(observer) {} 53*6777b538SAndroid Build Coastguard Worker ScopedMultiSourceObservation(const ScopedMultiSourceObservation&) = delete; 54*6777b538SAndroid Build Coastguard Worker ScopedMultiSourceObservation& operator=(const ScopedMultiSourceObservation&) = 55*6777b538SAndroid Build Coastguard Worker delete; ~ScopedMultiSourceObservation()56*6777b538SAndroid Build Coastguard Worker ~ScopedMultiSourceObservation() { RemoveAllObservations(); } 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker // Adds the object passed to the constructor as an observer on |source|. AddObservation(Source * source)59*6777b538SAndroid Build Coastguard Worker void AddObservation(Source* source) { 60*6777b538SAndroid Build Coastguard Worker CHECK(!IsObservingSource(source)); 61*6777b538SAndroid Build Coastguard Worker sources_.push_back(source); 62*6777b538SAndroid Build Coastguard Worker Traits::AddObserver(source, observer_); 63*6777b538SAndroid Build Coastguard Worker } 64*6777b538SAndroid Build Coastguard Worker 65*6777b538SAndroid Build Coastguard Worker // Remove the object passed to the constructor as an observer from |source|. RemoveObservation(Source * source)66*6777b538SAndroid Build Coastguard Worker void RemoveObservation(Source* source) { 67*6777b538SAndroid Build Coastguard Worker auto it = base::ranges::find(sources_, source); 68*6777b538SAndroid Build Coastguard Worker CHECK(it != sources_.end()); 69*6777b538SAndroid Build Coastguard Worker sources_.erase(it); 70*6777b538SAndroid Build Coastguard Worker Traits::RemoveObserver(source, observer_); 71*6777b538SAndroid Build Coastguard Worker } 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard Worker // Remove the object passed to the constructor as an observer from all sources 74*6777b538SAndroid Build Coastguard Worker // it's observing. RemoveAllObservations()75*6777b538SAndroid Build Coastguard Worker void RemoveAllObservations() { 76*6777b538SAndroid Build Coastguard Worker for (Source* source : sources_) { 77*6777b538SAndroid Build Coastguard Worker Traits::RemoveObserver(source, observer_); 78*6777b538SAndroid Build Coastguard Worker } 79*6777b538SAndroid Build Coastguard Worker sources_.clear(); 80*6777b538SAndroid Build Coastguard Worker } 81*6777b538SAndroid Build Coastguard Worker 82*6777b538SAndroid Build Coastguard Worker // Returns true if any source is being observed. IsObservingAnySource()83*6777b538SAndroid Build Coastguard Worker bool IsObservingAnySource() const { return !sources_.empty(); } 84*6777b538SAndroid Build Coastguard Worker 85*6777b538SAndroid Build Coastguard Worker // Returns true if |source| is being observed. IsObservingSource(Source * source)86*6777b538SAndroid Build Coastguard Worker bool IsObservingSource(Source* source) const { 87*6777b538SAndroid Build Coastguard Worker DCHECK(source); 88*6777b538SAndroid Build Coastguard Worker return base::Contains(sources_, source); 89*6777b538SAndroid Build Coastguard Worker } 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker // Returns the number of sources being observed. GetSourcesCount()92*6777b538SAndroid Build Coastguard Worker size_t GetSourcesCount() const { return sources_.size(); } 93*6777b538SAndroid Build Coastguard Worker 94*6777b538SAndroid Build Coastguard Worker // Returns the sources being observed. Note: It is invalid to add or remove 95*6777b538SAndroid Build Coastguard Worker // sources while iterating on it. sources()96*6777b538SAndroid Build Coastguard Worker const std::vector<raw_ptr<Source>>& sources() const { return sources_; } 97*6777b538SAndroid Build Coastguard Worker 98*6777b538SAndroid Build Coastguard Worker private: 99*6777b538SAndroid Build Coastguard Worker using Traits = ScopedObservationTraits<Source, Observer>; 100*6777b538SAndroid Build Coastguard Worker 101*6777b538SAndroid Build Coastguard Worker const raw_ptr<Observer> observer_; 102*6777b538SAndroid Build Coastguard Worker 103*6777b538SAndroid Build Coastguard Worker std::vector<raw_ptr<Source>> sources_; 104*6777b538SAndroid Build Coastguard Worker }; 105*6777b538SAndroid Build Coastguard Worker 106*6777b538SAndroid Build Coastguard Worker } // namespace base 107*6777b538SAndroid Build Coastguard Worker 108*6777b538SAndroid Build Coastguard Worker #endif // BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_ 109