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

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: remove a bit of unneeded code 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') | no next file » | 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 : protected Thread {
45 public:
46 BackgroundThread()
47 : Thread("owner_thread") {
48 Start();
awong 2011/08/23 00:11:15 This constitutes work in a constructor which the s
49 }
50
51 void CreateConsumer(Consumer** consumer, Producer* producer) {
awong 2011/08/23 00:11:15 Overloaded functions are discouraged by the style
52 WaitableEvent completion(true, false);
53 message_loop()->PostTask(
54 FROM_HERE,
55 NewRunnableFunction(&BackgroundThread::DoCreateFromProducer,
56 consumer,
57 producer,
58 &completion));
59 completion.Wait();
60 }
61
62 void CreateConsumer(Consumer** consumer, const Consumer* other) {
63 WaitableEvent completion(true, false);
64 message_loop()->PostTask(
65 FROM_HERE,
66 NewRunnableFunction(&BackgroundThread::DoCreateFromConsumer,
67 consumer,
68 other,
69 &completion));
70 completion.Wait();
71 }
72
73 void DeleteProducer(Producer* object) {
74 WaitableEvent completion(true, false);
75 message_loop()->PostTask(
76 FROM_HERE,
77 NewRunnableFunction(&BackgroundThread::DoDeleteProducer,
78 object,
79 &completion));
80 completion.Wait();
81 }
82
83 void DeleteConsumer(Consumer* object) {
84 WaitableEvent completion(true, false);
85 message_loop()->PostTask(
86 FROM_HERE,
87 NewRunnableFunction(&BackgroundThread::DoDeleteConsumer,
88 object,
89 &completion));
90 completion.Wait();
91 }
92
93 Producer* DeRef(const Consumer* consumer) {
94 WaitableEvent completion(true, false);
95 Producer* result = NULL;
96 message_loop()->PostTask(
97 FROM_HERE,
98 NewRunnableFunction(&BackgroundThread::DoDeRef,
99 consumer,
100 &result,
101 &completion));
102 completion.Wait();
103 return result;
104 }
105
106 protected:
107 static void DoCreateFromConsumer(Consumer** consumer,
108 const Consumer* other,
109 WaitableEvent* completion) {
110 *consumer = new Consumer;
111 **consumer = *other;
112 completion->Signal();
113 }
114
115 static void DoCreateFromProducer(Consumer** consumer,
116 Producer* producer,
117 WaitableEvent* completion) {
118 *consumer = new Consumer;
119 (*consumer)->producer = producer->AsWeakPtr();
120 completion->Signal();
121 }
122
123 static void DoDeRef(const Consumer* consumer,
124 Producer** result,
125 WaitableEvent* completion) {
126 *result = consumer->producer.get();
127 completion->Signal();
128 }
129
130 static void DoDeleteProducer(Producer* object, WaitableEvent* completion) {
131 delete object;
132 completion->Signal();
133 }
134
135 static void DoDeleteConsumer(Consumer* object, WaitableEvent* completion) {
136 delete object;
137 completion->Signal();
138 }
139 };
140
41 } // namespace 141 } // namespace
42 142
43 TEST(WeakPtrTest, Basic) { 143 TEST(WeakPtrTest, Basic) {
44 int data; 144 int data;
45 WeakPtrFactory<int> factory(&data); 145 WeakPtrFactory<int> factory(&data);
46 WeakPtr<int> ptr = factory.GetWeakPtr(); 146 WeakPtr<int> ptr = factory.GetWeakPtr();
47 EXPECT_EQ(&data, ptr.get()); 147 EXPECT_EQ(&data, ptr.get());
48 } 148 }
49 149
50 TEST(WeakPtrTest, Comparison) { 150 TEST(WeakPtrTest, Comparison) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 TEST(WeakPtrTest, SingleThreaded2) { 241 TEST(WeakPtrTest, SingleThreaded2) {
142 // Test that it is OK to create a class that has a WeakPtr member on one 242 // 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 243 // 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. 244 // checks that ensure that a weak reference is not used by multiple threads.
145 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject()); 245 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject());
146 Producer producer; 246 Producer producer;
147 consumer->producer = producer.AsWeakPtr(); 247 consumer->producer = producer.AsWeakPtr();
148 EXPECT_EQ(&producer, consumer->producer.get()); 248 EXPECT_EQ(&producer, consumer->producer.get());
149 } 249 }
150 250
251 TEST(WeakPtrTest, MoveOwnerShip) {
awong 2011/08/23 00:11:15 OwnerShip -> Ownership
252 // Move object ownership to other thread by releasing all weak pointers
253 // on the original thread first.
254 // - Thread A creates object and weak pointer
255 // - Thread A deletes the weak pointer
256 // - Thread B creates weak pointer
257 // - Thread B derefs weak pointer
258 // - Thread B deletes object
259 BackgroundThread thread;
260 Producer* producer = new Producer;
awong 2011/08/23 00:11:15 new Producer();
261 {
262 WeakPtr<Producer> weak_ptr = producer->AsWeakPtr();
263 }
264 Consumer* consumer;
265 thread.CreateConsumer(&consumer, producer);
266 EXPECT_EQ(thread.DeRef(consumer), producer);
267 thread.DeleteProducer(producer);
268 thread.DeleteConsumer(consumer);
269 }
270
271 TEST(WeakPtrTest, DetachFromThread) {
272 // Test that we do not trip any checks if we establish weak references
273 // on one thread and delete the object on another thread after explicit
274 // detachment.
275 // - Thread A creates object
276 // - Thread B creates weak pointer
277 // - Thread B releases weak pointer
278 // - Detach owner from thread B
279 // - Thread A destroys object
280 BackgroundThread thread;
281 Producer producer;
282 Consumer* consumer;
283 thread.CreateConsumer(&consumer, &producer);
284 EXPECT_EQ(thread.DeRef(consumer), &producer);
285 thread.DeleteConsumer(consumer);
286 producer.DetachFromThread();
287 }
288
289 TEST(WeakPtrTest, ThreadARefOutlivesThreadBRef) {
290 // Originating thread has a WeakPtr that outlives others.
291 // - Thread A creates WeakPtr<> and passes copy to Thread B
292 // - Destruct the pointer on thread B
awong 2011/08/23 00:11:15 Capitalize "thread"
293 // - Destruct the pointer on thread A
294 BackgroundThread thread;
295 Producer producer;
296 Consumer consumer;
297 consumer.producer = producer.AsWeakPtr();
298 Consumer* consumer_copy;
299 thread.CreateConsumer(&consumer_copy, &consumer);
300 EXPECT_EQ(consumer_copy->producer, &producer);
301 thread.DeleteConsumer(consumer_copy);
302 }
303
304 TEST(WeakPtrTest, ThreadBRefOutlivesThreadARef) {
305 // Originating thread drops all references before another thread.
306 // - Thread A creates WeakPtr<> and passes copy to Thread B
307 // - Destruct the pointer on thread A
awong 2011/08/23 00:11:15 Capitalize "thread."
308 // - Destruct the pointer on thread B
309 BackgroundThread thread;
310 Producer producer;
311 Consumer* consumer_copy;
312 {
313 Consumer consumer;
314 consumer.producer = producer.AsWeakPtr();
315 thread.CreateConsumer(&consumer_copy, &consumer);
316 }
317 EXPECT_EQ(consumer_copy->producer, &producer);
318 thread.DeleteConsumer(consumer_copy);
319 }
320
321 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
322 // Originating thread invalidates WeakPtrs while its held by other thread.
323 // - Thread A creates WeakPtr<> and passes Copy to Thread B
324 // - WeakReferenceOwner gets destroyed on thread A
awong 2011/08/23 00:11:15 Capitalize "thread."
325 // - WeakPtr gets destroyed on thread B
326 BackgroundThread thread;
327 Consumer* consumer_copy;
328 {
329 Producer producer;
330 Consumer consumer;
331 consumer.producer = producer.AsWeakPtr();
332 thread.CreateConsumer(&consumer_copy, &consumer);
333 }
334 EXPECT_TRUE(consumer_copy->producer == NULL);
335 thread.DeleteConsumer(consumer_copy);
336 }
337
151 } // namespace base 338 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/weak_ptr.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698