Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/ArenaRefPtr.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
 */
7
8
/* smart pointer for strong references to nsPresArena-allocated objects
9
   that might be held onto until the arena's destruction */
10
11
#include "mozilla/Assertions.h"
12
#include "mozilla/RefPtr.h"
13
14
#ifndef mozilla_ArenaRefPtr_h
15
#define mozilla_ArenaRefPtr_h
16
17
class nsPresArena;
18
19
namespace mozilla {
20
21
/**
22
 * A class for holding strong references to nsPresArena-allocated
23
 * objects.
24
 *
25
 * Since the arena's lifetime is not related to the refcounts
26
 * of the objects allocated within it, it is possible to have a strong
27
 * reference to an arena-allocated object that lives until the
28
 * destruction of the arena.  An ArenaRefPtr acts like a weak reference
29
 * in that it will clear its referent if the arena is about to go away.
30
 *
31
 * T must be a class that has these two methods:
32
 *
33
 *   static mozilla::ArenaObjectID ArenaObjectID();
34
 *   U* Arena();
35
 *
36
 * where U is a class that has these two methods:
37
 *
38
 *   void RegisterArenaRefPtr(ArenaRefPtr<T>*);
39
 *   void DeregisterArenaRefPtr(ArenaRefPtr<T>*);
40
 *
41
 * Currently, both nsPresArena and nsIPresShell can be used as U.
42
 *
43
 * The ArenaObjectID method must return the mozilla::ArenaObjectID that
44
 * uniquely identifies T, and the Arena method must return the nsPresArena
45
 * (or a proxy for it) in which the object was allocated.
46
 */
47
template<typename T>
48
class ArenaRefPtr
49
{
50
  friend class ::nsPresArena;
51
52
public:
53
  ArenaRefPtr()
54
0
  {
55
0
    AssertValidType();
56
0
  }
57
58
  template<typename I>
59
  MOZ_IMPLICIT ArenaRefPtr(already_AddRefed<I>& aRhs)
60
  {
61
    AssertValidType();
62
    assign(aRhs);
63
  }
64
65
  template<typename I>
66
  MOZ_IMPLICIT ArenaRefPtr(already_AddRefed<I>&& aRhs)
67
  {
68
    AssertValidType();
69
    assign(aRhs);
70
  }
71
72
  MOZ_IMPLICIT ArenaRefPtr(T* aRhs)
73
  {
74
    AssertValidType();
75
    assign(aRhs);
76
  }
77
78
  template<typename I>
79
  ArenaRefPtr<T>& operator=(already_AddRefed<I>& aRhs)
80
  {
81
    assign(aRhs);
82
    return *this;
83
  }
84
85
  template<typename I>
86
  ArenaRefPtr<T>& operator=(already_AddRefed<I>&& aRhs)
87
  {
88
    assign(aRhs);
89
    return *this;
90
  }
91
92
  ArenaRefPtr<T>& operator=(T* aRhs)
93
0
  {
94
0
    assign(aRhs);
95
0
    return *this;
96
0
  }
97
98
0
  ~ArenaRefPtr() { assign(nullptr); }
99
100
0
  operator T*() const & { return get(); }
101
  operator T*() const && = delete;
102
0
  explicit operator bool() const { return !!mPtr; }
103
0
  bool operator!() const { return !mPtr; }
104
0
  T* operator->() const { return mPtr.operator->(); }
105
0
  T& operator*() const { return *get(); }
106
107
0
  T* get() const { return mPtr; }
108
109
private:
110
  void AssertValidType();
111
112
  /**
113
   * Clears the pointer to the arena-allocated object but skips the usual
114
   * step of deregistering the ArenaRefPtr from the nsPresArena.  This
115
   * method is called by nsPresArena when clearing all registered ArenaRefPtrs
116
   * so that it can deregister them all at once, avoiding hash table churn.
117
   */
118
  void ClearWithoutDeregistering()
119
0
  {
120
0
    mPtr = nullptr;
121
0
  }
122
123
  template<typename I>
124
  void assign(already_AddRefed<I>& aSmartPtr)
125
  {
126
    RefPtr<T> newPtr(aSmartPtr);
127
    assignFrom(newPtr);
128
  }
129
130
  template<typename I>
131
  void assign(already_AddRefed<I>&& aSmartPtr)
132
  {
133
    RefPtr<T> newPtr(aSmartPtr);
134
    assignFrom(newPtr);
135
  }
136
137
0
  void assign(T* aPtr) { assignFrom(aPtr); }
138
139
  template<typename I>
140
  void assignFrom(I& aPtr)
141
0
  {
142
0
    if (aPtr == mPtr) {
143
0
      return;
144
0
    }
145
0
    bool sameArena = mPtr && aPtr && mPtr->Arena() == aPtr->Arena();
146
0
    if (mPtr && !sameArena) {
147
0
      MOZ_ASSERT(mPtr->Arena());
148
0
      mPtr->Arena()->DeregisterArenaRefPtr(this);
149
0
    }
150
0
    mPtr = std::move(aPtr);
151
0
    if (mPtr && !sameArena) {
152
0
      MOZ_ASSERT(mPtr->Arena());
153
0
      mPtr->Arena()->RegisterArenaRefPtr(this);
154
0
    }
155
0
  }
156
157
  RefPtr<T> mPtr;
158
};
159
160
} // namespace mozilla
161
162
#endif // mozilla_ArenaRefPtr_h