| 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> | |
| 65 class AddInObserve : public Foo { | 64 class AddInObserve : public Foo { |
| 66 public: | 65 public: |
| 67 explicit AddInObserve(ObserverListType* observer_list) | 66 explicit AddInObserve(ObserverList<Foo>* observer_list) |
| 68 : added(false), | 67 : added(false), |
| 69 observer_list(observer_list), | 68 observer_list(observer_list), |
| 70 adder(1) { | 69 adder(1) { |
| 71 } | 70 } |
| 72 virtual void Observe(int x) { | 71 virtual void Observe(int x) { |
| 73 if (!added) { | 72 if (!added) { |
| 74 added = true; | 73 added = true; |
| 75 observer_list->AddObserver(&adder); | 74 observer_list->AddObserver(&adder); |
| 76 } | 75 } |
| 77 } | 76 } |
| 78 | 77 |
| 79 bool added; | 78 bool added; |
| 80 ObserverListType* observer_list; | 79 ObserverList<Foo>* observer_list; |
| 81 Adder adder; | 80 Adder adder; |
| 82 }; | 81 }; |
| 83 | 82 |
| 84 | 83 |
| 84 class ObserverListThreadSafeTest : public testing::Test { |
| 85 }; |
| 86 |
| 85 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test. | 87 static const int kThreadRunTime = 2000; // ms to run the multi-threaded test. |
| 86 | 88 |
| 87 // A thread for use in the ThreadSafeObserver test | 89 // A thread for use in the ThreadSafeObserver test |
| 88 // which will add and remove itself from the notification | 90 // which will add and remove itself from the notification |
| 89 // list repeatedly. | 91 // list repeatedly. |
| 90 class AddRemoveThread : public PlatformThread::Delegate, | 92 class AddRemoveThread : public PlatformThread::Delegate, |
| 91 public Foo { | 93 public Foo { |
| 92 public: | 94 public: |
| 93 AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify) | 95 AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify) |
| 94 : list_(list), | 96 : list_(list), |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 // the main thread. | 350 // the main thread. |
| 349 ThreadSafeObserverHarness(7, false); | 351 ThreadSafeObserverHarness(7, false); |
| 350 } | 352 } |
| 351 | 353 |
| 352 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) { | 354 TEST(ObserverListThreadSafeTest, CrossThreadNotifications) { |
| 353 // Use 3 observer threads. Notifications will fire from | 355 // Use 3 observer threads. Notifications will fire from |
| 354 // the main thread and all 3 observer threads. | 356 // the main thread and all 3 observer threads. |
| 355 ThreadSafeObserverHarness(3, true); | 357 ThreadSafeObserverHarness(3, true); |
| 356 } | 358 } |
| 357 | 359 |
| 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 | |
| 370 TEST(ObserverListTest, Existing) { | 360 TEST(ObserverListTest, Existing) { |
| 371 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); | 361 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); |
| 372 Adder a(1); | 362 Adder a(1); |
| 373 AddInObserve<ObserverList<Foo> > b(&observer_list); | 363 AddInObserve b(&observer_list); |
| 374 | 364 |
| 375 observer_list.AddObserver(&a); | 365 observer_list.AddObserver(&a); |
| 376 observer_list.AddObserver(&b); | 366 observer_list.AddObserver(&b); |
| 377 | 367 |
| 378 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); | 368 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); |
| 379 | 369 |
| 380 EXPECT_TRUE(b.added); | 370 EXPECT_TRUE(b.added); |
| 381 // B's adder should not have been notified because it was added during | 371 // B's adder should not have been notified because it was added during |
| 382 // notificaiton. | 372 // notificaiton. |
| 383 EXPECT_EQ(0, b.adder.total); | 373 EXPECT_EQ(0, b.adder.total); |
| 384 | 374 |
| 385 // Notify again to make sure b's adder is notified. | 375 // Notify again to make sure b's adder is notified. |
| 386 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); | 376 FOR_EACH_OBSERVER(Foo, observer_list, Observe(1)); |
| 387 EXPECT_EQ(1, b.adder.total); | 377 EXPECT_EQ(1, b.adder.total); |
| 388 } | 378 } |
| 389 | 379 |
| 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 | |
| 415 class AddInClearObserve : public Foo { | 380 class AddInClearObserve : public Foo { |
| 416 public: | 381 public: |
| 417 explicit AddInClearObserve(ObserverList<Foo>* list) | 382 explicit AddInClearObserve(ObserverList<Foo>* list) |
| 418 : list_(list), added_(false), adder_(1) {} | 383 : list_(list), added_(false), adder_(1) {} |
| 419 | 384 |
| 420 virtual void Observe(int /* x */) { | 385 virtual void Observe(int /* x */) { |
| 421 list_->Clear(); | 386 list_->Clear(); |
| 422 list_->AddObserver(&adder_); | 387 list_->AddObserver(&adder_); |
| 423 added_ = true; | 388 added_ = true; |
| 424 } | 389 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 ObserverList<Foo>* observer_list = new ObserverList<Foo>; | 439 ObserverList<Foo>* observer_list = new ObserverList<Foo>; |
| 475 ListDestructor a(observer_list); | 440 ListDestructor a(observer_list); |
| 476 observer_list->AddObserver(&a); | 441 observer_list->AddObserver(&a); |
| 477 | 442 |
| 478 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0)); | 443 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0)); |
| 479 // If this test fails, there'll be Valgrind errors when this function goes out | 444 // If this test fails, there'll be Valgrind errors when this function goes out |
| 480 // of scope. | 445 // of scope. |
| 481 } | 446 } |
| 482 | 447 |
| 483 } // namespace | 448 } // namespace |
| OLD | NEW |