Index: Source/heap/Heap.h |
diff --git a/Source/heap/Heap.h b/Source/heap/Heap.h |
index c84a0ce76f81da717d30a1754e83a1ff535940fd..e75ad0178cd88dbdd398e852bed358eb8f5fb7ee 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> |
@@ -535,6 +536,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. |
haraken
2014/03/27 11:44:05
Probably you can eliminate this restriction by usi
keishi
2014/04/03 06:53:19
Done.
|
+// This is currently used by the WebAudio code and the WebDatabase code. |
haraken
2014/03/27 11:44:05
Remove the "WebDatabase code" part. I think tkent-
keishi
2014/04/03 06:53:19
Done.
|
+// 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 WTF::ThreadSafeRefCountedBase, public GarbageCollectedFinalized<T> { |
Mads Ager (chromium)
2014/03/27 11:06:49
I think it was like this on the branch as well, bu
keishi
2014/04/03 06:53:19
Done.
|
+ WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedGarbageCollected); |
+ |
+public: |
+ ThreadSafeRefCountedGarbageCollected() |
+ { |
+#ifndef NDEBUG |
+ m_threadState = ThreadState::current(); |
+#endif |
+ m_keepAlive = new Persistent<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 = new Persistent<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()) { |
haraken
2014/03/27 11:44:05
I suspect this leaks memory, because currently der
keishi
2014/04/03 06:53:19
haraken fixed this in r170256
|
+ ASSERT(m_threadState == ThreadState::current()); |
+ m_keepAlive = 0; |
haraken
2014/03/27 11:44:05
m_keepAlive = nullptr;
keishi
2014/04/03 06:53:19
Done.
|
+ } |
+ } |
+ |
+ using GarbageCollectedFinalized<T>::operator new; |
+ using GarbageCollectedFinalized<T>::operator delete; |
+ |
+protected: |
+ ~ThreadSafeRefCountedGarbageCollected() { } |
+ |
+private: |
+ Persistent<T>* m_keepAlive; |
haraken
2014/03/27 11:44:05
Shall we use an OwnPtr<Persistent<T> > ?
keishi
2014/04/03 06:53:19
Done.
|
+ 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 |
@@ -1007,6 +1070,11 @@ public: |
return m_refCount == 1; |
} |
+ int refCount() |
Mads Ager (chromium)
2014/03/27 11:06:49
Do we need this? When something is RefCountedGarba
keishi
2014/04/03 06:53:19
Done.
|
+ { |
+ return m_refCount; |
+ } |
+ |
protected: |
~RefCountedGarbageCollected() { } |