1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/2d/GenericRefCounted.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,131 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +// This header provides virtual, non-templated alternatives to MFBT's RefCounted<T>. 1.10 +// It intentionally uses MFBT coding style with the intention of moving there 1.11 +// should there be other use cases for it. 1.12 + 1.13 +#ifndef MOZILLA_GENERICREFCOUNTED_H_ 1.14 +#define MOZILLA_GENERICREFCOUNTED_H_ 1.15 + 1.16 +#include "mozilla/RefPtr.h" 1.17 + 1.18 +namespace mozilla { 1.19 + 1.20 +/** 1.21 + * Common base class for GenericRefCounted and GenericAtomicRefCounted. 1.22 + * 1.23 + * Having this shared base class, common to both the atomic and non-atomic 1.24 + * cases, allows to have RefPtr's that don't care about whether the 1.25 + * objects they're managing have atomic refcounts or not. 1.26 + */ 1.27 +class GenericRefCountedBase 1.28 +{ 1.29 + protected: 1.30 + virtual ~GenericRefCountedBase() {}; 1.31 + 1.32 + public: 1.33 + // AddRef() and Release() method names are for compatibility with nsRefPtr. 1.34 + virtual void AddRef() = 0; 1.35 + 1.36 + virtual void Release() = 0; 1.37 + 1.38 + // ref() and deref() method names are for compatibility with wtf::RefPtr. 1.39 + // No virtual keywords here: if a subclass wants to override the refcounting 1.40 + // mechanism, it is welcome to do so by overriding AddRef() and Release(). 1.41 + void ref() { AddRef(); } 1.42 + void deref() { Release(); } 1.43 + 1.44 +#ifdef MOZ_REFCOUNTED_LEAK_CHECKING 1.45 + virtual const char* typeName() const = 0; 1.46 + virtual size_t typeSize() const = 0; 1.47 +#endif 1.48 +}; 1.49 + 1.50 +namespace detail { 1.51 + 1.52 +template<RefCountAtomicity Atomicity> 1.53 +class GenericRefCounted : public GenericRefCountedBase 1.54 +{ 1.55 + protected: 1.56 + GenericRefCounted() : refCnt(0) { } 1.57 + 1.58 + virtual ~GenericRefCounted() { 1.59 + MOZ_ASSERT(refCnt == detail::DEAD); 1.60 + } 1.61 + 1.62 + public: 1.63 + virtual void AddRef() { 1.64 + // Note: this method must be thread safe for GenericAtomicRefCounted. 1.65 + MOZ_ASSERT(int32_t(refCnt) >= 0); 1.66 +#ifndef MOZ_REFCOUNTED_LEAK_CHECKING 1.67 + ++refCnt; 1.68 +#else 1.69 + const char* type = typeName(); 1.70 + uint32_t size = typeSize(); 1.71 + const void* ptr = this; 1.72 + MozRefCountType cnt = ++refCnt; 1.73 + detail::RefCountLogger::logAddRef(ptr, cnt, type, size); 1.74 +#endif 1.75 + } 1.76 + 1.77 + virtual void Release() { 1.78 + // Note: this method must be thread safe for GenericAtomicRefCounted. 1.79 + MOZ_ASSERT(int32_t(refCnt) > 0); 1.80 +#ifndef MOZ_REFCOUNTED_LEAK_CHECKING 1.81 + MozRefCountType cnt = --refCnt; 1.82 +#else 1.83 + const char* type = typeName(); 1.84 + const void* ptr = this; 1.85 + MozRefCountType cnt = --refCnt; 1.86 + // Note: it's not safe to touch |this| after decrementing the refcount, 1.87 + // except for below. 1.88 + detail::RefCountLogger::logRelease(ptr, cnt, type); 1.89 +#endif 1.90 + if (0 == cnt) { 1.91 + // Because we have atomically decremented the refcount above, only 1.92 + // one thread can get a 0 count here, so as long as we can assume that 1.93 + // everything else in the system is accessing this object through 1.94 + // RefPtrs, it's safe to access |this| here. 1.95 +#ifdef DEBUG 1.96 + refCnt = detail::DEAD; 1.97 +#endif 1.98 + delete this; 1.99 + } 1.100 + } 1.101 + 1.102 + MozRefCountType refCount() const { return refCnt; } 1.103 + bool hasOneRef() const { 1.104 + MOZ_ASSERT(refCnt > 0); 1.105 + return refCnt == 1; 1.106 + } 1.107 + 1.108 + private: 1.109 + typename Conditional<Atomicity == AtomicRefCount, Atomic<MozRefCountType>, MozRefCountType>::Type refCnt; 1.110 +}; 1.111 + 1.112 +} // namespace detail 1.113 + 1.114 +/** 1.115 + * This reference-counting base class is virtual instead of 1.116 + * being templated, which is useful in cases where one needs 1.117 + * genericity at binary code level, but comes at the cost 1.118 + * of a moderate performance and size overhead, like anything virtual. 1.119 + */ 1.120 +class GenericRefCounted : public detail::GenericRefCounted<detail::NonAtomicRefCount> 1.121 +{ 1.122 +}; 1.123 + 1.124 +/** 1.125 + * GenericAtomicRefCounted is like GenericRefCounted, with an atomically updated 1.126 + * reference counter. 1.127 + */ 1.128 +class GenericAtomicRefCounted : public detail::GenericRefCounted<detail::AtomicRefCount> 1.129 +{ 1.130 +}; 1.131 + 1.132 +} // namespace mozilla 1.133 + 1.134 +#endif