• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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