Home | History | Annotate | Download | only in fxcrt
      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:
     20     ObservedPtr() : m_pObservable(nullptr) {}
     21     explicit ObservedPtr(T* pObservable) : m_pObservable(pObservable) {
     22       if (m_pObservable)
     23         m_pObservable->AddObservedPtr(this);
     24     }
     25     ObservedPtr(const ObservedPtr& that) : ObservedPtr(that.Get()) {}
     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     }
     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; }
     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;
     60   ~Observable() { NotifyObservedPtrs(); }
     61   void AddObservedPtr(ObservedPtr* pObservedPtr) {
     62     ASSERT(!pdfium::ContainsKey(m_ObservedPtrs, pObservedPtr));
     63     m_ObservedPtrs.insert(pObservedPtr);
     64   }
     65   void RemoveObservedPtr(ObservedPtr* pObservedPtr) {
     66     ASSERT(pdfium::ContainsKey(m_ObservedPtrs, pObservedPtr));
     67     m_ObservedPtrs.erase(pObservedPtr);
     68   }
     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:
     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