Bug 1869092 - Fix timeouts in browser_PanelMultiView.js. r=twisniewski,test-only
[gecko.git] / js / public / RefCounted.h
blobde5a72f2d8bbf1f602a321f5e41f66dcf8804573
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/. */
7 #ifndef js_RefCounted_h
8 #define js_RefCounted_h
10 #include "mozilla/Atomics.h"
11 #include "mozilla/RefCountType.h"
13 #include "js/Utility.h"
15 // These types implement the same interface as mozilla::(Atomic)RefCounted and
16 // must be used instead of mozilla::(Atomic)RefCounted for everything in
17 // SpiderMonkey. There are two reasons:
18 // - Release() needs to call js_delete, not delete
19 // - SpiderMonkey does not have MOZILLA_INTERNAL_API defined which can lead
20 // to ODR violations that show up as spurious leak reports when ref-counted
21 // types are allocated by SpiderMonkey and released by Gecko (or vice versa).
23 namespace js {
25 template <typename T>
26 class RefCounted {
27 static const MozRefCountType DEAD = 0xffffdead;
29 protected:
30 RefCounted() : mRefCnt(0) {}
31 ~RefCounted() { MOZ_ASSERT(mRefCnt == DEAD); }
33 public:
34 void AddRef() const {
35 MOZ_ASSERT(int32_t(mRefCnt) >= 0);
36 ++mRefCnt;
39 void Release() const {
40 MOZ_ASSERT(int32_t(mRefCnt) > 0);
41 MozRefCountType cnt = --mRefCnt;
42 if (0 == cnt) {
43 #ifdef DEBUG
44 mRefCnt = DEAD;
45 #endif
46 js_delete(const_cast<T*>(static_cast<const T*>(this)));
50 private:
51 mutable MozRefCountType mRefCnt;
54 template <typename T>
55 class AtomicRefCounted {
56 // On 64-bit systems, if the refcount type is small (say, 32 bits), there's
57 // a risk that it could overflow. So require it to be large enough.
59 static_assert(sizeof(MozRefCountType) == sizeof(uintptr_t),
60 "You're at risk for ref count overflow.");
62 static const MozRefCountType DEAD = ~MozRefCountType(0xffff) | 0xdead;
64 protected:
65 AtomicRefCounted() = default;
66 ~AtomicRefCounted() { MOZ_ASSERT(mRefCnt == DEAD); }
68 public:
69 void AddRef() const {
70 ++mRefCnt;
71 MOZ_ASSERT(mRefCnt != DEAD);
74 void Release() const {
75 MOZ_ASSERT(mRefCnt != 0);
76 MozRefCountType cnt = --mRefCnt;
77 if (0 == cnt) {
78 #ifdef DEBUG
79 mRefCnt = DEAD;
80 #endif
81 js_delete(const_cast<T*>(static_cast<const T*>(this)));
85 bool hasOneRef() const {
86 MOZ_ASSERT(mRefCnt > 0);
87 return mRefCnt == 1;
90 private:
91 mutable mozilla::Atomic<MozRefCountType> mRefCnt{0};
94 } // namespace js
96 #endif /* js_RefCounted_h */