OLD | NEW |
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/observer_list.h" | 5 #include "base/observer_list.h" |
6 #include "base/observer_list_threadsafe.h" | 6 #include "base/observer_list_threadsafe.h" |
7 | 7 |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 : list_(list), doomed_(doomed) { } | 54 : list_(list), doomed_(doomed) { } |
55 virtual ~ThreadSafeDisrupter() { } | 55 virtual ~ThreadSafeDisrupter() { } |
56 virtual void Observe(int x) { | 56 virtual void Observe(int x) { |
57 list_->RemoveObserver(doomed_); | 57 list_->RemoveObserver(doomed_); |
58 } | 58 } |
59 private: | 59 private: |
60 ObserverListThreadSafe<Foo>* list_; | 60 ObserverListThreadSafe<Foo>* list_; |
61 Foo* doomed_; | 61 Foo* doomed_; |
62 }; | 62 }; |
63 | 63 |
| 64 template <typename ObserverListType> |
64 class AddInObserve : public Foo { | 65 class AddInObserve : public Foo { |
65 public: | 66 public: |
66 explicit AddInObserve(ObserverList<Foo>* observer_list) | 67 explicit AddInObserve(ObserverListType* observer_list) |
67 : added(false), | 68 : added(false), |
68 observer_list(observer_list), | 69 observer_list(observer_list), |
69 adder(1) { | 70 adder(1) { |
70 } | 71 } |
71 virtual void Observe(int x) { | 72 virtual void Observe(int x) { |
72 if (!added) { | 73 if (!added) { |
73 added = true; | 74 added = true; |
74 observer_list->AddObserver(&adder); | 75 observer_list->AddObserver(&adder); |
75 } | 76 } |
76 } | 77 } |
77 | 78 |
78 bool added; | 79 bool added; |
79 ObserverList<Foo>* observer_list; | 80 ObserverListType* observer_list; |
80 Adder adder; | 81 Adder adder; |
81 }; | 82 }; |
82 | 83 |
83 | 84 |
84 class ObserverListThreadSafeTest : public testing::Test { | |
85 }; | |
86 | |
87 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test. | 85 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test. |
88 | 86 |
89 // A thread for use in the ThreadSafeObserver test | 87 // A thread for use in the ThreadSafeObserver test |
90 // which will add and remove itself from the notification | 88 // which will add and remove itself from the notification |
91 // list repeatedly. | 89 // list repeatedly. |
92 class AddRemoveThread : public PlatformThread::Delegate, | 90 class AddRemoveThread : public PlatformThread::Delegate, |
93 public Foo { | 91 public Foo { |
94 public: | 92 public: |
95 AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify) | 93 AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify) |
96 : list_(list), | 94 : list_(list), |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 // the main thread. | 348 // the main thread. |
351 ThreadSafeObserverHarness(7, false); | 349 ThreadSafeObserverHarness(7, false); |
352 } | 350 } |
353 | 351 |
354 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) { | 352 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) { |
355 // Use 3 observer threads. Notifications will fire from | 353 // Use 3 observer threads. Notifications will fire from |
356 // the main thread and all 3 observer threads. | 354 // the main thread and all 3 observer threads. |
357 ThreadSafeObserverHarness(3, true); | 355 ThreadSafeObserverHarness(3, true); |
358 } | 356 } |
359 | 357 |
| 358 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) { |
| 359 MessageLoop* loop = new MessageLoop; |
| 360 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( |
| 361 new ObserverListThreadSafe<Foo>); |
| 362 |
| 363 Adder a(1); |
| 364 observer_list->AddObserver(&a); |
| 365 delete loop; |
| 366 // Test passes if we don't crash here. |
| 367 observer_list->Notify(&Foo::Observe, 1); |
| 368 } |
| 369 |
360 TEST(ObserverListTest, Existing) { | 370 TEST(ObserverListTest, Existing) { |
361 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); | 371 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); |
362 Adder a(1); | 372 Adder a(1); |
363 AddInObserve b(&observer_list); | 373 AddInObserve<ObserverList<Foo> > b(&observer_list); |
364 | 374 |
365 observer_list.AddObserver(&a); | 375 observer_list.AddObserver(&a); |
366 observer_list.AddObserver(&b); | 376 observer_list.AddObserver(&b); |
367 | 377 |
368 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); | 378 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); |
369 | 379 |
370 EXPECT_TRUE(b.added); | 380 EXPECT_TRUE(b.added); |
371 // B's adder should not have been notified because it was added during | 381 // B's adder should not have been notified because it was added during |
372 // notificaiton. | 382 // notificaiton. |
373 EXPECT_EQ(0, b.adder.total); | 383 EXPECT_EQ(0, b.adder.total); |
374 | 384 |
375 // Notify again to make sure b's adder is notified. | 385 // Notify again to make sure b's adder is notified. |
376 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); | 386 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); |
377 EXPECT_EQ(1, b.adder.total); | 387 EXPECT_EQ(1, b.adder.total); |
378 } | 388 } |
379 | 389 |
| 390 // Same as above, but for ObserverListThreadSafe |
| 391 TEST(ObserverListThreadSafeTest, Existing) { |
| 392 MessageLoop loop; |
| 393 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( |
| 394 new ObserverListThreadSafe<Foo>(ObserverList<Foo>::NOTIFY_EXISTING_ONLY)); |
| 395 Adder a(1); |
| 396 AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get()); |
| 397 |
| 398 observer_list->AddObserver(&a); |
| 399 observer_list->AddObserver(&b); |
| 400 |
| 401 observer_list->Notify(&Foo::Observe, 1); |
| 402 loop.RunAllPending(); |
| 403 |
| 404 EXPECT_TRUE(b.added); |
| 405 // B's adder should not have been notified because it was added during |
| 406 // notificaiton. |
| 407 EXPECT_EQ(0, b.adder.total); |
| 408 |
| 409 // Notify again to make sure b's adder is notified. |
| 410 observer_list->Notify(&Foo::Observe, 1); |
| 411 loop.RunAllPending(); |
| 412 EXPECT_EQ(1, b.adder.total); |
| 413 } |
| 414 |
380 class AddInClearObserve : public Foo { | 415 class AddInClearObserve : public Foo { |
381 public: | 416 public: |
382 explicit AddInClearObserve(ObserverList<Foo>* list) | 417 explicit AddInClearObserve(ObserverList<Foo>* list) |
383 : list_(list), added_(false), adder_(1) {} | 418 : list_(list), added_(false), adder_(1) {} |
384 | 419 |
385 virtual void Observe(int /* x */) { | 420 virtual void Observe(int /* x */) { |
386 list_->Clear(); | 421 list_->Clear(); |
387 list_->AddObserver(&adder_); | 422 list_->AddObserver(&adder_); |
388 added_ = true; | 423 added_ = true; |
389 } | 424 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 ObserverList<Foo>* observer_list = new ObserverList<Foo>; | 474 ObserverList<Foo>* observer_list = new ObserverList<Foo>; |
440 ListDestructor a(observer_list); | 475 ListDestructor a(observer_list); |
441 observer_list->AddObserver(&a); | 476 observer_list->AddObserver(&a); |
442 | 477 |
443 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0)); | 478 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0)); |
444 // If this test fails, there'll be Valgrind errors when this function goes out | 479 // If this test fails, there'll be Valgrind errors when this function goes out |
445 // of scope. | 480 // of scope. |
446 } | 481 } |
447 | 482 |
448 } // namespace | 483 } // namespace |
OLD | NEW |