diff --git a/webrtc/base/sigslot.h b/webrtc/base/sigslot.h index 4534ec9dae..45e0da216b 100644 --- a/webrtc/base/sigslot.h +++ b/webrtc/base/sigslot.h @@ -407,15 +407,12 @@ namespace sigslot { _signal_base& operator= (_signal_base const& that); public: - _signal_base(const _signal_base& s) : _signal_base_interface(&_signal_base::do_slot_disconnect, &_signal_base::do_slot_duplicate) { + _signal_base(const _signal_base& o) : _signal_base_interface(&_signal_base::do_slot_disconnect, &_signal_base::do_slot_duplicate) { lock_block lock(this); - connections_list::const_iterator it = m_connected_slots.begin(); - connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) + for (const auto& connection : o.m_connected_slots) { - it->getdest()->signal_connect(this); - m_connected_slots.push_back(*it); - ++it; + connection.getdest()->signal_connect(this); + m_connected_slots.push_back(connection); } } @@ -528,13 +525,21 @@ namespace sigslot { { } + has_slots(has_slots const& o) : has_slots_interface(&has_slots::do_signal_connect, &has_slots::do_signal_disconnect, &has_slots::do_disconnect_all) + { + lock_block lock(this); + for (auto* sender : o.m_senders) { + sender->slot_duplicate(&o, this); + m_senders.insert(sender); + } + } + ~has_slots() { this->disconnect_all(); } private: - has_slots(has_slots const&); has_slots& operator= (has_slots const&); static void do_signal_connect(has_slots_interface* p, _signal_base_interface* sender) diff --git a/webrtc/base/sigslot_unittest.cc b/webrtc/base/sigslot_unittest.cc index cb77336310..e860fe3373 100644 --- a/webrtc/base/sigslot_unittest.cc +++ b/webrtc/base/sigslot_unittest.cc @@ -36,6 +36,10 @@ class SigslotReceiver : public sigslot::has_slots { ~SigslotReceiver() { } + // Provide copy constructor so that tests can exercise the has_slots copy + // constructor. + SigslotReceiver(const SigslotReceiver&) = default; + void Connect(sigslot::signal0* signal) { if (!signal) return; Disconnect(); @@ -222,7 +226,7 @@ TEST_F(SigslotMTLockTest, LockSanity) { } // Destroy signal and slot in different orders. -TEST(DestructionOrder, SignalFirst) { +TEST(SigslotDestructionOrder, SignalFirst) { sigslot::signal0<>* signal = new sigslot::signal0<>; SigslotReceiver<>* receiver = new SigslotReceiver<>(); receiver->Connect(signal); @@ -232,7 +236,7 @@ TEST(DestructionOrder, SignalFirst) { delete receiver; } -TEST(DestructionOrder, SlotFirst) { +TEST(SigslotDestructionOrder, SlotFirst) { sigslot::signal0<>* signal = new sigslot::signal0<>; SigslotReceiver<>* receiver = new SigslotReceiver<>(); receiver->Connect(signal); @@ -243,3 +247,28 @@ TEST(DestructionOrder, SlotFirst) { (*signal)(); delete signal; } + +// Test that if a signal is copied, its slot connections are copied as well. +TEST(SigslotTest, CopyConnectedSignal) { + sigslot::signal<> signal; + SigslotReceiver<> receiver; + receiver.Connect(&signal); + + // Fire the copied signal, expecting the receiver to be notified. + sigslot::signal<> copied_signal(signal); + copied_signal(); + EXPECT_EQ(1, receiver.signal_count()); +} + +// Test that if a slot is copied, its signal connections are copied as well. +TEST(SigslotTest, CopyConnectedSlot) { + sigslot::signal<> signal; + SigslotReceiver<> receiver; + receiver.Connect(&signal); + + // Fire the signal after copying the receiver, expecting the copied receiver + // to be notified. + SigslotReceiver<> copied_receiver(receiver); + signal(); + EXPECT_EQ(1, copied_receiver.signal_count()); +}