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_OBSERVED_PTR_H_
6 #define CORE_FXCRT_OBSERVED_PTR_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 class Observable {
16  public:
17   // General-purpose interface for more complicated cleanup.
18   class ObserverIface {
19    public:
20     virtual ~ObserverIface() = default;
21     virtual void OnObservableDestroyed() = 0;
22   };
23 
24   Observable();
25   Observable(const Observable& that) = delete;
26   ~Observable();
AddObserver(ObserverIface * pObserver)27   void AddObserver(ObserverIface* pObserver) {
28     ASSERT(!pdfium::ContainsKey(m_Observers, pObserver));
29     m_Observers.insert(pObserver);
30   }
RemoveObserver(ObserverIface * pObserver)31   void RemoveObserver(ObserverIface* pObserver) {
32     ASSERT(pdfium::ContainsKey(m_Observers, pObserver));
33     m_Observers.erase(pObserver);
34   }
NotifyObservers()35   void NotifyObservers() {
36     for (auto* pObserver : m_Observers)
37       pObserver->OnObservableDestroyed();
38     m_Observers.clear();
39   }
40   Observable& operator=(const Observable& that) = delete;
41 
42  protected:
ActiveObserversForTesting()43   size_t ActiveObserversForTesting() const { return m_Observers.size(); }
44 
45  private:
46   std::set<ObserverIface*> m_Observers;
47 };
48 
49 // Simple case of a self-nulling pointer.
50 template <typename T>
51 class ObservedPtr final : public Observable::ObserverIface {
52  public:
53   ObservedPtr() = default;
ObservedPtr(T * pObservable)54   explicit ObservedPtr(T* pObservable) : m_pObservable(pObservable) {
55     if (m_pObservable)
56       m_pObservable->AddObserver(this);
57   }
ObservedPtr(const ObservedPtr & that)58   ObservedPtr(const ObservedPtr& that) : ObservedPtr(that.Get()) {}
~ObservedPtr()59   ~ObservedPtr() override {
60     if (m_pObservable)
61       m_pObservable->RemoveObserver(this);
62   }
63   void Reset(T* pObservable = nullptr) {
64     if (m_pObservable)
65       m_pObservable->RemoveObserver(this);
66     m_pObservable = pObservable;
67     if (m_pObservable)
68       m_pObservable->AddObserver(this);
69   }
OnObservableDestroyed()70   void OnObservableDestroyed() override {
71     ASSERT(m_pObservable);
72     m_pObservable = nullptr;
73   }
HasObservable()74   bool HasObservable() const { return !!m_pObservable; }
75   ObservedPtr& operator=(const ObservedPtr& that) {
76     Reset(that.Get());
77     return *this;
78   }
79   bool operator==(const ObservedPtr& that) const {
80     return m_pObservable == that.m_pObservable;
81   }
82   bool operator!=(const ObservedPtr& that) const { return !(*this == that); }
83 
84   template <typename U>
85   bool operator==(const U* that) const {
86     return Get() == that;
87   }
88 
89   template <typename U>
90   bool operator!=(const U* that) const {
91     return !(*this == that);
92   }
93 
94   explicit operator bool() const { return HasObservable(); }
Get()95   T* Get() const { return m_pObservable; }
96   T& operator*() const { return *m_pObservable; }
97   T* operator->() const { return m_pObservable; }
98 
99  private:
100   T* m_pObservable = nullptr;
101 };
102 
103 template <typename T, typename U>
104 inline bool operator==(const U* lhs, const ObservedPtr<T>& rhs) {
105   return rhs == lhs;
106 }
107 
108 template <typename T, typename U>
109 inline bool operator!=(const U* lhs, const ObservedPtr<T>& rhs) {
110   return rhs != lhs;
111 }
112 
113 }  // namespace fxcrt
114 
115 using fxcrt::Observable;
116 using fxcrt::ObservedPtr;
117 
118 #endif  // CORE_FXCRT_OBSERVED_PTR_H_
119