Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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 js_RefCounted_h
8 : #define js_RefCounted_h
9 :
10 : #include "mozilla/Atomics.h"
11 : #include "mozilla/RefCountType.h"
12 :
13 : #include "js/Utility.h"
14 :
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).
22 :
23 : namespace js {
24 :
25 : template <typename T>
26 : class RefCounted
27 : {
28 : static const MozRefCountType DEAD = 0xffffdead;
29 :
30 : protected:
31 0 : RefCounted() : mRefCnt(0) {}
32 0 : ~RefCounted() { MOZ_ASSERT(mRefCnt == DEAD); }
33 :
34 : public:
35 0 : void AddRef() const
36 : {
37 0 : MOZ_ASSERT(int32_t(mRefCnt) >= 0);
38 0 : ++mRefCnt;
39 0 : }
40 :
41 0 : void Release() const
42 : {
43 0 : MOZ_ASSERT(int32_t(mRefCnt) > 0);
44 0 : MozRefCountType cnt = --mRefCnt;
45 0 : if (0 == cnt) {
46 : #ifdef DEBUG
47 0 : mRefCnt = DEAD;
48 : #endif
49 0 : js_delete(const_cast<T*>(static_cast<const T*>(this)));
50 : }
51 0 : }
52 :
53 : private:
54 : mutable MozRefCountType mRefCnt;
55 : };
56 :
57 : template <typename T>
58 : class AtomicRefCounted
59 : {
60 : static const MozRefCountType DEAD = 0xffffdead;
61 :
62 : protected:
63 0 : AtomicRefCounted() : mRefCnt(0) {}
64 0 : ~AtomicRefCounted() { MOZ_ASSERT(mRefCnt == DEAD); }
65 :
66 : public:
67 0 : void AddRef() const
68 : {
69 0 : MOZ_ASSERT(int32_t(mRefCnt) >= 0);
70 0 : ++mRefCnt;
71 0 : }
72 :
73 0 : void Release() const
74 : {
75 0 : MOZ_ASSERT(int32_t(mRefCnt) > 0);
76 0 : MozRefCountType cnt = --mRefCnt;
77 0 : if (0 == cnt) {
78 : #ifdef DEBUG
79 0 : mRefCnt = DEAD;
80 : #endif
81 0 : js_delete(const_cast<T*>(static_cast<const T*>(this)));
82 : }
83 0 : }
84 :
85 : private:
86 : mutable mozilla::Atomic<MozRefCountType> mRefCnt;
87 : };
88 :
89 : } // namespace js
90 :
91 : #endif /* js_RefCounted_h */
|