| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 VLOG(1) << "DONE!"; | 127 VLOG(1) << "DONE!"; |
| 128 return; | 128 return; |
| 129 } | 129 } |
| 130 | 130 |
| 131 if (!in_list_) { | 131 if (!in_list_) { |
| 132 list_->AddObserver(this); | 132 list_->AddObserver(this); |
| 133 in_list_ = true; | 133 in_list_ = true; |
| 134 } | 134 } |
| 135 | 135 |
| 136 if (do_notifies_) { | 136 if (do_notifies_) { |
| 137 list_->Notify(&Foo::Observe, 10); | 137 list_->Notify(FROM_HERE, &Foo::Observe, 10); |
| 138 } | 138 } |
| 139 | 139 |
| 140 loop_->PostTask( | 140 loop_->PostTask( |
| 141 FROM_HERE, | 141 FROM_HERE, |
| 142 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr())); | 142 base::Bind(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr())); |
| 143 } | 143 } |
| 144 | 144 |
| 145 void Quit() { | 145 void Quit() { |
| 146 loop_->PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); | 146 loop_->PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); |
| 147 } | 147 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 new ObserverListThreadSafe<Foo>); | 210 new ObserverListThreadSafe<Foo>); |
| 211 Adder a(1); | 211 Adder a(1); |
| 212 Adder b(-1); | 212 Adder b(-1); |
| 213 Adder c(1); | 213 Adder c(1); |
| 214 Adder d(-1); | 214 Adder d(-1); |
| 215 ThreadSafeDisrupter evil(observer_list.get(), &c); | 215 ThreadSafeDisrupter evil(observer_list.get(), &c); |
| 216 | 216 |
| 217 observer_list->AddObserver(&a); | 217 observer_list->AddObserver(&a); |
| 218 observer_list->AddObserver(&b); | 218 observer_list->AddObserver(&b); |
| 219 | 219 |
| 220 observer_list->Notify(&Foo::Observe, 10); | 220 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); |
| 221 RunLoop().RunUntilIdle(); | 221 RunLoop().RunUntilIdle(); |
| 222 | 222 |
| 223 observer_list->AddObserver(&evil); | 223 observer_list->AddObserver(&evil); |
| 224 observer_list->AddObserver(&c); | 224 observer_list->AddObserver(&c); |
| 225 observer_list->AddObserver(&d); | 225 observer_list->AddObserver(&d); |
| 226 | 226 |
| 227 observer_list->Notify(&Foo::Observe, 10); | 227 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); |
| 228 RunLoop().RunUntilIdle(); | 228 RunLoop().RunUntilIdle(); |
| 229 | 229 |
| 230 EXPECT_EQ(20, a.total); | 230 EXPECT_EQ(20, a.total); |
| 231 EXPECT_EQ(-20, b.total); | 231 EXPECT_EQ(-20, b.total); |
| 232 EXPECT_EQ(0, c.total); | 232 EXPECT_EQ(0, c.total); |
| 233 EXPECT_EQ(-10, d.total); | 233 EXPECT_EQ(-10, d.total); |
| 234 } | 234 } |
| 235 | 235 |
| 236 TEST(ObserverListThreadSafeTest, RemoveObserver) { | 236 TEST(ObserverListThreadSafeTest, RemoveObserver) { |
| 237 MessageLoop loop; | 237 MessageLoop loop; |
| 238 | 238 |
| 239 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( | 239 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( |
| 240 new ObserverListThreadSafe<Foo>); | 240 new ObserverListThreadSafe<Foo>); |
| 241 Adder a(1), b(1); | 241 Adder a(1), b(1); |
| 242 | 242 |
| 243 // A workaround for the compiler bug. See http://crbug.com/121960. | 243 // A workaround for the compiler bug. See http://crbug.com/121960. |
| 244 EXPECT_NE(&a, &b); | 244 EXPECT_NE(&a, &b); |
| 245 | 245 |
| 246 // Should do nothing. | 246 // Should do nothing. |
| 247 observer_list->RemoveObserver(&a); | 247 observer_list->RemoveObserver(&a); |
| 248 observer_list->RemoveObserver(&b); | 248 observer_list->RemoveObserver(&b); |
| 249 | 249 |
| 250 observer_list->Notify(&Foo::Observe, 10); | 250 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); |
| 251 RunLoop().RunUntilIdle(); | 251 RunLoop().RunUntilIdle(); |
| 252 | 252 |
| 253 EXPECT_EQ(0, a.total); | 253 EXPECT_EQ(0, a.total); |
| 254 EXPECT_EQ(0, b.total); | 254 EXPECT_EQ(0, b.total); |
| 255 | 255 |
| 256 observer_list->AddObserver(&a); | 256 observer_list->AddObserver(&a); |
| 257 | 257 |
| 258 // Should also do nothing. | 258 // Should also do nothing. |
| 259 observer_list->RemoveObserver(&b); | 259 observer_list->RemoveObserver(&b); |
| 260 | 260 |
| 261 observer_list->Notify(&Foo::Observe, 10); | 261 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); |
| 262 RunLoop().RunUntilIdle(); | 262 RunLoop().RunUntilIdle(); |
| 263 | 263 |
| 264 EXPECT_EQ(10, a.total); | 264 EXPECT_EQ(10, a.total); |
| 265 EXPECT_EQ(0, b.total); | 265 EXPECT_EQ(0, b.total); |
| 266 } | 266 } |
| 267 | 267 |
| 268 TEST(ObserverListThreadSafeTest, WithoutMessageLoop) { | 268 TEST(ObserverListThreadSafeTest, WithoutMessageLoop) { |
| 269 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( | 269 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( |
| 270 new ObserverListThreadSafe<Foo>); | 270 new ObserverListThreadSafe<Foo>); |
| 271 | 271 |
| 272 Adder a(1), b(1), c(1); | 272 Adder a(1), b(1), c(1); |
| 273 | 273 |
| 274 // No MessageLoop, so these should not be added. | 274 // No MessageLoop, so these should not be added. |
| 275 observer_list->AddObserver(&a); | 275 observer_list->AddObserver(&a); |
| 276 observer_list->AddObserver(&b); | 276 observer_list->AddObserver(&b); |
| 277 | 277 |
| 278 { | 278 { |
| 279 // Add c when there's a loop. | 279 // Add c when there's a loop. |
| 280 MessageLoop loop; | 280 MessageLoop loop; |
| 281 observer_list->AddObserver(&c); | 281 observer_list->AddObserver(&c); |
| 282 | 282 |
| 283 observer_list->Notify(&Foo::Observe, 10); | 283 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); |
| 284 RunLoop().RunUntilIdle(); | 284 RunLoop().RunUntilIdle(); |
| 285 | 285 |
| 286 EXPECT_EQ(0, a.total); | 286 EXPECT_EQ(0, a.total); |
| 287 EXPECT_EQ(0, b.total); | 287 EXPECT_EQ(0, b.total); |
| 288 EXPECT_EQ(10, c.total); | 288 EXPECT_EQ(10, c.total); |
| 289 | 289 |
| 290 // Now add a when there's a loop. | 290 // Now add a when there's a loop. |
| 291 observer_list->AddObserver(&a); | 291 observer_list->AddObserver(&a); |
| 292 | 292 |
| 293 // Remove c when there's a loop. | 293 // Remove c when there's a loop. |
| 294 observer_list->RemoveObserver(&c); | 294 observer_list->RemoveObserver(&c); |
| 295 | 295 |
| 296 // Notify again. | 296 // Notify again. |
| 297 observer_list->Notify(&Foo::Observe, 20); | 297 observer_list->Notify(FROM_HERE, &Foo::Observe, 20); |
| 298 RunLoop().RunUntilIdle(); | 298 RunLoop().RunUntilIdle(); |
| 299 | 299 |
| 300 EXPECT_EQ(20, a.total); | 300 EXPECT_EQ(20, a.total); |
| 301 EXPECT_EQ(0, b.total); | 301 EXPECT_EQ(0, b.total); |
| 302 EXPECT_EQ(10, c.total); | 302 EXPECT_EQ(10, c.total); |
| 303 } | 303 } |
| 304 | 304 |
| 305 // Removing should always succeed with or without a loop. | 305 // Removing should always succeed with or without a loop. |
| 306 observer_list->RemoveObserver(&a); | 306 observer_list->RemoveObserver(&a); |
| 307 | 307 |
| 308 // Notifying should not fail but should also be a no-op. | 308 // Notifying should not fail but should also be a no-op. |
| 309 MessageLoop loop; | 309 MessageLoop loop; |
| 310 observer_list->AddObserver(&b); | 310 observer_list->AddObserver(&b); |
| 311 observer_list->Notify(&Foo::Observe, 30); | 311 observer_list->Notify(FROM_HERE, &Foo::Observe, 30); |
| 312 RunLoop().RunUntilIdle(); | 312 RunLoop().RunUntilIdle(); |
| 313 | 313 |
| 314 EXPECT_EQ(20, a.total); | 314 EXPECT_EQ(20, a.total); |
| 315 EXPECT_EQ(30, b.total); | 315 EXPECT_EQ(30, b.total); |
| 316 EXPECT_EQ(10, c.total); | 316 EXPECT_EQ(10, c.total); |
| 317 } | 317 } |
| 318 | 318 |
| 319 class FooRemover : public Foo { | 319 class FooRemover : public Foo { |
| 320 public: | 320 public: |
| 321 explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {} | 321 explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {} |
| (...skipping 24 matching lines...) Expand all Loading... |
| 346 | 346 |
| 347 FooRemover a(observer_list.get()); | 347 FooRemover a(observer_list.get()); |
| 348 Adder b(1); | 348 Adder b(1); |
| 349 | 349 |
| 350 observer_list->AddObserver(&a); | 350 observer_list->AddObserver(&a); |
| 351 observer_list->AddObserver(&b); | 351 observer_list->AddObserver(&b); |
| 352 | 352 |
| 353 a.AddFooToRemove(&a); | 353 a.AddFooToRemove(&a); |
| 354 a.AddFooToRemove(&b); | 354 a.AddFooToRemove(&b); |
| 355 | 355 |
| 356 observer_list->Notify(&Foo::Observe, 1); | 356 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); |
| 357 RunLoop().RunUntilIdle(); | 357 RunLoop().RunUntilIdle(); |
| 358 } | 358 } |
| 359 | 359 |
| 360 // A test driver for a multi-threaded notification loop. Runs a number | 360 // A test driver for a multi-threaded notification loop. Runs a number |
| 361 // of observer threads, each of which constantly adds/removes itself | 361 // of observer threads, each of which constantly adds/removes itself |
| 362 // from the observer list. Optionally, if cross_thread_notifies is set | 362 // from the observer list. Optionally, if cross_thread_notifies is set |
| 363 // to true, the observer threads will also trigger notifications to | 363 // to true, the observer threads will also trigger notifications to |
| 364 // all observers. | 364 // all observers. |
| 365 static void ThreadSafeObserverHarness(int num_threads, | 365 static void ThreadSafeObserverHarness(int num_threads, |
| 366 bool cross_thread_notifies) { | 366 bool cross_thread_notifies) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 385 threaded_observer[index] = new AddRemoveThread(observer_list.get(), false); | 385 threaded_observer[index] = new AddRemoveThread(observer_list.get(), false); |
| 386 EXPECT_TRUE(PlatformThread::Create(0, | 386 EXPECT_TRUE(PlatformThread::Create(0, |
| 387 threaded_observer[index], &threads[index])); | 387 threaded_observer[index], &threads[index])); |
| 388 } | 388 } |
| 389 | 389 |
| 390 Time start = Time::Now(); | 390 Time start = Time::Now(); |
| 391 while (true) { | 391 while (true) { |
| 392 if ((Time::Now() - start).InMilliseconds() > kThreadRunTime) | 392 if ((Time::Now() - start).InMilliseconds() > kThreadRunTime) |
| 393 break; | 393 break; |
| 394 | 394 |
| 395 observer_list->Notify(&Foo::Observe, 10); | 395 observer_list->Notify(FROM_HERE, &Foo::Observe, 10); |
| 396 | 396 |
| 397 RunLoop().RunUntilIdle(); | 397 RunLoop().RunUntilIdle(); |
| 398 } | 398 } |
| 399 | 399 |
| 400 for (int index = 0; index < num_threads; index++) { | 400 for (int index = 0; index < num_threads; index++) { |
| 401 threaded_observer[index]->Quit(); | 401 threaded_observer[index]->Quit(); |
| 402 PlatformThread::Join(threads[index]); | 402 PlatformThread::Join(threads[index]); |
| 403 } | 403 } |
| 404 } | 404 } |
| 405 | 405 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 417 | 417 |
| 418 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) { | 418 TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) { |
| 419 MessageLoop* loop = new MessageLoop; | 419 MessageLoop* loop = new MessageLoop; |
| 420 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( | 420 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( |
| 421 new ObserverListThreadSafe<Foo>); | 421 new ObserverListThreadSafe<Foo>); |
| 422 | 422 |
| 423 Adder a(1); | 423 Adder a(1); |
| 424 observer_list->AddObserver(&a); | 424 observer_list->AddObserver(&a); |
| 425 delete loop; | 425 delete loop; |
| 426 // Test passes if we don't crash here. | 426 // Test passes if we don't crash here. |
| 427 observer_list->Notify(&Foo::Observe, 1); | 427 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); |
| 428 } | 428 } |
| 429 | 429 |
| 430 TEST(ObserverListTest, Existing) { | 430 TEST(ObserverListTest, Existing) { |
| 431 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); | 431 ObserverList<Foo> observer_list(ObserverList<Foo>::NOTIFY_EXISTING_ONLY); |
| 432 Adder a(1); | 432 Adder a(1); |
| 433 AddInObserve<ObserverList<Foo> > b(&observer_list); | 433 AddInObserve<ObserverList<Foo> > b(&observer_list); |
| 434 | 434 |
| 435 observer_list.AddObserver(&a); | 435 observer_list.AddObserver(&a); |
| 436 observer_list.AddObserver(&b); | 436 observer_list.AddObserver(&b); |
| 437 | 437 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 451 TEST(ObserverListThreadSafeTest, Existing) { | 451 TEST(ObserverListThreadSafeTest, Existing) { |
| 452 MessageLoop loop; | 452 MessageLoop loop; |
| 453 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( | 453 scoped_refptr<ObserverListThreadSafe<Foo> > observer_list( |
| 454 new ObserverListThreadSafe<Foo>(ObserverList<Foo>::NOTIFY_EXISTING_ONLY)); | 454 new ObserverListThreadSafe<Foo>(ObserverList<Foo>::NOTIFY_EXISTING_ONLY)); |
| 455 Adder a(1); | 455 Adder a(1); |
| 456 AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get()); | 456 AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get()); |
| 457 | 457 |
| 458 observer_list->AddObserver(&a); | 458 observer_list->AddObserver(&a); |
| 459 observer_list->AddObserver(&b); | 459 observer_list->AddObserver(&b); |
| 460 | 460 |
| 461 observer_list->Notify(&Foo::Observe, 1); | 461 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); |
| 462 RunLoop().RunUntilIdle(); | 462 RunLoop().RunUntilIdle(); |
| 463 | 463 |
| 464 EXPECT_TRUE(b.added); | 464 EXPECT_TRUE(b.added); |
| 465 // B's adder should not have been notified because it was added during | 465 // B's adder should not have been notified because it was added during |
| 466 // notification. | 466 // notification. |
| 467 EXPECT_EQ(0, b.adder.total); | 467 EXPECT_EQ(0, b.adder.total); |
| 468 | 468 |
| 469 // Notify again to make sure b's adder is notified. | 469 // Notify again to make sure b's adder is notified. |
| 470 observer_list->Notify(&Foo::Observe, 1); | 470 observer_list->Notify(FROM_HERE, &Foo::Observe, 1); |
| 471 RunLoop().RunUntilIdle(); | 471 RunLoop().RunUntilIdle(); |
| 472 EXPECT_EQ(1, b.adder.total); | 472 EXPECT_EQ(1, b.adder.total); |
| 473 } | 473 } |
| 474 | 474 |
| 475 class AddInClearObserve : public Foo { | 475 class AddInClearObserve : public Foo { |
| 476 public: | 476 public: |
| 477 explicit AddInClearObserve(ObserverList<Foo>* list) | 477 explicit AddInClearObserve(ObserverList<Foo>* list) |
| 478 : list_(list), added_(false), adder_(1) {} | 478 : list_(list), added_(false), adder_(1) {} |
| 479 | 479 |
| 480 void Observe(int /* x */) override { | 480 void Observe(int /* x */) override { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 ListDestructor a(observer_list); | 534 ListDestructor a(observer_list); |
| 535 observer_list->AddObserver(&a); | 535 observer_list->AddObserver(&a); |
| 536 | 536 |
| 537 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0)); | 537 FOR_EACH_OBSERVER(Foo, *observer_list, Observe(0)); |
| 538 // If this test fails, there'll be Valgrind errors when this function goes out | 538 // If this test fails, there'll be Valgrind errors when this function goes out |
| 539 // of scope. | 539 // of scope. |
| 540 } | 540 } |
| 541 | 541 |
| 542 } // namespace | 542 } // namespace |
| 543 } // namespace base | 543 } // namespace base |
| OLD | NEW |