| // Copyright 2016 The PDFium Authors |
| // 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 <stddef.h> |
| |
| #include <set> |
| |
| #include "core/fxcrt/unowned_ptr_exclusion.h" |
| #include "third_party/base/check.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. |
| // Generally, pass ObservedPtr<> by non-const reference since this saves |
| // considerable work compared to pass by value. |
| 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 { |
| DCHECK(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: |
| UNOWNED_PTR_EXCLUSION 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_ |