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 |