no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / gfx / 2d / GenericRefCounted.h
blob4462c942304be49ad7733dc952f561285e252d1f
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 // This header provides virtual, non-templated alternatives to MFBT's
8 // RefCounted<T>. It intentionally uses MFBT coding style with the intention of
9 // moving there should there be other use cases for it.
11 #ifndef MOZILLA_GENERICREFCOUNTED_H_
12 #define MOZILLA_GENERICREFCOUNTED_H_
14 #include <type_traits>
16 #include "mozilla/RefPtr.h"
17 #include "mozilla/RefCounted.h"
19 namespace mozilla {
21 /**
22 * Common base class for GenericRefCounted and GenericAtomicRefCounted.
24 * Having this shared base class, common to both the atomic and non-atomic
25 * cases, allows to have RefPtr's that don't care about whether the
26 * objects they're managing have atomic refcounts or not.
28 class GenericRefCountedBase {
29 protected:
30 virtual ~GenericRefCountedBase() = default;
32 public:
33 // AddRef() and Release() method names are for compatibility with nsRefPtr.
34 virtual void AddRef() = 0;
36 virtual void Release() = 0;
38 // ref() and deref() method names are for compatibility with wtf::RefPtr.
39 // No virtual keywords here: if a subclass wants to override the refcounting
40 // mechanism, it is welcome to do so by overriding AddRef() and Release().
41 void ref() { AddRef(); }
42 void deref() { Release(); }
44 #ifdef MOZ_REFCOUNTED_LEAK_CHECKING
45 virtual const char* typeName() const = 0;
46 virtual size_t typeSize() const = 0;
47 #endif
50 namespace detail {
52 template <RefCountAtomicity Atomicity>
53 class GenericRefCounted : public GenericRefCountedBase {
54 protected:
55 GenericRefCounted() : refCnt(0) {}
57 virtual ~GenericRefCounted() { MOZ_ASSERT(refCnt == detail::DEAD); }
59 public:
60 virtual void AddRef() override {
61 // Note: this method must be thread safe for GenericAtomicRefCounted.
62 MOZ_ASSERT(int32_t(refCnt) >= 0);
63 MozRefCountType cnt = ++refCnt;
64 detail::RefCountLogger::logAddRef(this, cnt);
67 virtual void Release() override {
68 // Note: this method must be thread safe for GenericAtomicRefCounted.
69 MOZ_ASSERT(int32_t(refCnt) > 0);
70 detail::RefCountLogger::ReleaseLogger logger{this};
71 MozRefCountType cnt = --refCnt;
72 // Note: it's not safe to touch |this| after decrementing the refcount,
73 // except for below.
74 logger.logRelease(cnt);
75 if (0 == cnt) {
76 // Because we have atomically decremented the refcount above, only
77 // one thread can get a 0 count here, so as long as we can assume that
78 // everything else in the system is accessing this object through
79 // RefPtrs, it's safe to access |this| here.
80 #ifdef DEBUG
81 refCnt = detail::DEAD;
82 #endif
83 delete this;
87 MozRefCountType refCount() const { return refCnt; }
88 bool hasOneRef() const {
89 MOZ_ASSERT(refCnt > 0);
90 return refCnt == 1;
93 private:
94 std::conditional_t<Atomicity == AtomicRefCount, Atomic<MozRefCountType>,
95 MozRefCountType>
96 refCnt;
99 } // namespace detail
102 * This reference-counting base class is virtual instead of
103 * being templated, which is useful in cases where one needs
104 * genericity at binary code level, but comes at the cost
105 * of a moderate performance and size overhead, like anything virtual.
107 class GenericRefCounted
108 : public detail::GenericRefCounted<detail::NonAtomicRefCount> {};
111 * GenericAtomicRefCounted is like GenericRefCounted, with an atomically updated
112 * reference counter.
114 class GenericAtomicRefCounted
115 : public detail::GenericRefCounted<detail::AtomicRefCount> {};
117 } // namespace mozilla
119 #endif