| // 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" | |
| 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& operator=(const Observable& that) = delete; | |
| ~Observable(); | |
| void AddObserver(ObserverIface* pObserver); | |
| void RemoveObserver(ObserverIface* pObserver); | |
| void NotifyObservers(); | |
| 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); } | |
| template <typename U> | |
| bool operator==(const U* that) const { | |
| return Get() == that; | |
| } | |
| template <typename U> | |
| bool operator!=(const U* 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; | |
| }; | |
| template <typename T, typename U> | |
| inline bool operator==(const U* lhs, const ObservedPtr<T>& rhs) { | |
| return rhs == lhs; | |
| } | |
| template <typename T, typename U> | |
| inline bool operator!=(const U* lhs, const ObservedPtr<T>& rhs) { | |
| return rhs != lhs; | |
| } | |
| } // namespace fxcrt | |
| using fxcrt::Observable; | |
| using fxcrt::ObservedPtr; | |
| #endif // CORE_FXCRT_OBSERVED_PTR_H_ |