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 |