1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/memory/weak_ptr.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 class OffThreadObjectCreator
{
22 static T
* NewObject() {
25 Thread
creator_thread("creator_thread");
26 creator_thread
.Start();
27 creator_thread
.message_loop()->PostTask(
29 base::Bind(OffThreadObjectCreator::CreateObject
, &result
));
31 DCHECK(result
); // We synchronized on thread destruction above.
35 static void CreateObject(T
** result
) {
43 struct Derived
: public Base
{};
46 struct Target
: public TargetBase
, public SupportsWeakPtr
<Target
> {};
47 struct DerivedTarget
: public Target
{};
49 WeakPtr
<Target
> target
;
52 // Helper class to create and destroy weak pointer copies
53 // and delete objects on a background thread.
54 class BackgroundThread
: public Thread
{
56 BackgroundThread() : Thread("owner_thread") {}
58 virtual ~BackgroundThread() {
62 void CreateArrowFromTarget(Arrow
** arrow
, Target
* target
) {
63 WaitableEvent
completion(true, false);
64 message_loop()->PostTask(
66 base::Bind(&BackgroundThread::DoCreateArrowFromTarget
,
67 arrow
, target
, &completion
));
71 void CreateArrowFromArrow(Arrow
** arrow
, const Arrow
* other
) {
72 WaitableEvent
completion(true, false);
73 message_loop()->PostTask(
75 base::Bind(&BackgroundThread::DoCreateArrowFromArrow
,
76 arrow
, other
, &completion
));
80 void DeleteTarget(Target
* object
) {
81 WaitableEvent
completion(true, false);
82 message_loop()->PostTask(
84 base::Bind(&BackgroundThread::DoDeleteTarget
, object
, &completion
));
88 void CopyAndAssignArrow(Arrow
* object
) {
89 WaitableEvent
completion(true, false);
90 message_loop()->PostTask(
92 base::Bind(&BackgroundThread::DoCopyAndAssignArrow
,
93 object
, &completion
));
97 void CopyAndAssignArrowBase(Arrow
* object
) {
98 WaitableEvent
completion(true, false);
99 message_loop()->PostTask(
101 base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase
,
102 object
, &completion
));
106 void DeleteArrow(Arrow
* object
) {
107 WaitableEvent
completion(true, false);
108 message_loop()->PostTask(
110 base::Bind(&BackgroundThread::DoDeleteArrow
, object
, &completion
));
114 Target
* DeRef(const Arrow
* arrow
) {
115 WaitableEvent
completion(true, false);
116 Target
* result
= NULL
;
117 message_loop()->PostTask(
119 base::Bind(&BackgroundThread::DoDeRef
, arrow
, &result
, &completion
));
125 static void DoCreateArrowFromArrow(Arrow
** arrow
,
127 WaitableEvent
* completion
) {
130 completion
->Signal();
133 static void DoCreateArrowFromTarget(Arrow
** arrow
,
135 WaitableEvent
* completion
) {
137 (*arrow
)->target
= target
->AsWeakPtr();
138 completion
->Signal();
141 static void DoDeRef(const Arrow
* arrow
,
143 WaitableEvent
* completion
) {
144 *result
= arrow
->target
.get();
145 completion
->Signal();
148 static void DoDeleteTarget(Target
* object
, WaitableEvent
* completion
) {
150 completion
->Signal();
153 static void DoCopyAndAssignArrow(Arrow
* object
, WaitableEvent
* completion
) {
156 // Assignment operator.
158 completion
->Signal();
161 static void DoCopyAndAssignArrowBase(
163 WaitableEvent
* completion
) {
165 WeakPtr
<TargetBase
> b
= object
->target
;
166 // Assignment operator.
167 WeakPtr
<TargetBase
> c
;
169 completion
->Signal();
172 static void DoDeleteArrow(Arrow
* object
, WaitableEvent
* completion
) {
174 completion
->Signal();
180 TEST(WeakPtrFactoryTest
, Basic
) {
182 WeakPtrFactory
<int> factory(&data
);
183 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
184 EXPECT_EQ(&data
, ptr
.get());
187 TEST(WeakPtrFactoryTest
, Comparison
) {
189 WeakPtrFactory
<int> factory(&data
);
190 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
191 WeakPtr
<int> ptr2
= ptr
;
192 EXPECT_EQ(ptr
, ptr2
);
195 TEST(WeakPtrFactoryTest
, OutOfScope
) {
197 EXPECT_EQ(NULL
, ptr
.get());
200 WeakPtrFactory
<int> factory(&data
);
201 ptr
= factory
.GetWeakPtr();
203 EXPECT_EQ(NULL
, ptr
.get());
206 TEST(WeakPtrFactoryTest
, Multiple
) {
210 WeakPtrFactory
<int> factory(&data
);
211 a
= factory
.GetWeakPtr();
212 b
= factory
.GetWeakPtr();
213 EXPECT_EQ(&data
, a
.get());
214 EXPECT_EQ(&data
, b
.get());
216 EXPECT_EQ(NULL
, a
.get());
217 EXPECT_EQ(NULL
, b
.get());
220 TEST(WeakPtrFactoryTest
, MultipleStaged
) {
224 WeakPtrFactory
<int> factory(&data
);
225 a
= factory
.GetWeakPtr();
227 WeakPtr
<int> b
= factory
.GetWeakPtr();
229 EXPECT_TRUE(NULL
!= a
.get());
231 EXPECT_EQ(NULL
, a
.get());
234 TEST(WeakPtrFactoryTest
, Dereference
) {
236 data
.member
= "123456";
237 WeakPtrFactory
<Base
> factory(&data
);
238 WeakPtr
<Base
> ptr
= factory
.GetWeakPtr();
239 EXPECT_EQ(&data
, ptr
.get());
240 EXPECT_EQ(data
.member
, (*ptr
).member
);
241 EXPECT_EQ(data
.member
, ptr
->member
);
244 TEST(WeakPtrFactoryTest
, UpCast
) {
246 WeakPtrFactory
<Derived
> factory(&data
);
247 WeakPtr
<Base
> ptr
= factory
.GetWeakPtr();
248 ptr
= factory
.GetWeakPtr();
249 EXPECT_EQ(ptr
.get(), &data
);
252 TEST(WeakPtrTest
, SupportsWeakPtr
) {
254 WeakPtr
<Target
> ptr
= target
.AsWeakPtr();
255 EXPECT_EQ(&target
, ptr
.get());
258 TEST(WeakPtrTest
, DerivedTarget
) {
259 DerivedTarget target
;
260 WeakPtr
<DerivedTarget
> ptr
= AsWeakPtr(&target
);
261 EXPECT_EQ(&target
, ptr
.get());
264 TEST(WeakPtrTest
, InvalidateWeakPtrs
) {
266 WeakPtrFactory
<int> factory(&data
);
267 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
268 EXPECT_EQ(&data
, ptr
.get());
269 EXPECT_TRUE(factory
.HasWeakPtrs());
270 factory
.InvalidateWeakPtrs();
271 EXPECT_EQ(NULL
, ptr
.get());
272 EXPECT_FALSE(factory
.HasWeakPtrs());
275 TEST(WeakPtrTest
, HasWeakPtrs
) {
277 WeakPtrFactory
<int> factory(&data
);
279 WeakPtr
<int> ptr
= factory
.GetWeakPtr();
280 EXPECT_TRUE(factory
.HasWeakPtrs());
282 EXPECT_FALSE(factory
.HasWeakPtrs());
285 TEST(WeakPtrTest
, ObjectAndWeakPtrOnDifferentThreads
) {
286 // Test that it is OK to create an object that supports WeakPtr on one thread,
287 // but use it on another. This tests that we do not trip runtime checks that
288 // ensure that a WeakPtr is not used by multiple threads.
289 scoped_ptr
<Target
> target(OffThreadObjectCreator
<Target
>::NewObject());
290 WeakPtr
<Target
> weak_ptr
= target
->AsWeakPtr();
291 EXPECT_EQ(target
.get(), weak_ptr
.get());
294 TEST(WeakPtrTest
, WeakPtrInitiateAndUseOnDifferentThreads
) {
295 // Test that it is OK to create an object that has a WeakPtr member on one
296 // thread, but use it on another. This tests that we do not trip runtime
297 // checks that ensure that a WeakPtr is not used by multiple threads.
298 scoped_ptr
<Arrow
> arrow(OffThreadObjectCreator
<Arrow
>::NewObject());
300 arrow
->target
= target
.AsWeakPtr();
301 EXPECT_EQ(&target
, arrow
->target
.get());
304 TEST(WeakPtrTest
, MoveOwnershipImplicitly
) {
305 // Move object ownership to another thread by releasing all weak pointers
306 // on the original thread first, and then establish WeakPtr on a different
308 BackgroundThread background
;
311 Target
* target
= new Target();
313 WeakPtr
<Target
> weak_ptr
= target
->AsWeakPtr();
314 // Main thread deletes the WeakPtr, then the thread ownership of the
315 // object can be implicitly moved.
319 // Background thread creates WeakPtr(and implicitly owns the object).
320 background
.CreateArrowFromTarget(&arrow
, target
);
321 EXPECT_EQ(background
.DeRef(arrow
), target
);
324 // Main thread creates another WeakPtr, but this does not trigger implicitly
325 // thread ownership move.
327 arrow
.target
= target
->AsWeakPtr();
329 // The new WeakPtr is owned by background thread.
330 EXPECT_EQ(target
, background
.DeRef(&arrow
));
333 // Target can only be deleted on background thread.
334 background
.DeleteTarget(target
);
335 background
.DeleteArrow(arrow
);
338 TEST(WeakPtrTest
, MoveOwnershipExplicitlyObjectNotReferenced
) {
339 // Case 1: The target is not bound to any thread yet. So calling
340 // DetachFromThread() is a no-op.
342 target
.DetachFromThread();
344 // Case 2: The target is bound to main thread but no WeakPtr is pointing to
345 // it. In this case, it will be re-bound to any thread trying to get a
346 // WeakPtr pointing to it. So detach function call is again no-op.
348 WeakPtr
<Target
> weak_ptr
= target
.AsWeakPtr();
350 target
.DetachFromThread();
353 TEST(WeakPtrTest
, MoveOwnershipExplicitly
) {
354 BackgroundThread background
;
360 // Background thread creates WeakPtr(and implicitly owns the object).
361 background
.CreateArrowFromTarget(&arrow
, &target
);
362 EXPECT_EQ(&target
, background
.DeRef(arrow
));
364 // Detach from background thread.
365 target
.DetachFromThread();
367 // Re-bind to main thread.
368 EXPECT_EQ(&target
, arrow
->target
.get());
370 // Main thread can now delete the target.
373 // WeakPtr can be deleted on non-owner thread.
374 background
.DeleteArrow(arrow
);
377 TEST(WeakPtrTest
, MainThreadRefOutlivesBackgroundThreadRef
) {
378 // Originating thread has a WeakPtr that outlives others.
379 // - Main thread creates a WeakPtr
380 // - Background thread creates a WeakPtr copy from the one in main thread
381 // - Destruct the WeakPtr on background thread
382 // - Destruct the WeakPtr on main thread
383 BackgroundThread background
;
388 arrow
.target
= target
.AsWeakPtr();
391 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
392 EXPECT_EQ(arrow_copy
->target
, &target
);
393 background
.DeleteArrow(arrow_copy
);
396 TEST(WeakPtrTest
, BackgroundThreadRefOutlivesMainThreadRef
) {
397 // Originating thread drops all references before another thread.
398 // - Main thread creates a WeakPtr and passes copy to background thread
399 // - Destruct the pointer on main thread
400 // - Destruct the pointer on background thread
401 BackgroundThread background
;
408 arrow
.target
= target
.AsWeakPtr();
409 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
411 EXPECT_EQ(arrow_copy
->target
, &target
);
412 background
.DeleteArrow(arrow_copy
);
415 TEST(WeakPtrTest
, OwnerThreadDeletesObject
) {
416 // Originating thread invalidates WeakPtrs while its held by other thread.
417 // - Main thread creates WeakPtr and passes Copy to background thread
418 // - Object gets destroyed on main thread
419 // (invalidates WeakPtr on background thread)
420 // - WeakPtr gets destroyed on Thread B
421 BackgroundThread background
;
427 arrow
.target
= target
.AsWeakPtr();
428 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
430 EXPECT_EQ(NULL
, arrow_copy
->target
.get());
431 background
.DeleteArrow(arrow_copy
);
434 TEST(WeakPtrTest
, NonOwnerThreadCanCopyAndAssignWeakPtr
) {
435 // Main thread creates a Target object.
437 // Main thread creates an arrow referencing the Target.
438 Arrow
* arrow
= new Arrow();
439 arrow
->target
= target
.AsWeakPtr();
441 // Background can copy and assign arrow (as well as the WeakPtr inside).
442 BackgroundThread background
;
444 background
.CopyAndAssignArrow(arrow
);
447 TEST(WeakPtrTest
, NonOwnerThreadCanCopyAndAssignWeakPtrBase
) {
448 // Main thread creates a Target object.
450 // Main thread creates an arrow referencing the Target.
451 Arrow
* arrow
= new Arrow();
452 arrow
->target
= target
.AsWeakPtr();
454 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
455 BackgroundThread background
;
457 background
.CopyAndAssignArrowBase(arrow
);
460 TEST(WeakPtrTest
, NonOwnerThreadCanDeleteWeakPtr
) {
461 // Main thread creates a Target object.
463 // Main thread creates an arrow referencing the Target.
464 Arrow
* arrow
= new Arrow();
465 arrow
->target
= target
.AsWeakPtr();
467 // Background can delete arrow (as well as the WeakPtr inside).
468 BackgroundThread background
;
470 background
.DeleteArrow(arrow
);
473 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
475 TEST(WeakPtrDeathTest
, WeakPtrCopyDoesNotChangeThreadBinding
) {
476 // The default style "fast" does not support multi-threaded tests
477 // (introduces deadlock on Linux).
478 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
480 BackgroundThread background
;
483 // Main thread creates a Target object.
485 // Main thread creates an arrow referencing the Target.
487 arrow
.target
= target
.AsWeakPtr();
489 // Background copies the WeakPtr.
491 background
.CreateArrowFromArrow(&arrow_copy
, &arrow
);
493 // The copy is still bound to main thread so I can deref.
494 EXPECT_EQ(arrow
.target
.get(), arrow_copy
->target
.get());
496 // Although background thread created the copy, it can not deref the copied
498 ASSERT_DEATH(background
.DeRef(arrow_copy
), "");
500 background
.DeleteArrow(arrow_copy
);
503 TEST(WeakPtrDeathTest
, NonOwnerThreadDereferencesWeakPtr
) {
504 // The default style "fast" does not support multi-threaded tests
505 // (introduces deadlock on Linux).
506 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
508 // Main thread creates a Target object.
511 // Main thread creates an arrow referencing the Target (so target's
512 // thread ownership can not be implicitly moved).
514 arrow
.target
= target
.AsWeakPtr();
516 // Background thread tries to deref target, which violates thread ownership.
517 BackgroundThread background
;
519 ASSERT_DEATH(background
.DeRef(&arrow
), "");
522 TEST(WeakPtrDeathTest
, NonOwnerThreadDeletesObject
) {
523 // The default style "fast" does not support multi-threaded tests
524 // (introduces deadlock on Linux).
525 ::testing::FLAGS_gtest_death_test_style
= "threadsafe";
527 scoped_ptr
<Target
> target(new Target());
528 // Main thread creates an arrow referencing the Target (so target's thread
529 // ownership can not be implicitly moved).
531 arrow
.target
= target
->AsWeakPtr();
533 // Background thread tries to delete target, which violates thread ownership.
534 BackgroundThread background
;
536 ASSERT_DEATH(background
.DeleteTarget(target
.release()), "");