// 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_OBSERVATION_H_ #define BASE_SCOPED_OBSERVATION_H_ #include #include "base/check.h" #include "base/check_op.h" #include "base/memory/raw_ptr.h" namespace base { // ScopedObservation is used to keep track of singular observation, e.g. // where an observer observes a single source only. // // Use base::ScopedMultiSourceObservation for objects that observe multiple // sources. // // When ScopedObservation is destroyed, it removes the registered observation, // if any. Basic example (as a member variable): // // class MyFooObserver : public FooObserver { // ... // private: // ScopedObservation foo_observation_{this}; // }; // // MyFooObserver::MyFooObserver(Foo* foo) { // foo_observation_.Observe(foo); // } // // For cases with methods not named AddObserver/RemoveObserver: // // class MyFooStateObserver : public FooStateObserver { // ... // private: // ScopedObservation // foo_observation_{this}; // }; template class ScopedObservation { public: explicit ScopedObservation(Observer* observer) : observer_(observer) {} ScopedObservation(const ScopedObservation&) = delete; ScopedObservation& operator=(const ScopedObservation&) = delete; ~ScopedObservation() { Reset(); } // Adds the object passed to the constructor as an observer on |source|. // IsObserving() must be false. void Observe(Source* source) { // TODO(https://crbug.com/1145565): Make this a DCHECK once ScopedObserver // has been fully retired. CHECK_EQ(source_, nullptr); source_ = source; (source_.get()->*AddObsFn)(observer_); } // Remove the object passed to the constructor as an observer from |source_| // if currently observing. Does nothing otherwise. void Reset() { if (source_) { (source_.get()->*RemoveObsFn)(observer_); source_ = nullptr; } } // Returns true if any source is being observed. bool IsObserving() const { return source_ != nullptr; } // Returns true if |source| is being observed. bool IsObservingSource(Source* source) const { DCHECK(source); return source_ == source; } private: const raw_ptr observer_; // The observed source, if any. raw_ptr source_ = nullptr; }; } // namespace base #endif // BASE_SCOPED_OBSERVATION_H_