|  | // Copyright 2016 PDFium 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 CORE_FXCRT_OBSERVED_PTR_H_ | 
|  | #define CORE_FXCRT_OBSERVED_PTR_H_ | 
|  |  | 
|  | #include <set> | 
|  |  | 
|  | #include "core/fxcrt/fx_system.h" | 
|  | #include "third_party/base/stl_util.h" | 
|  |  | 
|  | namespace fxcrt { | 
|  |  | 
|  | class Observable { | 
|  | public: | 
|  | // General-purpose interface for more complicated cleanup. | 
|  | class ObserverIface { | 
|  | public: | 
|  | virtual ~ObserverIface() = default; | 
|  | virtual void OnObservableDestroyed() = 0; | 
|  | }; | 
|  |  | 
|  | Observable(); | 
|  | Observable(const Observable& that) = delete; | 
|  | ~Observable(); | 
|  | void AddObserver(ObserverIface* pObserver) { | 
|  | ASSERT(!pdfium::ContainsKey(m_Observers, pObserver)); | 
|  | m_Observers.insert(pObserver); | 
|  | } | 
|  | void RemoveObserver(ObserverIface* pObserver) { | 
|  | ASSERT(pdfium::ContainsKey(m_Observers, pObserver)); | 
|  | m_Observers.erase(pObserver); | 
|  | } | 
|  | void NotifyObservers() { | 
|  | for (auto* pObserver : m_Observers) | 
|  | pObserver->OnObservableDestroyed(); | 
|  | m_Observers.clear(); | 
|  | } | 
|  | Observable& operator=(const Observable& that) = delete; | 
|  |  | 
|  | protected: | 
|  | size_t ActiveObserversForTesting() const { return m_Observers.size(); } | 
|  |  | 
|  | private: | 
|  | std::set<ObserverIface*> m_Observers; | 
|  | }; | 
|  |  | 
|  | // Simple case of a self-nulling pointer. | 
|  | template <typename T> | 
|  | class ObservedPtr final : public Observable::ObserverIface { | 
|  | public: | 
|  | ObservedPtr() = default; | 
|  | explicit ObservedPtr(T* pObservable) : m_pObservable(pObservable) { | 
|  | if (m_pObservable) | 
|  | m_pObservable->AddObserver(this); | 
|  | } | 
|  | ObservedPtr(const ObservedPtr& that) : ObservedPtr(that.Get()) {} | 
|  | ~ObservedPtr() override { | 
|  | if (m_pObservable) | 
|  | m_pObservable->RemoveObserver(this); | 
|  | } | 
|  | void Reset(T* pObservable = nullptr) { | 
|  | if (m_pObservable) | 
|  | m_pObservable->RemoveObserver(this); | 
|  | m_pObservable = pObservable; | 
|  | if (m_pObservable) | 
|  | m_pObservable->AddObserver(this); | 
|  | } | 
|  | void OnObservableDestroyed() override { | 
|  | ASSERT(m_pObservable); | 
|  | m_pObservable = nullptr; | 
|  | } | 
|  | bool HasObservable() const { return !!m_pObservable; } | 
|  | ObservedPtr& operator=(const ObservedPtr& that) { | 
|  | Reset(that.Get()); | 
|  | return *this; | 
|  | } | 
|  | bool operator==(const ObservedPtr& that) const { | 
|  | return m_pObservable == that.m_pObservable; | 
|  | } | 
|  | bool operator!=(const ObservedPtr& that) const { return !(*this == that); } | 
|  | explicit operator bool() const { return HasObservable(); } | 
|  | T* Get() const { return m_pObservable; } | 
|  | T& operator*() const { return *m_pObservable; } | 
|  | T* operator->() const { return m_pObservable; } | 
|  |  | 
|  | private: | 
|  | T* m_pObservable = nullptr; | 
|  | }; | 
|  |  | 
|  | }  // namespace fxcrt | 
|  |  | 
|  | using fxcrt::Observable; | 
|  | using fxcrt::ObservedPtr; | 
|  |  | 
|  | #endif  // CORE_FXCRT_OBSERVED_PTR_H_ |