xref: /aosp_15_r20/external/pdfium/core/fxcrt/observed_ptr.h (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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/unowned_ptr_exclusion.h"
13 #include "third_party/base/check.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 template <typename T>
46 class ObservedPtr final : public Observable::ObserverIface {
47  public:
48   ObservedPtr() = default;
ObservedPtr(T * pObservable)49   explicit ObservedPtr(T* pObservable) : m_pObservable(pObservable) {
50     if (m_pObservable)
51       m_pObservable->AddObserver(this);
52   }
ObservedPtr(const ObservedPtr & that)53   ObservedPtr(const ObservedPtr& that) : ObservedPtr(that.Get()) {}
~ObservedPtr()54   ~ObservedPtr() override {
55     if (m_pObservable)
56       m_pObservable->RemoveObserver(this);
57   }
58   void Reset(T* pObservable = nullptr) {
59     if (m_pObservable)
60       m_pObservable->RemoveObserver(this);
61     m_pObservable = pObservable;
62     if (m_pObservable)
63       m_pObservable->AddObserver(this);
64   }
OnObservableDestroyed()65   void OnObservableDestroyed() override {
66     DCHECK(m_pObservable);
67     m_pObservable = nullptr;
68   }
HasObservable()69   bool HasObservable() const { return !!m_pObservable; }
70   ObservedPtr& operator=(const ObservedPtr& that) {
71     Reset(that.Get());
72     return *this;
73   }
74   bool operator==(const ObservedPtr& that) const {
75     return m_pObservable == that.m_pObservable;
76   }
77   bool operator!=(const ObservedPtr& that) const { return !(*this == that); }
78 
79   template <typename U>
80   bool operator==(const U* that) const {
81     return Get() == that;
82   }
83 
84   template <typename U>
85   bool operator!=(const U* that) const {
86     return !(*this == that);
87   }
88 
89   explicit operator bool() const { return HasObservable(); }
Get()90   T* Get() const { return m_pObservable; }
91   T& operator*() const { return *m_pObservable; }
92   T* operator->() const { return m_pObservable; }
93 
94  private:
95   UNOWNED_PTR_EXCLUSION T* m_pObservable = nullptr;
96 };
97 
98 template <typename T, typename U>
99 inline bool operator==(const U* lhs, const ObservedPtr<T>& rhs) {
100   return rhs == lhs;
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 }  // namespace fxcrt
109 
110 using fxcrt::Observable;
111 using fxcrt::ObservedPtr;
112 
113 #endif  // CORE_FXCRT_OBSERVED_PTR_H_
114