Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/layers/AtomicRefCountedWithFinalize.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
#ifndef MOZILLA_ATOMICREFCOUNTEDWITHFINALIZE_H_
8
#define MOZILLA_ATOMICREFCOUNTEDWITHFINALIZE_H_
9
10
#include "mozilla/RefPtr.h"
11
#include "mozilla/Likely.h"
12
#include "MainThreadUtils.h"
13
#include "base/message_loop.h"
14
#include "base/task.h"
15
#include "mozilla/gfx/Logging.h"
16
17
0
#define ADDREF_MANUALLY(obj)  (obj)->AddRefManually(__FUNCTION__, __FILE__, __LINE__)
18
0
#define RELEASE_MANUALLY(obj)  (obj)->ReleaseManually(__FUNCTION__, __FILE__, __LINE__)
19
20
namespace mozilla {
21
22
template<class U>
23
class StaticRefPtr;
24
25
namespace gl {
26
template<typename T>
27
class RefSet;
28
29
template<typename T>
30
class RefQueue;
31
} // namespace gl
32
33
template<typename T>
34
class AtomicRefCountedWithFinalize
35
{
36
protected:
37
    explicit AtomicRefCountedWithFinalize(const char* aName)
38
      : mRecycleCallback(nullptr)
39
      , mClosure(nullptr)
40
      , mRefCount(0)
41
#ifdef DEBUG
42
      , mSpew(false)
43
      , mManualAddRefs(0)
44
      , mManualReleases(0)
45
#endif
46
#ifdef NS_BUILD_REFCNT_LOGGING
47
      , mName(aName)
48
#endif
49
0
    {}
Unexecuted instantiation: mozilla::AtomicRefCountedWithFinalize<mozilla::layers::TextureClient>::AtomicRefCountedWithFinalize(char const*)
Unexecuted instantiation: mozilla::AtomicRefCountedWithFinalize<mozilla::layers::TextureHost>::AtomicRefCountedWithFinalize(char const*)
50
51
0
    ~AtomicRefCountedWithFinalize() {
52
0
      if (mRefCount >= 0) {
53
0
        gfxCriticalError() << "Deleting referenced object? " << mRefCount;
54
0
      }
55
0
    }
Unexecuted instantiation: mozilla::AtomicRefCountedWithFinalize<mozilla::layers::TextureClient>::~AtomicRefCountedWithFinalize()
Unexecuted instantiation: mozilla::AtomicRefCountedWithFinalize<mozilla::layers::TextureHost>::~AtomicRefCountedWithFinalize()
56
57
public:
58
    // Mark user classes that are considered flawless.
59
    template<class U>
60
    friend class ::mozilla::StaticRefPtr;
61
62
    template<class U>
63
    friend struct mozilla::RefPtrTraits;
64
65
    template<typename U>
66
    friend class ::mozilla::gl::RefSet;
67
68
    template<typename U>
69
    friend class ::mozilla::gl::RefQueue;
70
71
    //friend class mozilla::gl::SurfaceFactory;
72
73
0
    void AddRefManually(const char* funcName, const char* fileName, uint32_t lineNum) {
74
#ifdef DEBUG
75
      uint32_t count = ++mManualAddRefs;
76
      if (mSpew) {
77
        printf_stderr("AddRefManually() #%u in %s at %s:%u\n", count, funcName,
78
                      fileName, lineNum);
79
      }
80
#else
81
      (void)funcName;
82
0
      (void)fileName;
83
0
      (void)lineNum;
84
0
#endif
85
0
      AddRef();
86
0
    }
87
88
0
    void ReleaseManually(const char* funcName, const char* fileName, uint32_t lineNum) {
89
#ifdef DEBUG
90
      uint32_t count = ++mManualReleases;
91
      if (mSpew) {
92
        printf_stderr("ReleaseManually() #%u in %s at %s:%u\n", count, funcName,
93
                      fileName, lineNum);
94
      }
95
#else
96
      (void)funcName;
97
0
      (void)fileName;
98
0
      (void)lineNum;
99
0
#endif
100
0
      Release();
101
0
    }
102
103
private:
104
0
    void AddRef() {
105
0
      MOZ_ASSERT(mRefCount >= 0, "AddRef() during/after Finalize()/dtor.");
106
#ifdef NS_BUILD_REFCNT_LOGGING
107
      int currCount = ++mRefCount;
108
      NS_LOG_ADDREF(this, currCount, mName, sizeof(*this));
109
#else
110
      ++mRefCount;
111
0
#endif
112
0
    }
Unexecuted instantiation: mozilla::AtomicRefCountedWithFinalize<mozilla::layers::TextureClient>::AddRef()
Unexecuted instantiation: mozilla::AtomicRefCountedWithFinalize<mozilla::layers::TextureHost>::AddRef()
113
114
0
    void Release() {
115
0
      MOZ_ASSERT(mRefCount > 0, "Release() during/after Finalize()/dtor.");
116
0
      // Read mRecycleCallback early so that it does not get set to
117
0
      // deleted memory, if the object is goes away.  See bug 994903.
118
0
      // This saves us in the case where there is no callback, so that
119
0
      // we can do the "else if" below.
120
0
      RecycleCallback recycleCallback = mRecycleCallback;
121
0
      int currCount = --mRefCount;
122
0
      if (currCount < 0) {
123
0
        gfxCriticalError() << "Invalid reference count release" << currCount;
124
0
        ++mRefCount;
125
0
        return;
126
0
      }
127
#ifdef NS_BUILD_REFCNT_LOGGING
128
      NS_LOG_RELEASE(this, currCount, mName);
129
#endif
130
131
0
      if (0 == currCount) {
132
0
        mRefCount = detail::DEAD;
133
0
        MOZ_ASSERT(IsDead());
134
0
135
0
        // Recycle listeners must call ClearRecycleCallback
136
0
        // before releasing their strong reference.
137
0
        if (mRecycleCallback) {
138
0
          gfxCriticalError() << "About to release with valid callback";
139
0
          mRecycleCallback = nullptr;
140
0
        }
141
0
142
0
        MOZ_ASSERT(mManualAddRefs == mManualReleases);
143
0
144
0
        T* derived = static_cast<T*>(this);
145
0
        derived->Finalize();
146
0
        delete derived;
147
0
      } else if (1 == currCount && recycleCallback) {
148
0
        // There is nothing enforcing this in the code, except how the callers
149
0
        // are being careful to never let the reference count go down if there
150
0
        // is a callback.
151
0
        MOZ_ASSERT(!IsDead());
152
0
        T* derived = static_cast<T*>(this);
153
0
        recycleCallback(derived, mClosure);
154
0
      }
155
0
    }
Unexecuted instantiation: mozilla::AtomicRefCountedWithFinalize<mozilla::layers::TextureClient>::Release()
Unexecuted instantiation: mozilla::AtomicRefCountedWithFinalize<mozilla::layers::TextureHost>::Release()
156
157
public:
158
    typedef void (*RecycleCallback)(T* aObject, void* aClosure);
159
    /**
160
     * Set a callback responsible for recycling this object
161
     * before it is finalized.
162
     */
163
    void SetRecycleCallback(RecycleCallback aCallback, void* aClosure)
164
0
    {
165
0
      MOZ_ASSERT(!IsDead());
166
0
      mRecycleCallback = aCallback;
167
0
      mClosure = aClosure;
168
0
    }
169
    void ClearRecycleCallback()
170
0
    {
171
0
      MOZ_ASSERT(!IsDead());
172
0
      SetRecycleCallback(nullptr, nullptr);
173
0
    }
174
175
    bool HasRecycleCallback() const
176
    {
177
      MOZ_ASSERT(!IsDead());
178
      return !!mRecycleCallback;
179
    }
180
181
    bool IsDead() const
182
    {
183
      return mRefCount < 0;
184
    }
185
186
    bool HasOneRef() const
187
    {
188
      return mRefCount == 1;
189
    }
190
191
private:
192
    RecycleCallback mRecycleCallback;
193
    void *mClosure;
194
    Atomic<int> mRefCount;
195
#ifdef DEBUG
196
public:
197
    bool mSpew;
198
private:
199
    Atomic<uint32_t> mManualAddRefs;
200
    Atomic<uint32_t> mManualReleases;
201
#endif
202
#ifdef NS_BUILD_REFCNT_LOGGING
203
    const char* mName;
204
#endif
205
};
206
207
} // namespace mozilla
208
209
#endif