Chromium Code Reviews| Index: Source/heap/HeapTest.cpp |
| diff --git a/Source/heap/HeapTest.cpp b/Source/heap/HeapTest.cpp |
| index 9cd048780a643d7955f177fcf0db06f2ac18d55e..bbbb821ea9ff267b008f0ea18c8427f4f3dca0d7 100644 |
| --- a/Source/heap/HeapTest.cpp |
| +++ b/Source/heap/HeapTest.cpp |
| @@ -531,6 +531,7 @@ public: |
| m_magic = 0; |
| s_live--; |
| } |
| + bool isLive() const { return m_magic; } |
| virtual void trace(Visitor* visitor) { } |
| static unsigned s_live; |
| @@ -562,6 +563,13 @@ public: |
| void clear() { m_bar.release(); } |
| + // willFinalize is called before finalize()/destructor. |
| + void willFinalize() |
| + { |
| + EXPECT_TRUE(m_bar->isLive()); |
| + EXPECT_EQ(1u, Bar::s_live); |
| + } |
| + |
| private: |
| explicit Baz(Bar* bar) |
| : m_bar(bar) |
| @@ -865,6 +873,65 @@ private: |
| WeakMember<Bar> m_weakBar; |
| }; |
| +// FIXME: This should be moved to heap/Handle.h. |
| +template <typename T> class Observer : public GarbageCollected<Observer<T> > { |
| +public: |
| + static Observer* create(T* data) { return new Observer(data); } |
| + |
| + void trace(Visitor* visitor) |
| + { |
| + visitor->registerWeakMembers(this, zapWeakMembers); |
| + } |
| + |
| + static void zapWeakMembers(Visitor* visitor, void* self) |
| + { |
| + Observer* o = reinterpret_cast<Observer*>(self); |
| + if (o->m_data && !visitor->isAlive(o->m_data)) { |
| + o->m_data->willFinalize(); |
| + o->m_data = 0; |
| + } |
| + } |
| + |
| +private: |
| + Observer(T* data) : m_data(data) { } |
| + T* m_data; |
|
zerny-chromium
2014/03/13 06:41:47
Nit: WeakMember<T> m_data;
|
| +}; |
| + |
| +// This demonstrates how to use Observer<T> as a part object of the target. |
| +class WillFinalized : public GarbageCollectedFinalized<WillFinalized> { |
| +public: |
| + WillFinalized(Bar* bar) |
| + : m_data(2014) |
| + , m_bar(bar) |
| + , m_observer(Observer<WillFinalized>::create(this)) |
| + { |
| + } |
| + |
| + // willFinalize is called before finalize()/destructor. |
| + void willFinalize() |
| + { |
| + EXPECT_NE(0, m_data); |
| + EXPECT_TRUE(m_bar->isLive()); |
| + m_data = 0; |
| + } |
| + |
| + ~WillFinalized() |
| + { |
| + EXPECT_EQ(0, m_data); |
| + } |
| + |
| + void trace(Visitor* visitor) |
| + { |
| + visitor->trace(m_bar); |
| + } |
| + |
| +private: |
| + int m_data; |
| + Member<Bar> m_bar; |
| + // This is a trick. Use Persistent for Observer<T> to avoid it is collected |
|
zerny-chromium
2014/03/13 06:41:47
it is collected -> it from being collected
Mads Ager (chromium)
2014/03/13 07:33:28
Instead of embedding the Persistent in the object
|
| + // with the target. |
| + Persistent<Observer<WillFinalized> > m_observer; |
| +}; |
| class SuperClass; |
| @@ -2481,6 +2548,28 @@ TEST(HeapTest, WeakMembers) |
| EXPECT_EQ(0u, Bar::s_live); // All gone. |
| } |
| +TEST(HeapTest, WillFinalize) |
| +{ |
| + // |o| observes |baz|. |
| + Persistent<Observer<Baz> > o; |
| + { |
| + Baz* baz = Baz::create(Bar::create()); |
| + o = Observer<Baz>::create(baz); |
| + } |
| + // Observer doesn't have a strong reference to baz. So baz and its member |
| + // will be collected. |
| + Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| + EXPECT_EQ(0u, Bar::s_live); |
| + |
| + // |wf| observes itself, and calls willFinalize(). |
| + { |
| + WillFinalized* wf = new WillFinalized(Bar::create()); |
| + wf = 0; |
| + } |
| + Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| + EXPECT_EQ(0u, Bar::s_live); |
| +} |
| + |
| TEST(HeapTest, Comparisons) |
| { |
| Persistent<Bar> barPersistent = Bar::create(); |