Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1106)

Side by Side Diff: webrtc/base/sigslot.h

Issue 2847243006: Revert of Fixing crash that can occur if signal is modified while firing. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | webrtc/base/sigslot_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // sigslot.h: Signal/Slot classes 1 // sigslot.h: Signal/Slot classes
2 // 2 //
3 // Written by Sarah Thompson (sarah@telergy.com) 2002. 3 // Written by Sarah Thompson (sarah@telergy.com) 2002.
4 // 4 //
5 // License: Public domain. You are free to use this code however you like, with the proviso that 5 // License: Public domain. You are free to use this code however you like, with the proviso that
6 // the author takes on no responsibility or liability for any use. 6 // the author takes on no responsibility or liability for any use.
7 // 7 //
8 // QUICK DOCUMENTATION 8 // QUICK DOCUMENTATION
9 // 9 //
10 // (see also the full documentation at http://sigsl ot.sourceforge.net/) 10 // (see also the full documentation at http://sigsl ot.sourceforge.net/)
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 (static_cast< DestT* >(self->pdest)->*(pm))(args...); 387 (static_cast< DestT* >(self->pdest)->*(pm))(args...);
388 } 388 }
389 }; 389 };
390 390
391 template<class mt_policy> 391 template<class mt_policy>
392 class _signal_base : public _signal_base_interface, public mt_policy 392 class _signal_base : public _signal_base_interface, public mt_policy
393 { 393 {
394 protected: 394 protected:
395 typedef std::list< _opaque_connection > connections_list; 395 typedef std::list< _opaque_connection > connections_list;
396 396
397 » » _signal_base() : _signal_base_interface(&_signal_base::do_slot_d isconnect, &_signal_base::do_slot_duplicate), 397 » » _signal_base() : _signal_base_interface(&_signal_base::do_slot_d isconnect, &_signal_base::do_slot_duplicate)
398 m_current_iterator(m_connected_slots.end())
399 { 398 {
400 } 399 }
401 400
402 ~_signal_base() 401 ~_signal_base()
403 { 402 {
404 disconnect_all(); 403 disconnect_all();
405 } 404 }
406 405
407 private: 406 private:
408 _signal_base& operator= (_signal_base const& that); 407 _signal_base& operator= (_signal_base const& that);
409 408
410 public: 409 public:
411 » » _signal_base(const _signal_base& o) : _signal_base_interface(&_s ignal_base::do_slot_disconnect, &_signal_base::do_slot_duplicate), 410 » » _signal_base(const _signal_base& o) : _signal_base_interface(&_s ignal_base::do_slot_disconnect, &_signal_base::do_slot_duplicate) {
412 m_current_iterator(m_connected_slots.end()) {
413 lock_block<mt_policy> lock(this); 411 lock_block<mt_policy> lock(this);
414 for (const auto& connection : o.m_connected_slots) 412 for (const auto& connection : o.m_connected_slots)
415 { 413 {
416 connection.getdest()->signal_connect(this); 414 connection.getdest()->signal_connect(this);
417 m_connected_slots.push_back(connection); 415 m_connected_slots.push_back(connection);
418 } 416 }
419 } 417 }
420 418
421 bool is_empty() 419 bool is_empty()
422 { 420 {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 void disconnect(has_slots_interface* pclass) 453 void disconnect(has_slots_interface* pclass)
456 { 454 {
457 lock_block<mt_policy> lock(this); 455 lock_block<mt_policy> lock(this);
458 connections_list::iterator it = m_connected_slots.begin( ); 456 connections_list::iterator it = m_connected_slots.begin( );
459 connections_list::iterator itEnd = m_connected_slots.end (); 457 connections_list::iterator itEnd = m_connected_slots.end ();
460 458
461 while(it != itEnd) 459 while(it != itEnd)
462 { 460 {
463 if(it->getdest() == pclass) 461 if(it->getdest() == pclass)
464 { 462 {
465 // If we're currently using this iterator, 463 » » » » » m_connected_slots.erase(it);
466 // don't erase it and invalidate it yet; set a
467 // flag to do so afterwards.
468 if (m_current_iterator == it) {
469 m_erase_current_iterator = true;
470 } else {
471 m_connected_slots.erase(it);
472 }
473 pclass->signal_disconnect(static_cast< _ signal_base_interface* >(this)); 464 pclass->signal_disconnect(static_cast< _ signal_base_interface* >(this));
474 return; 465 return;
475 } 466 }
476 467
477 ++it; 468 ++it;
478 } 469 }
479 } 470 }
480 471
481 private: 472 private:
482 static void do_slot_disconnect(_signal_base_interface* p, has_sl ots_interface* pslot) 473 static void do_slot_disconnect(_signal_base_interface* p, has_sl ots_interface* pslot)
483 { 474 {
484 _signal_base* const self = static_cast< _signal_base* >( p); 475 _signal_base* const self = static_cast< _signal_base* >( p);
485 lock_block<mt_policy> lock(self); 476 lock_block<mt_policy> lock(self);
486 connections_list::iterator it = self->m_connected_slots. begin(); 477 connections_list::iterator it = self->m_connected_slots. begin();
487 connections_list::iterator itEnd = self->m_connected_slo ts.end(); 478 connections_list::iterator itEnd = self->m_connected_slo ts.end();
488 479
489 while(it != itEnd) 480 while(it != itEnd)
490 { 481 {
491 connections_list::iterator itNext = it; 482 connections_list::iterator itNext = it;
492 ++itNext; 483 ++itNext;
493 484
494 if(it->getdest() == pslot) 485 if(it->getdest() == pslot)
495 { 486 {
496 // If we're currently using this iterator, 487 » » » » » self->m_connected_slots.erase(it);
497 // don't erase it and invalidate it yet; set a 488 » » » » }
498 // flag to do so afterwards.
499 if (self->m_current_iterator == it) {
500 self->m_erase_current_iterator = true;
501 } else {
502 self->m_connected_slots.erase(it);
503 }
504 }
505 489
506 it = itNext; 490 it = itNext;
507 } 491 }
508 } 492 }
509 493
510 static void do_slot_duplicate(_signal_base_interface* p, const h as_slots_interface* oldtarget, has_slots_interface* newtarget) 494 static void do_slot_duplicate(_signal_base_interface* p, const h as_slots_interface* oldtarget, has_slots_interface* newtarget)
511 { 495 {
512 _signal_base* const self = static_cast< _signal_base* >( p); 496 _signal_base* const self = static_cast< _signal_base* >( p);
513 lock_block<mt_policy> lock(self); 497 lock_block<mt_policy> lock(self);
514 connections_list::iterator it = self->m_connected_slots. begin(); 498 connections_list::iterator it = self->m_connected_slots. begin();
515 connections_list::iterator itEnd = self->m_connected_slo ts.end(); 499 connections_list::iterator itEnd = self->m_connected_slo ts.end();
516 500
517 while(it != itEnd) 501 while(it != itEnd)
518 { 502 {
519 if(it->getdest() == oldtarget) 503 if(it->getdest() == oldtarget)
520 { 504 {
521 self->m_connected_slots.push_back(it->du plicate(newtarget)); 505 self->m_connected_slots.push_back(it->du plicate(newtarget));
522 } 506 }
523 507
524 ++it; 508 ++it;
525 } 509 }
526 } 510 }
527 511
528 protected: 512 protected:
529 connections_list m_connected_slots; 513 connections_list m_connected_slots;
530 514 » };
531 // Used to handle a slot being disconnected while a signal is
532 // firing (iterating m_connected_slots).
533 connections_list::iterator m_current_iterator;
534 bool m_erase_current_iterator = false;
535 };
536 515
537 template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY> 516 template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
538 class has_slots : public has_slots_interface, public mt_policy 517 class has_slots : public has_slots_interface, public mt_policy
539 { 518 {
540 private: 519 private:
541 typedef std::set< _signal_base_interface* > sender_set; 520 typedef std::set< _signal_base_interface* > sender_set;
542 typedef sender_set::const_iterator const_iterator; 521 typedef sender_set::const_iterator const_iterator;
543 522
544 public: 523 public:
545 has_slots() : has_slots_interface(&has_slots::do_signal_connect, &has_slots::do_signal_disconnect, &has_slots::do_disconnect_all) 524 has_slots() : has_slots_interface(&has_slots::do_signal_connect, &has_slots::do_signal_disconnect, &has_slots::do_disconnect_all)
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 void connect(desttype* pclass, void (desttype::*pmemfun)(Args... )) 598 void connect(desttype* pclass, void (desttype::*pmemfun)(Args... ))
620 { 599 {
621 lock_block<mt_policy> lock(this); 600 lock_block<mt_policy> lock(this);
622 this->m_connected_slots.push_back(_opaque_connection(pcl ass, pmemfun)); 601 this->m_connected_slots.push_back(_opaque_connection(pcl ass, pmemfun));
623 pclass->signal_connect(static_cast< _signal_base_interfa ce* >(this)); 602 pclass->signal_connect(static_cast< _signal_base_interfa ce* >(this));
624 } 603 }
625 604
626 void emit(Args... args) 605 void emit(Args... args)
627 { 606 {
628 lock_block<mt_policy> lock(this); 607 lock_block<mt_policy> lock(this);
629 this->m_current_iterator = 608 » » » typename connections_list::const_iterator it = this->m_c onnected_slots.begin();
630 this->m_connected_slots.begin(); 609 » » » typename connections_list::const_iterator itEnd = this-> m_connected_slots.end();
631 while (this->m_current_iterator != 610
632 this->m_connected_slots.end()) { 611 » » » while(it != itEnd)
633 _opaque_connection const& conn = 612 » » » {
634 *this->m_current_iterator; 613 » » » » _opaque_connection const& conn = *it;
635 conn.emit<Args...>(args...); 614 » » » » ++it;
636 if (this->m_erase_current_iterator) { 615
637 this->m_current_iterator = 616 » » » » conn.emit<Args...>(args...);
638 this->m_connected_slots.erase( 617 » » » }
639 this->m_current_iterator);
640 this->m_erase_current_iterator = false;
641 } else {
642 ++(this->m_current_iterator);
643 }
644 }
645 } 618 }
646 619
647 void operator()(Args... args) 620 void operator()(Args... args)
648 { 621 {
649 emit(args...); 622 emit(args...);
650 } 623 }
651 }; 624 };
652 625
653 // Alias with default thread policy. Needed because both default argumen ts 626 // Alias with default thread policy. Needed because both default argumen ts
654 // and variadic template arguments must go at the end of the list, so we 627 // and variadic template arguments must go at the end of the list, so we
(...skipping 28 matching lines...) Expand all
683 656
684 template<typename A1, typename A2, typename A3, typename A4, typename A5 , typename A6, typename A7, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY> 657 template<typename A1, typename A2, typename A3, typename A4, typename A5 , typename A6, typename A7, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
685 using signal7 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7>; 658 using signal7 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7>;
686 659
687 template<typename A1, typename A2, typename A3, typename A4, typename A5 , typename A6, typename A7, typename A8, typename mt_policy = SIGSLOT_DEFAULT_MT _POLICY> 660 template<typename A1, typename A2, typename A3, typename A4, typename A5 , typename A6, typename A7, typename A8, typename mt_policy = SIGSLOT_DEFAULT_MT _POLICY>
688 using signal8 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7, A8>; 661 using signal8 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7, A8>;
689 662
690 } // namespace sigslot 663 } // namespace sigslot
691 664
692 #endif // WEBRTC_BASE_SIGSLOT_H__ 665 #endif // WEBRTC_BASE_SIGSLOT_H__
OLDNEW
« no previous file with comments | « no previous file | webrtc/base/sigslot_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698