1 // Copyright 2016 PDFium Authors. All rights reserved. 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_OBSERVABLE_H_ 6 #define CORE_FXCRT_OBSERVABLE_H_ 7 8 #include <set> 9 10 #include "core/fxcrt/fx_system.h" 11 #include "third_party/base/stl_util.h" 12 13 namespace fxcrt { 14 15 template <class T> 16 class Observable { 17 public: 18 class ObservedPtr { 19 public: ObservedPtr()20 ObservedPtr() : m_pObservable(nullptr) {} ObservedPtr(T * pObservable)21 explicit ObservedPtr(T* pObservable) : m_pObservable(pObservable) { 22 if (m_pObservable) 23 m_pObservable->AddObservedPtr(this); 24 } ObservedPtr(const ObservedPtr & that)25 ObservedPtr(const ObservedPtr& that) : ObservedPtr(that.Get()) {} ~ObservedPtr()26 ~ObservedPtr() { 27 if (m_pObservable) 28 m_pObservable->RemoveObservedPtr(this); 29 } 30 void Reset(T* pObservable = nullptr) { 31 if (m_pObservable) 32 m_pObservable->RemoveObservedPtr(this); 33 m_pObservable = pObservable; 34 if (m_pObservable) 35 m_pObservable->AddObservedPtr(this); 36 } OnDestroy()37 void OnDestroy() { 38 ASSERT(m_pObservable); 39 m_pObservable = nullptr; 40 } 41 ObservedPtr& operator=(const ObservedPtr& that) { 42 Reset(that.Get()); 43 return *this; 44 } 45 bool operator==(const ObservedPtr& that) const { 46 return m_pObservable == that.m_pObservable; 47 } 48 bool operator!=(const ObservedPtr& that) const { return !(*this == that); } 49 explicit operator bool() const { return !!m_pObservable; } Get()50 T* Get() const { return m_pObservable; } 51 T& operator*() const { return *m_pObservable; } 52 T* operator->() const { return m_pObservable; } 53 54 private: 55 T* m_pObservable; 56 }; 57 58 Observable() = default; 59 Observable(const Observable& that) = delete; ~Observable()60 ~Observable() { NotifyObservedPtrs(); } AddObservedPtr(ObservedPtr * pObservedPtr)61 void AddObservedPtr(ObservedPtr* pObservedPtr) { 62 ASSERT(!pdfium::ContainsKey(m_ObservedPtrs, pObservedPtr)); 63 m_ObservedPtrs.insert(pObservedPtr); 64 } RemoveObservedPtr(ObservedPtr * pObservedPtr)65 void RemoveObservedPtr(ObservedPtr* pObservedPtr) { 66 ASSERT(pdfium::ContainsKey(m_ObservedPtrs, pObservedPtr)); 67 m_ObservedPtrs.erase(pObservedPtr); 68 } NotifyObservedPtrs()69 void NotifyObservedPtrs() { 70 for (auto* pObservedPtr : m_ObservedPtrs) 71 pObservedPtr->OnDestroy(); 72 m_ObservedPtrs.clear(); 73 } 74 Observable& operator=(const Observable& that) = delete; 75 76 protected: ActiveObservedPtrsForTesting()77 size_t ActiveObservedPtrsForTesting() const { return m_ObservedPtrs.size(); } 78 79 private: 80 std::set<ObservedPtr*> m_ObservedPtrs; 81 }; 82 83 } // namespace fxcrt 84 85 using fxcrt::Observable; 86 87 #endif // CORE_FXCRT_OBSERVABLE_H_ 88