| Index: Source/heap/Heap.h
|
| diff --git a/Source/heap/Heap.h b/Source/heap/Heap.h
|
| index b00320f91886fceae29663f759a6f703ed4a3210..d95f726d8e13ca0558e987e5b4bb74c6cdef2228 100644
|
| --- a/Source/heap/Heap.h
|
| +++ b/Source/heap/Heap.h
|
| @@ -39,6 +39,7 @@
|
| #include "wtf/Assertions.h"
|
| #include "wtf/OwnPtr.h"
|
| #include "wtf/PassRefPtr.h"
|
| +#include "wtf/ThreadSafeRefCounted.h"
|
|
|
| #include <stdint.h>
|
|
|
| @@ -67,6 +68,7 @@ class HeapStats;
|
| class PageMemory;
|
| template<ThreadAffinity affinity> class ThreadLocalPersistents;
|
| template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTrait<T>::Affinity > > class Persistent;
|
| +template<typename T> class CrossThreadPersistent;
|
|
|
| HEAP_EXPORT size_t osPageSize();
|
|
|
| @@ -535,6 +537,68 @@ private:
|
| friend class ThreadState;
|
| };
|
|
|
| +// FIXME(oilpan): The current implementation requires the deallocating
|
| +// thread to be the same as the thread on which this instance was first
|
| +// allocated. Only the refs/derefs that are not 0 -> 1 or 1 -> 0 are
|
| +// thread safe.
|
| +// This is currently used by the WebAudio code.
|
| +// We should attempt to restructure the WebAudio code so that the main thread
|
| +// alone determines life-time and receives messages about life-time from the
|
| +// audio thread.
|
| +template<typename T>
|
| +class ThreadSafeRefCountedGarbageCollected : public GarbageCollectedFinalized<T>, public WTF::ThreadSafeRefCountedBase {
|
| + WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedGarbageCollected);
|
| +
|
| +public:
|
| + ThreadSafeRefCountedGarbageCollected()
|
| + {
|
| +#ifndef NDEBUG
|
| + m_threadState = ThreadState::current();
|
| +#endif
|
| + m_keepAlive = adoptPtr(new CrossThreadPersistent<T>(static_cast<T*>(this)));
|
| + }
|
| +
|
| + // Override ref to deal with a case where a reference count goes up
|
| + // from 0 to 1. This can happen in the following scenario:
|
| + // (1) The reference count becomes 0, but on-stack pointers keep references to the object.
|
| + // (2) The on-stack pointer is assigned to a RefPtr. The reference count becomes 1.
|
| + // In this case, we have to resurrect m_keepAlive.
|
| + void ref()
|
| + {
|
| + MutexLocker lock(m_mutex);
|
| + if (UNLIKELY(!refCount())) {
|
| + ASSERT(!m_keepAlive);
|
| + ASSERT(m_threadState->contains(reinterpret_cast<Address>(this)));
|
| + // ASSERT(m_threadState == ThreadState::current());
|
| + m_keepAlive = adoptPtr(new CrossThreadPersistent<T>(static_cast<T*>(this)));
|
| + }
|
| + WTF::ThreadSafeRefCountedBase::ref();
|
| + }
|
| +
|
| + // Override deref to deal with our own deallocation based on ref counting.
|
| + void deref()
|
| + {
|
| + MutexLocker lock(m_mutex);
|
| + if (derefBase()) {
|
| + ASSERT(m_threadState == ThreadState::current());
|
| + m_keepAlive.clear();
|
| + }
|
| + }
|
| +
|
| + using GarbageCollectedFinalized<T>::operator new;
|
| + using GarbageCollectedFinalized<T>::operator delete;
|
| +
|
| +protected:
|
| + ~ThreadSafeRefCountedGarbageCollected() { }
|
| +
|
| +private:
|
| + OwnPtr<CrossThreadPersistent<T> > m_keepAlive;
|
| + mutable Mutex m_mutex;
|
| +#ifndef NDEBUG
|
| + ThreadState* m_threadState;
|
| +#endif
|
| +};
|
| +
|
| // The CallbackStack contains all the visitor callbacks used to trace and mark
|
| // objects. A specific CallbackStack instance contains at most bufferSize elements.
|
| // If more space is needed a new CallbackStack instance is created and chained
|
|
|