mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 864035 - Add an atomic RefCounted and WeakPtr implementation. r=Waldo
This commit is contained in:
parent
5638e38904
commit
d292a5f228
@ -9,6 +9,7 @@
|
||||
#define mozilla_RefPtr_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
@ -41,13 +42,19 @@ template<typename T> OutParamRef<T> byRef(RefPtr<T>&);
|
||||
* state distinguishes use-before-ref (refcount==0) from
|
||||
* use-after-destroy (refcount==0xffffdead).
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
namespace detail {
|
||||
#ifdef DEBUG
|
||||
static const int DEAD = 0xffffdead;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
// This is used WeakPtr.h as well as this file.
|
||||
enum RefCountAtomicity
|
||||
{
|
||||
AtomicRefCount,
|
||||
NonAtomicRefCount
|
||||
};
|
||||
|
||||
template<typename T, RefCountAtomicity Atomicity>
|
||||
class RefCounted
|
||||
{
|
||||
friend class RefPtr<T>;
|
||||
@ -56,8 +63,6 @@ class RefCounted
|
||||
RefCounted() : refCnt(0) { }
|
||||
~RefCounted() {
|
||||
MOZ_ASSERT(refCnt == detail::DEAD);
|
||||
MOZ_STATIC_ASSERT((IsBaseOf<RefCounted<T>, T>::value),
|
||||
"T must derive from RefCounted<T>");
|
||||
}
|
||||
|
||||
public:
|
||||
@ -87,7 +92,33 @@ class RefCounted
|
||||
}
|
||||
|
||||
private:
|
||||
int refCnt;
|
||||
typename Conditional<Atomicity == AtomicRefCount, Atomic<int>, int>::Type refCnt;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class RefCounted : public detail::RefCounted<T, detail::NonAtomicRefCount>
|
||||
{
|
||||
public:
|
||||
~RefCounted() {
|
||||
MOZ_STATIC_ASSERT((IsBaseOf<RefCounted, T>::value),
|
||||
"T must derive from RefCounted<T>");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* AtomicRefCounted<T> is like RefCounted<T>, with an atomically updated
|
||||
* reference counter.
|
||||
*/
|
||||
template<typename T>
|
||||
class AtomicRefCounted : public detail::RefCounted<T, detail::AtomicRefCount>
|
||||
{
|
||||
public:
|
||||
~AtomicRefCounted() {
|
||||
MOZ_STATIC_ASSERT((IsBaseOf<AtomicRefCounted, T>::value),
|
||||
"T must derive from AtomicRefCounted<T>");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -13,6 +13,9 @@
|
||||
* the WeakPtrs to it and allows the WeakReference to live beyond the lifetime
|
||||
* of 'Foo'.
|
||||
*
|
||||
* AtomicSupportsWeakPtr can be used for a variant with an atomically updated
|
||||
* reference counter.
|
||||
*
|
||||
* The overhead of WeakPtr is that accesses to 'Foo' becomes an additional
|
||||
* dereference, and an additional heap allocated pointer sized object shared
|
||||
* between all of the WeakPtrs.
|
||||
@ -59,6 +62,7 @@
|
||||
#define mozilla_WeakPtr_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/NullPtr.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
@ -71,8 +75,8 @@ template <typename T, class WeakReference> class SupportsWeakPtrBase;
|
||||
namespace detail {
|
||||
|
||||
// This can live beyond the lifetime of the class derived from SupportsWeakPtrBase.
|
||||
template<class T>
|
||||
class WeakReference : public RefCounted<WeakReference<T> >
|
||||
template<class T, RefCountAtomicity Atomicity>
|
||||
class WeakReference : public RefCounted<WeakReference<T, Atomicity>, Atomicity>
|
||||
{
|
||||
public:
|
||||
explicit WeakReference(T* p) : ptr(p) {}
|
||||
@ -81,8 +85,8 @@ class WeakReference : public RefCounted<WeakReference<T> >
|
||||
}
|
||||
|
||||
private:
|
||||
friend class WeakPtrBase<T, WeakReference<T> >;
|
||||
friend class SupportsWeakPtrBase<T, WeakReference<T> >;
|
||||
friend class WeakPtrBase<T, WeakReference>;
|
||||
friend class SupportsWeakPtrBase<T, WeakReference>;
|
||||
void detach() {
|
||||
ptr = nullptr;
|
||||
}
|
||||
@ -116,10 +120,30 @@ class SupportsWeakPtrBase
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class SupportsWeakPtr : public SupportsWeakPtrBase<T, detail::WeakReference<T> >
|
||||
class SupportsWeakPtr
|
||||
: public SupportsWeakPtrBase<T, detail::WeakReference<T, detail::NonAtomicRefCount> >
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class AtomicSupportsWeakPtr
|
||||
: public SupportsWeakPtrBase<T, detail::WeakReference<T, detail::AtomicRefCount> >
|
||||
{
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
struct WeakReferenceCount
|
||||
{
|
||||
static const RefCountAtomicity atomicity =
|
||||
IsBaseOf<AtomicSupportsWeakPtr<T>, T>::value
|
||||
? AtomicRefCount
|
||||
: NonAtomicRefCount;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename T, class WeakReference>
|
||||
class WeakPtrBase
|
||||
{
|
||||
@ -152,9 +176,9 @@ class WeakPtrBase
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class WeakPtr : public WeakPtrBase<T, detail::WeakReference<T> >
|
||||
class WeakPtr : public WeakPtrBase<T, detail::WeakReference<T, detail::WeakReferenceCount<T>::atomicity> >
|
||||
{
|
||||
typedef WeakPtrBase<T, detail::WeakReference<T> > Base;
|
||||
typedef WeakPtrBase<T, detail::WeakReference<T, detail::WeakReferenceCount<T>::atomicity> > Base;
|
||||
public:
|
||||
WeakPtr(const WeakPtr<T>& o) : Base(o) {}
|
||||
WeakPtr(const Base& o) : Base(o) {}
|
||||
|
@ -68,14 +68,16 @@ __dl_munmap(void *handle, void *addr, size_t length);
|
||||
class LibHandle;
|
||||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
template <> inline void RefCounted<LibHandle>::Release();
|
||||
template <> inline void RefCounted<LibHandle, NonAtomicRefCount>::Release();
|
||||
|
||||
template <> inline RefCounted<LibHandle>::~RefCounted()
|
||||
template <> inline RefCounted<LibHandle, NonAtomicRefCount>::~RefCounted()
|
||||
{
|
||||
MOZ_ASSERT(refCnt == 0x7fffdead);
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace mozilla */
|
||||
|
||||
/* Forward declaration */
|
||||
@ -213,8 +215,9 @@ private:
|
||||
* would mean too many Releases from within the destructor.
|
||||
*/
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
template <> inline void RefCounted<LibHandle>::Release() {
|
||||
template <> inline void RefCounted<LibHandle, NonAtomicRefCount>::Release() {
|
||||
#ifdef DEBUG
|
||||
if (refCnt > 0x7fff0000)
|
||||
MOZ_ASSERT(refCnt > 0x7fffdead);
|
||||
@ -232,6 +235,7 @@ template <> inline void RefCounted<LibHandle>::Release() {
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace mozilla */
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user