// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_ #define BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_ #include #include #include "base/check.h" #include "base/containers/contains.h" #include "base/memory/raw_ptr.h" #include "base/ranges/algorithm.h" namespace base { // ScopedMultiSourceObservation is used to keep track of plural observation, // e.g. where an observer observes more than a single source. // // Use base::ScopedObservation for objects that observe only a single source. // // When ScopedMultiSourceObservation is destroyed, it removes the object as an // observer from all sources it has been added to. // Basic example (as a member variable): // // class MyFooObserver : public FooObserver { // ... // private: // ScopedMultiSourceObservation foo_observations_{this}; // }; // // MyFooObserver::OnFooCreated(Foo* foo) { // foo_observations_.AddObservation(foo); // } // // For cases with methods not named AddObserver/RemoveObserver: // // class MyFooStateObserver : public FooStateObserver { // ... // private: // ScopedMultiSourceObservation // foo_observations_{this}; // }; template class ScopedMultiSourceObservation { public: explicit ScopedMultiSourceObservation(Observer* observer) : observer_(observer) {} ScopedMultiSourceObservation(const ScopedMultiSourceObservation&) = delete; ScopedMultiSourceObservation& operator=(const ScopedMultiSourceObservation&) = delete; ~ScopedMultiSourceObservation() { RemoveAllObservations(); } // Adds the object passed to the constructor as an observer on |source|. void AddObservation(Source* source) { sources_.push_back(source); (source->*AddObsFn)(observer_); } // Remove the object passed to the constructor as an observer from |source|. void RemoveObservation(Source* source) { auto it = base::ranges::find(sources_, source); DCHECK(it != sources_.end()); sources_.erase(it); (source->*RemoveObsFn)(observer_); } // Remove the object passed to the constructor as an observer from all sources // it's observing. void RemoveAllObservations() { for (Source* source : sources_) (source->*RemoveObsFn)(observer_); sources_.clear(); } // Returns true if any source is being observed. bool IsObservingAnySource() const { return !sources_.empty(); } // Returns true if |source| is being observed. bool IsObservingSource(Source* source) const { DCHECK(source); return base::Contains(sources_, source); } // Returns the number of sources being observed. size_t GetSourcesCount() const { return sources_.size(); } private: const raw_ptr observer_; std::vector sources_; }; } // namespace base #endif // BASE_SCOPED_MULTI_SOURCE_OBSERVATION_H_