Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(711)

Side by Side Diff: base/memory/weak_ptr_unittest.cc

Issue 7677028: Make WeakPtr thread-safe, i.e. allow cross-thread copying of WeakPtr (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add suppression Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/memory/weak_ptr.cc ('k') | tools/valgrind/memcheck/suppressions.txt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/memory/scoped_ptr.h" 5 #include "base/memory/scoped_ptr.h"
6 #include "base/memory/weak_ptr.h" 6 #include "base/memory/weak_ptr.h"
7 #include "testing/gtest/include/gtest/gtest.h" 7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/synchronization/waitable_event.h"
9 #include "base/threading/thread.h" 10 #include "base/threading/thread.h"
10 11
11 namespace base { 12 namespace base {
12 namespace { 13 namespace {
13 14
14 template <class T> 15 template <class T>
15 class OffThreadObjectCreator { 16 class OffThreadObjectCreator {
16 public: 17 public:
17 static T* NewObject() { 18 static T* NewObject() {
18 T* result; 19 T* result;
(...skipping 12 matching lines...) Expand all
31 *result = new T; 32 *result = new T;
32 } 33 }
33 }; 34 };
34 35
35 struct Base {}; 36 struct Base {};
36 struct Derived : Base {}; 37 struct Derived : Base {};
37 38
38 struct Producer : SupportsWeakPtr<Producer> {}; 39 struct Producer : SupportsWeakPtr<Producer> {};
39 struct Consumer { WeakPtr<Producer> producer; }; 40 struct Consumer { WeakPtr<Producer> producer; };
40 41
42 // Helper class to create and destroy weak pointer copies
43 // and delete objects on a background thread.
44 class BackgroundThread : public Thread {
45 public:
46 BackgroundThread()
47 : Thread("owner_thread") {
48 }
49
50 void CreateConsumerFromProducer(Consumer** consumer, Producer* producer) {
51 WaitableEvent completion(true, false);
52 message_loop()->PostTask(
53 FROM_HERE,
54 NewRunnableFunction(&BackgroundThread::DoCreateFromProducer,
55 consumer,
56 producer,
57 &completion));
58 completion.Wait();
59 }
60
61 void CreateConsumerFromConsumer(Consumer** consumer, const Consumer* other) {
62 WaitableEvent completion(true, false);
63 message_loop()->PostTask(
64 FROM_HERE,
65 NewRunnableFunction(&BackgroundThread::DoCreateFromConsumer,
66 consumer,
67 other,
68 &completion));
69 completion.Wait();
70 }
71
72 void DeleteProducer(Producer* object) {
73 WaitableEvent completion(true, false);
74 message_loop()->PostTask(
75 FROM_HERE,
76 NewRunnableFunction(&BackgroundThread::DoDeleteProducer,
77 object,
78 &completion));
79 completion.Wait();
80 }
81
82 void DeleteConsumer(Consumer* object) {
83 WaitableEvent completion(true, false);
84 message_loop()->PostTask(
85 FROM_HERE,
86 NewRunnableFunction(&BackgroundThread::DoDeleteConsumer,
87 object,
88 &completion));
89 completion.Wait();
90 }
91
92 Producer* DeRef(const Consumer* consumer) {
93 WaitableEvent completion(true, false);
94 Producer* result = NULL;
95 message_loop()->PostTask(
96 FROM_HERE,
97 NewRunnableFunction(&BackgroundThread::DoDeRef,
98 consumer,
99 &result,
100 &completion));
101 completion.Wait();
102 return result;
103 }
104
105 protected:
106 static void DoCreateFromConsumer(Consumer** consumer,
107 const Consumer* other,
108 WaitableEvent* completion) {
109 *consumer = new Consumer;
110 **consumer = *other;
111 completion->Signal();
112 }
113
114 static void DoCreateFromProducer(Consumer** consumer,
115 Producer* producer,
116 WaitableEvent* completion) {
117 *consumer = new Consumer;
118 (*consumer)->producer = producer->AsWeakPtr();
119 completion->Signal();
120 }
121
122 static void DoDeRef(const Consumer* consumer,
123 Producer** result,
124 WaitableEvent* completion) {
125 *result = consumer->producer.get();
126 completion->Signal();
127 }
128
129 static void DoDeleteProducer(Producer* object, WaitableEvent* completion) {
130 delete object;
131 completion->Signal();
132 }
133
134 static void DoDeleteConsumer(Consumer* object, WaitableEvent* completion) {
135 delete object;
136 completion->Signal();
137 }
138 };
139
41 } // namespace 140 } // namespace
42 141
43 TEST(WeakPtrTest, Basic) { 142 TEST(WeakPtrTest, Basic) {
44 int data; 143 int data;
45 WeakPtrFactory<int> factory(&data); 144 WeakPtrFactory<int> factory(&data);
46 WeakPtr<int> ptr = factory.GetWeakPtr(); 145 WeakPtr<int> ptr = factory.GetWeakPtr();
47 EXPECT_EQ(&data, ptr.get()); 146 EXPECT_EQ(&data, ptr.get());
48 } 147 }
49 148
50 TEST(WeakPtrTest, Comparison) { 149 TEST(WeakPtrTest, Comparison) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 TEST(WeakPtrTest, SingleThreaded2) { 240 TEST(WeakPtrTest, SingleThreaded2) {
142 // Test that it is OK to create a class that has a WeakPtr member on one 241 // Test that it is OK to create a class that has a WeakPtr member on one
143 // thread, but use it on another. This tests that we do not trip runtime 242 // thread, but use it on another. This tests that we do not trip runtime
144 // checks that ensure that a weak reference is not used by multiple threads. 243 // checks that ensure that a weak reference is not used by multiple threads.
145 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject()); 244 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject());
146 Producer producer; 245 Producer producer;
147 consumer->producer = producer.AsWeakPtr(); 246 consumer->producer = producer.AsWeakPtr();
148 EXPECT_EQ(&producer, consumer->producer.get()); 247 EXPECT_EQ(&producer, consumer->producer.get());
149 } 248 }
150 249
250 TEST(WeakPtrTest, MoveOwnershipImplicit) {
251 // Move object ownership to other thread by releasing all weak pointers
252 // on the original thread first. Establishing weak pointers on a different
253 // thread after previous pointers have been destroyed implicitly reattaches
254 // the thread checks.
255 // - Thread A creates object and weak pointer
256 // - Thread A deletes the weak pointer
257 // - Thread B creates weak pointer
258 // - Thread B derefs weak pointer
259 // - Thread B deletes object
260 BackgroundThread thread;
261 thread.Start();
262 Producer* producer = new Producer();
263 {
264 WeakPtr<Producer> weak_ptr = producer->AsWeakPtr();
265 }
266 Consumer* consumer;
267 thread.CreateConsumerFromProducer(&consumer, producer);
268 EXPECT_EQ(thread.DeRef(consumer), producer);
269 thread.DeleteProducer(producer);
270 thread.DeleteConsumer(consumer);
271 }
272
273 TEST(WeakPtrTest, MoveOwnershipExplicit) {
274 // Test that we do not trip any checks if we establish weak references
275 // on one thread and delete the object on another thread after explicit
276 // detachment.
277 // - Thread A creates object
278 // - Thread B creates weak pointer
279 // - Thread B releases weak pointer
280 // - Detach owner from Thread B
281 // - Thread A destroys object
282 BackgroundThread thread;
283 thread.Start();
284 Producer producer;
285 Consumer* consumer;
286 thread.CreateConsumerFromProducer(&consumer, &producer);
287 EXPECT_EQ(thread.DeRef(consumer), &producer);
288 thread.DeleteConsumer(consumer);
289 producer.DetachFromThread();
290 }
291
292 TEST(WeakPtrTest, ThreadARefOutlivesThreadBRef) {
293 // Originating thread has a WeakPtr that outlives others.
294 // - Thread A creates WeakPtr<> and passes copy to Thread B
295 // - Destruct the pointer on Thread B
296 // - Destruct the pointer on Thread A
297 BackgroundThread thread;
298 thread.Start();
299 Producer producer;
300 Consumer consumer;
301 consumer.producer = producer.AsWeakPtr();
302 Consumer* consumer_copy;
303 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer);
304 EXPECT_EQ(consumer_copy->producer, &producer);
305 thread.DeleteConsumer(consumer_copy);
306 }
307
308 TEST(WeakPtrTest, ThreadBRefOutlivesThreadARef) {
309 // Originating thread drops all references before another thread.
310 // - Thread A creates WeakPtr<> and passes copy to Thread B
311 // - Destruct the pointer on Thread A
312 // - Destruct the pointer on Thread B
313 BackgroundThread thread;
314 thread.Start();
315 Producer producer;
316 Consumer* consumer_copy;
317 {
318 Consumer consumer;
319 consumer.producer = producer.AsWeakPtr();
320 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer);
321 }
322 EXPECT_EQ(consumer_copy->producer, &producer);
323 thread.DeleteConsumer(consumer_copy);
324 }
325
326 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
327 // Originating thread invalidates WeakPtrs while its held by other thread.
328 // - Thread A creates WeakPtr<> and passes Copy to Thread B
329 // - WeakReferenceOwner gets destroyed on Thread A
330 // - WeakPtr gets destroyed on Thread B
331 BackgroundThread thread;
332 thread.Start();
333 Consumer* consumer_copy;
334 {
335 Producer producer;
336 Consumer consumer;
337 consumer.producer = producer.AsWeakPtr();
338 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer);
339 }
340 EXPECT_TRUE(consumer_copy->producer == NULL);
341 thread.DeleteConsumer(consumer_copy);
342 }
343
151 } // namespace base 344 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/weak_ptr.cc ('k') | tools/valgrind/memcheck/suppressions.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698