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