1 // Copyright 2016 The PDFium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CORE_FXCRT_OBSERVED_PTR_H_ 6 #define CORE_FXCRT_OBSERVED_PTR_H_ 7 8 #include <stddef.h> 9 10 #include <set> 11 12 #include "core/fxcrt/check.h" 13 #include "core/fxcrt/unowned_ptr_exclusion.h" 14 15 namespace fxcrt { 16 17 class Observable { 18 public: 19 // General-purpose interface for more complicated cleanup. 20 class ObserverIface { 21 public: 22 virtual ~ObserverIface() = default; 23 virtual void OnObservableDestroyed() = 0; 24 }; 25 26 Observable(); 27 Observable(const Observable& that) = delete; 28 Observable& operator=(const Observable& that) = delete; 29 ~Observable(); 30 31 void AddObserver(ObserverIface* pObserver); 32 void RemoveObserver(ObserverIface* pObserver); 33 void NotifyObservers(); 34 35 protected: ActiveObserversForTesting()36 size_t ActiveObserversForTesting() const { return m_Observers.size(); } 37 38 private: 39 std::set<ObserverIface*> m_Observers; 40 }; 41 42 // Simple case of a self-nulling pointer. 43 // Generally, pass ObservedPtr<> by non-const reference since this saves 44 // considerable work compared to pass by value. 45 // NOTE: Once an UnownedPtr<> is made from an underlying reference, the 46 // best practice is to only refer to that object by the UnownedPtr<> and 47 // not the original reference. 48 template <typename T> 49 class ObservedPtr final : public Observable::ObserverIface { 50 public: 51 ObservedPtr() = default; ObservedPtr(T * pObservable)52 explicit ObservedPtr(T* pObservable) : m_pObservable(pObservable) { 53 if (m_pObservable) 54 m_pObservable->AddObserver(this); 55 } ObservedPtr(const ObservedPtr & that)56 ObservedPtr(const ObservedPtr& that) : ObservedPtr(that.Get()) {} ~ObservedPtr()57 ~ObservedPtr() override { 58 if (m_pObservable) 59 m_pObservable->RemoveObserver(this); 60 } 61 void Reset(T* pObservable = nullptr) { 62 if (m_pObservable) 63 m_pObservable->RemoveObserver(this); 64 m_pObservable = pObservable; 65 if (m_pObservable) 66 m_pObservable->AddObserver(this); 67 } OnObservableDestroyed()68 void OnObservableDestroyed() override { 69 DCHECK(m_pObservable); 70 m_pObservable = nullptr; 71 } HasObservable()72 bool HasObservable() const { return !!m_pObservable; } 73 ObservedPtr& operator=(const ObservedPtr& that) { 74 Reset(that.Get()); 75 return *this; 76 } 77 bool operator==(const ObservedPtr& that) const { 78 return m_pObservable == that.m_pObservable; 79 } 80 bool operator!=(const ObservedPtr& that) const { return !(*this == that); } 81 82 template <typename U> 83 bool operator==(const U* that) const { 84 return Get() == that; 85 } 86 87 template <typename U> 88 bool operator!=(const U* that) const { 89 return !(*this == that); 90 } 91 92 explicit operator bool() const { return HasObservable(); } Get()93 T* Get() const { return m_pObservable; } 94 T& operator*() const { return *m_pObservable; } 95 T* operator->() const { return m_pObservable; } 96 97 private: 98 UNOWNED_PTR_EXCLUSION T* m_pObservable = nullptr; 99 }; 100 101 template <typename T, typename U> 102 inline bool operator==(const U* lhs, const ObservedPtr<T>& rhs) { 103 return rhs == lhs; 104 } 105 106 template <typename T, typename U> 107 inline bool operator!=(const U* lhs, const ObservedPtr<T>& rhs) { 108 return rhs != lhs; 109 } 110 111 } // namespace fxcrt 112 113 using fxcrt::Observable; 114 using fxcrt::ObservedPtr; 115 116 #endif // CORE_FXCRT_OBSERVED_PTR_H_ 117