From d88c22ef39bba3670c12b0396da00d79a8e959e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 12 Jul 2017 17:32:23 +0200 Subject: GLibSignal: change the methods signatures to return values (bzr r4245.2.1) --- UnityCore/GLibSignal-inl.h | 12 ++++- UnityCore/GLibSignal.cpp | 13 +++-- UnityCore/GLibSignal.h | 15 +++--- tests/test_glib_signals.cpp | 117 ++++++++++++++++++++++---------------------- 4 files changed, 84 insertions(+), 73 deletions(-) diff --git a/UnityCore/GLibSignal-inl.h b/UnityCore/GLibSignal-inl.h index e1cab8dd4..e7d786ea6 100644 --- a/UnityCore/GLibSignal-inl.h +++ b/UnityCore/GLibSignal-inl.h @@ -34,11 +34,11 @@ Signal::Signal(G object, std::string const& signal_name, } template -void Signal::Connect(G object, std::string const& signal_name, +bool Signal::Connect(G object, std::string const& signal_name, SignalCallback const& callback) { if (!callback || !G_IS_OBJECT(object) || signal_name.empty()) - return; + return false; Disconnect(); @@ -47,6 +47,8 @@ void Signal::Connect(G object, std::string const& signal_name, callback_ = callback; connection_id_ = g_signal_connect(object_, signal_name.c_str(), G_CALLBACK(Callback), this); g_object_add_weak_pointer(object_, reinterpret_cast(&object_)); + + return true; } template @@ -59,6 +61,12 @@ R Signal::Callback(G object, Ts... vs, Signal* self) return R(); } +template +SignalBase::Ptr SignalManager::Add(G object, std::string const& signal_name, typename Signal::SignalCallback const& callback) +{ + return Add(std::make_shared>(object, signal_name, callback)); +} + } } diff --git a/UnityCore/GLibSignal.cpp b/UnityCore/GLibSignal.cpp index 6173a09b4..f0949e84a 100644 --- a/UnityCore/GLibSignal.cpp +++ b/UnityCore/GLibSignal.cpp @@ -35,16 +35,20 @@ SignalBase::~SignalBase() Disconnect(); } -void SignalBase::Disconnect() +bool SignalBase::Disconnect() { + bool disconnected = false; + if (connection_id_ && G_IS_OBJECT(object_)) { g_signal_handler_disconnect(object_, connection_id_); g_object_remove_weak_pointer(object_, reinterpret_cast(&object_)); + disconnected = true; } object_ = nullptr; connection_id_ = 0; + return disconnected; } GObject* SignalBase::object() const @@ -75,15 +79,16 @@ SignalManager::~SignalManager() // was too messy to try and write a copy constructor/operator that would steal // from "other" and make the new one the owner. Not only did it create // opportunity for random bugs, it also made the API bad. -void SignalManager::Add(SignalBase* signal) +SignalBase::Ptr SignalManager::Add(SignalBase* signal) { - Add(SignalBase::Ptr(signal)); + return Add(SignalBase::Ptr(signal)); } -void SignalManager::Add(SignalBase::Ptr const& signal) +SignalBase::Ptr SignalManager::Add(SignalBase::Ptr const& signal) { connections_.push_back(signal); g_object_weak_ref(signal->object(), (GWeakNotify)&OnObjectDestroyed, this); + return signal; } void SignalManager::OnObjectDestroyed(SignalManager* self, GObject* old_obj) diff --git a/UnityCore/GLibSignal.h b/UnityCore/GLibSignal.h index 392ff3382..46914bd00 100644 --- a/UnityCore/GLibSignal.h +++ b/UnityCore/GLibSignal.h @@ -39,7 +39,7 @@ public: virtual ~SignalBase(); - void Disconnect(); + bool Disconnect(); GObject* object() const; std::string const& name() const; @@ -71,9 +71,9 @@ public: #endif inline Signal() {}; - inline Signal(G object, std::string const& signal_name, SignalCallback const& callback); + inline Signal(G object, std::string const& signal_name, SignalCallback const&); - inline void Connect(G Object, std::string const& signal_name, SignalCallback const& callback); + inline bool Connect(G Object, std::string const& signal_name, SignalCallback const&); private: static R Callback(G Object, Ts... vs, Signal* self); @@ -86,13 +86,10 @@ class SignalManager : boost::noncopyable public: SignalManager(); ~SignalManager(); - void Add(SignalBase* signal); - void Add(SignalBase::Ptr const& signal); + SignalBase::Ptr Add(SignalBase* signal); + SignalBase::Ptr Add(SignalBase::Ptr const& signal); template - void Add(G object, std::string const& signal_name, typename Signal::SignalCallback const& callback) - { - Add(std::make_shared>(object, signal_name, callback)); - } + SignalBase::Ptr Add(G object, std::string const& signal_name, typename Signal::SignalCallback const&); void Disconnect(void* object, std::string const& signal_name = ""); diff --git a/tests/test_glib_signals.cpp b/tests/test_glib_signals.cpp index 1c0b20bf7..82855d99f 100644 --- a/tests/test_glib_signals.cpp +++ b/tests/test_glib_signals.cpp @@ -136,8 +136,8 @@ TEST_F(TestGLibSignals, TestConstructions) TEST_F(TestGLibSignals, TestSignal0) { Signal signal; - signal.Connect(test_signals_, "signal0", - sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback))); g_signal_emit_by_name(test_signals_, "signal0"); @@ -148,8 +148,8 @@ TEST_F(TestGLibSignals, TestSignal0) TEST_F(TestGLibSignals, TestSignal1) { Signal signal; - signal.Connect(test_signals_, "signal1", - sigc::mem_fun(this, &TestGLibSignals::Signal1Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal1", + sigc::mem_fun(this, &TestGLibSignals::Signal1Callback))); g_signal_emit_by_name(test_signals_, "signal1", "test"); @@ -161,8 +161,8 @@ TEST_F(TestGLibSignals, TestSignal1) TEST_F(TestGLibSignals, TestSignal2) { Signal signal; - signal.Connect(test_signals_, "signal2", - sigc::mem_fun(this, &TestGLibSignals::Signal2Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal2", + sigc::mem_fun(this, &TestGLibSignals::Signal2Callback))); g_signal_emit_by_name(test_signals_, "signal2", "test", 100); @@ -175,8 +175,8 @@ TEST_F(TestGLibSignals, TestSignal2) TEST_F(TestGLibSignals, TestSignal3) { Signal signal; - signal.Connect(test_signals_, "signal3", - sigc::mem_fun(this, &TestGLibSignals::Signal3Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal3", + sigc::mem_fun(this, &TestGLibSignals::Signal3Callback))); g_signal_emit_by_name(test_signals_, "signal3", "test", 100, 200.0f); @@ -191,8 +191,8 @@ TEST_F(TestGLibSignals, TestSignal3) TEST_F(TestGLibSignals, TestSignal4) { Signal signal; - signal.Connect(test_signals_, "signal4", - sigc::mem_fun(this, &TestGLibSignals::Signal4Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal4", + sigc::mem_fun(this, &TestGLibSignals::Signal4Callback))); g_signal_emit_by_name(test_signals_, "signal4", "test", 100, 200.0f, 300.00); @@ -207,8 +207,8 @@ TEST_F(TestGLibSignals, TestSignal4) TEST_F(TestGLibSignals, TestSignal5) { Signal signal; - signal.Connect(test_signals_, "signal5", - sigc::mem_fun(this, &TestGLibSignals::Signal5Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal5", + sigc::mem_fun(this, &TestGLibSignals::Signal5Callback))); g_signal_emit_by_name(test_signals_, "signal5", "test", 100, 200.0f, 300.00, TRUE); @@ -226,8 +226,8 @@ TEST_F(TestGLibSignals, TestSignal5) TEST_F(TestGLibSignals, TestSignal6) { Signal signal; - signal.Connect(test_signals_, "signal6", - sigc::mem_fun(this, &TestGLibSignals::Signal6Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal6", + sigc::mem_fun(this, &TestGLibSignals::Signal6Callback))); gboolean ret = FALSE; g_signal_emit_by_name(test_signals_, "signal6", "test", 100, 200.0f, 300.00, @@ -246,9 +246,9 @@ TEST_F(TestGLibSignals, TestSignal6) TEST_F(TestGLibSignals, TestDisconnection) { Signal signal; - signal.Connect(test_signals_, "signal0", - sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); - signal.Disconnect(); + ASSERT_TRUE(signal.Connect(test_signals_, "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback))); + EXPECT_TRUE(signal.Disconnect()); g_signal_emit_by_name(test_signals_, "signal0"); @@ -259,8 +259,8 @@ TEST_F(TestGLibSignals, TestAutoDisconnection) { { Signal signal; - signal.Connect(test_signals_, "signal0", - sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback))); } g_signal_emit_by_name(test_signals_, "signal0"); @@ -271,8 +271,8 @@ TEST_F(TestGLibSignals, TestAutoDisconnection) TEST_F(TestGLibSignals, TestCleanDestruction) { Signal signal; - signal.Connect(test_signals_, "signal0", - sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback))); g_clear_object(&test_signals_); EXPECT_EQ(signal.object(), nullptr); } @@ -280,11 +280,11 @@ TEST_F(TestGLibSignals, TestCleanDestruction) TEST_F(TestGLibSignals, TestConnectReplacePreviousConnection) { Signal signal; - signal.Connect(test_signals_, "signal0", - sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); + ASSERT_TRUE(signal.Connect(test_signals_, "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback))); unsigned signal0_num_cb = 0; - signal.Connect(test_signals_, "signal0", [&] (TestSignals*) {++signal0_num_cb;}); + ASSERT_TRUE(signal.Connect(test_signals_, "signal0", [&] (TestSignals*) {++signal0_num_cb;})); g_signal_emit_by_name(test_signals_, "signal0"); @@ -302,27 +302,27 @@ TEST_F(TestGLibSignals, TestManagerAddition) { MockSignalManager manager; - manager.Add(new Signal(test_signals_, - "signal0", - sigc::mem_fun(this, &TestGLibSignals::Signal0Callback))); - manager.Add(new Signal(test_signals_, - "signal1", - sigc::mem_fun(this, &TestGLibSignals::Signal1Callback))); - manager.Add(new Signal(test_signals_, - "signal2", - sigc::mem_fun(this, &TestGLibSignals::Signal2Callback))); - manager.Add(new Signal(test_signals_, - "signal3", - sigc::mem_fun(this, &TestGLibSignals::Signal3Callback))); - manager.Add(new Signal(test_signals_, - "signal4", - sigc::mem_fun(this, &TestGLibSignals::Signal4Callback))); - manager.Add(new Signal(test_signals_, - "signal5", - sigc::mem_fun(this, &TestGLibSignals::Signal5Callback))); - manager.Add(new Signal(test_signals_, - "signal6", - sigc::mem_fun(this, &TestGLibSignals::Signal6Callback))); + EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, + "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)))); + EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, + "signal1", + sigc::mem_fun(this, &TestGLibSignals::Signal1Callback)))); + EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, + "signal2", + sigc::mem_fun(this, &TestGLibSignals::Signal2Callback)))); + EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, + "signal3", + sigc::mem_fun(this, &TestGLibSignals::Signal3Callback)))); + EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, + "signal4", + sigc::mem_fun(this, &TestGLibSignals::Signal4Callback)))); + EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, + "signal5", + sigc::mem_fun(this, &TestGLibSignals::Signal5Callback)))); + EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, + "signal6", + sigc::mem_fun(this, &TestGLibSignals::Signal6Callback)))); EXPECT_EQ(manager.GetConnections().size(), 7u); } @@ -331,19 +331,20 @@ TEST_F(TestGLibSignals, TestManagerAdditionTemplate) { MockSignalManager manager; - manager.Add(test_signals_, "signal0", - sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); - manager.Add(test_signals_, "signal1", - sigc::mem_fun(this, &TestGLibSignals::Signal1Callback)); - manager.Add(test_signals_, "signal2", - sigc::mem_fun(this, &TestGLibSignals::Signal2Callback)); - manager.Add(test_signals_, "signal3", - sigc::mem_fun(this, &TestGLibSignals::Signal3Callback)); - manager.Add(test_signals_, "signal4", - sigc::mem_fun(this, &TestGLibSignals::Signal4Callback)); - manager.Add(test_signals_, "signal5", - sigc::mem_fun(this, &TestGLibSignals::Signal5Callback)); - manager.Add(test_signals_, "signal6", sigc::mem_fun(this, &TestGLibSignals::Signal6Callback)); + EXPECT_NE(nullptr, (manager.Add(test_signals_, "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)))); + EXPECT_NE(nullptr, (manager.Add(test_signals_, "signal1", + sigc::mem_fun(this, &TestGLibSignals::Signal1Callback)))); + EXPECT_NE(nullptr, (manager.Add(test_signals_, "signal2", + sigc::mem_fun(this, &TestGLibSignals::Signal2Callback)))); + EXPECT_NE(nullptr, (manager.Add(test_signals_, "signal3", + sigc::mem_fun(this, &TestGLibSignals::Signal3Callback)))); + EXPECT_NE(nullptr, (manager.Add(test_signals_, "signal4", + sigc::mem_fun(this, &TestGLibSignals::Signal4Callback)))); + EXPECT_NE(nullptr, (manager.Add(test_signals_, "signal5", + sigc::mem_fun(this, &TestGLibSignals::Signal5Callback)))); + EXPECT_NE(nullptr, (manager.Add(test_signals_, "signal6", + sigc::mem_fun(this, &TestGLibSignals::Signal6Callback)))); EXPECT_EQ(manager.GetConnections().size(), 7u); } -- cgit v1.2.3 From e4c421bc64b1aad5bc971faca2c0e1ad84e64db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 12 Jul 2017 18:00:20 +0200 Subject: TestGLibSignals: verify the result of addition to manager in better way (bzr r4245.2.2) --- tests/test_glib_signals.cpp | 77 ++++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 21 deletions(-) diff --git a/tests/test_glib_signals.cpp b/tests/test_glib_signals.cpp index 82855d99f..df17f8366 100644 --- a/tests/test_glib_signals.cpp +++ b/tests/test_glib_signals.cpp @@ -302,27 +302,62 @@ TEST_F(TestGLibSignals, TestManagerAddition) { MockSignalManager manager; - EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, - "signal0", - sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)))); - EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, - "signal1", - sigc::mem_fun(this, &TestGLibSignals::Signal1Callback)))); - EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, - "signal2", - sigc::mem_fun(this, &TestGLibSignals::Signal2Callback)))); - EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, - "signal3", - sigc::mem_fun(this, &TestGLibSignals::Signal3Callback)))); - EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, - "signal4", - sigc::mem_fun(this, &TestGLibSignals::Signal4Callback)))); - EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, - "signal5", - sigc::mem_fun(this, &TestGLibSignals::Signal5Callback)))); - EXPECT_NE(nullptr, manager.Add(new Signal(test_signals_, - "signal6", - sigc::mem_fun(this, &TestGLibSignals::Signal6Callback)))); + auto signal0 = \ + std::make_shared>(test_signals_, + "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); + auto signal0_added = manager.Add(signal0); + ASSERT_NE(nullptr, signal0_added); + EXPECT_EQ(signal0, signal0_added); + + auto signal1 = \ + std::make_shared>(test_signals_, + "signal1", + sigc::mem_fun(this, &TestGLibSignals::Signal1Callback)); + auto signal1_added = manager.Add(signal1); + ASSERT_NE(nullptr, signal1_added); + EXPECT_EQ(signal1, signal1_added); + + auto signal2 = \ + std::make_shared>(test_signals_, + "signal2", + sigc::mem_fun(this, &TestGLibSignals::Signal2Callback)); + auto signal2_added = manager.Add(signal2); + ASSERT_NE(nullptr, signal2_added); + EXPECT_EQ(signal2, signal2_added); + + auto signal3 = \ + std::make_shared>(test_signals_, + "signal3", + sigc::mem_fun(this, &TestGLibSignals::Signal3Callback)); + auto signal3_added = manager.Add(signal3); + ASSERT_NE(nullptr, signal3_added); + EXPECT_EQ(signal3, signal3_added); + + auto signal4 = \ + std::make_shared>(test_signals_, + "signal4", + sigc::mem_fun(this, &TestGLibSignals::Signal4Callback)); + auto signal4_added = manager.Add(signal4); + ASSERT_NE(nullptr, signal4_added); + EXPECT_EQ(signal4, signal4_added); + + auto signal5 = \ + std::make_shared>(test_signals_, + "signal5", + sigc::mem_fun(this, &TestGLibSignals::Signal5Callback)); + auto signal5_added = manager.Add(signal5); + ASSERT_NE(nullptr, signal5_added); + EXPECT_EQ(signal5, signal5_added); + + auto signal6 = \ + std::make_shared>(test_signals_, + "signal6", + sigc::mem_fun(this, &TestGLibSignals::Signal6Callback)); + auto signal6_added = manager.Add(signal6); + ASSERT_NE(nullptr, signal6_added); + EXPECT_EQ(signal6, signal6_added); + EXPECT_EQ(manager.GetConnections().size(), 7u); } -- cgit v1.2.3 From af2d08087a6e2386aa6edd5e133f5b581779c013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 12 Jul 2017 18:13:47 +0200 Subject: GLibSignal: allow to block, unblock signals (bzr r4245.2.3) --- UnityCore/GLibSignal.cpp | 26 ++++++++++++++++++++++++++ UnityCore/GLibSignal.h | 3 +++ tests/test_glib_signals.cpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/UnityCore/GLibSignal.cpp b/UnityCore/GLibSignal.cpp index f0949e84a..b649e2543 100644 --- a/UnityCore/GLibSignal.cpp +++ b/UnityCore/GLibSignal.cpp @@ -51,6 +51,32 @@ bool SignalBase::Disconnect() return disconnected; } +bool SignalBase::Block() const +{ + bool blocked = false; + + if (connection_id_ && G_IS_OBJECT(object_)) + { + g_signal_handler_block(object_, connection_id_); + blocked = true; + } + + return blocked; +} + +bool SignalBase::Unblock() const +{ + bool unblocked = false; + + if (connection_id_ && G_IS_OBJECT(object_)) + { + g_signal_handler_unblock(object_, connection_id_); + unblocked = true; + } + + return unblocked; +} + GObject* SignalBase::object() const { return object_; diff --git a/UnityCore/GLibSignal.h b/UnityCore/GLibSignal.h index 46914bd00..894b7843c 100644 --- a/UnityCore/GLibSignal.h +++ b/UnityCore/GLibSignal.h @@ -41,6 +41,9 @@ public: bool Disconnect(); + bool Block() const; + bool Unblock() const; + GObject* object() const; std::string const& name() const; diff --git a/tests/test_glib_signals.cpp b/tests/test_glib_signals.cpp index df17f8366..a514f8d86 100644 --- a/tests/test_glib_signals.cpp +++ b/tests/test_glib_signals.cpp @@ -243,6 +243,40 @@ TEST_F(TestGLibSignals, TestSignal6) EXPECT_EQ(ret, TRUE); } +TEST_F(TestGLibSignals, TestBlock) +{ + Signal signal; + ASSERT_TRUE(signal.Connect(test_signals_, "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback))); + EXPECT_TRUE(signal.Block()); + + g_signal_emit_by_name(test_signals_, "signal0"); + EXPECT_FALSE(signal0_received_); + + signal0_received_ = false; + EXPECT_TRUE(signal.Unblock()); + + g_signal_emit_by_name(test_signals_, "signal0"); + EXPECT_TRUE(signal0_received_); +} + +TEST_F(TestGLibSignals, TestUnblock) +{ + Signal signal; + ASSERT_TRUE(signal.Connect(test_signals_, "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback))); + EXPECT_TRUE(signal.Unblock()); + + g_signal_emit_by_name(test_signals_, "signal0"); + EXPECT_TRUE(signal0_received_); + + signal0_received_ = false; + EXPECT_TRUE(signal.Block()); + + g_signal_emit_by_name(test_signals_, "signal0"); + EXPECT_FALSE(signal0_received_); +} + TEST_F(TestGLibSignals, TestDisconnection) { Signal signal; -- cgit v1.2.3 From e9b4d8bfe29f2715609d2b148591f36757988253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 12 Jul 2017 18:55:23 +0200 Subject: SignalManager: add internal ForeachMatchedSignal to do similar tasks once (bzr r4245.2.4) --- UnityCore/GLibSignal.cpp | 46 +++++++++++++++++++++++----------------------- UnityCore/GLibSignal.h | 3 ++- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/UnityCore/GLibSignal.cpp b/UnityCore/GLibSignal.cpp index b649e2543..447785a12 100644 --- a/UnityCore/GLibSignal.cpp +++ b/UnityCore/GLibSignal.cpp @@ -117,30 +117,11 @@ SignalBase::Ptr SignalManager::Add(SignalBase::Ptr const& signal) return signal; } -void SignalManager::OnObjectDestroyed(SignalManager* self, GObject* old_obj) -{ - for (auto it = self->connections_.begin(); it != self->connections_.end();) - { - auto const& signal = *it; - - // When an object has been destroyed, the signal member is nullified, - // so at this point we can be sure that removing signal with a null object, - // means removing invalid signals. - if (!signal->object()) - { - it = self->connections_.erase(it); - } - else - { - ++it; - } - } -} - // This uses void* to keep in line with the g_signal* functions // (it allows you to pass in a GObject without casting up). -void SignalManager::Disconnect(void* object, std::string const& signal_name) +bool SignalManager::ForeachMatchedSignal(void* object, std::string const& signal_name, std::function action, bool erase_after) { + bool action_performed = false; bool all_signals = signal_name.empty(); for (auto it = connections_.begin(); it != connections_.end();) @@ -149,14 +130,33 @@ void SignalManager::Disconnect(void* object, std::string const& signal_name) if (signal->object() == object && (all_signals || signal->name() == signal_name)) { - g_object_weak_unref(signal->object(), (GWeakNotify)&OnObjectDestroyed, this); - it = connections_.erase(it); + if (action) + { + action_performed = true; + action(signal); + } + + it = erase_after ? connections_.erase(it) : ++it; } else { ++it; } } + + return action_performed; +} + +void SignalManager::OnObjectDestroyed(SignalManager* self, GObject* old_obj) +{ + self->ForeachMatchedSignal(nullptr, "", nullptr, /*erase_after*/ true); +} + +bool SignalManager::Disconnect(void* object, std::string const& signal_name) +{ + return ForeachMatchedSignal(object, signal_name, [this] (SignalBase::Ptr const& signal) { + g_object_weak_unref(signal->object(), (GWeakNotify)&OnObjectDestroyed, this); + }, true); } } diff --git a/UnityCore/GLibSignal.h b/UnityCore/GLibSignal.h index 894b7843c..fe78853a8 100644 --- a/UnityCore/GLibSignal.h +++ b/UnityCore/GLibSignal.h @@ -94,9 +94,10 @@ public: template SignalBase::Ptr Add(G object, std::string const& signal_name, typename Signal::SignalCallback const&); - void Disconnect(void* object, std::string const& signal_name = ""); + bool Disconnect(void* object, std::string const& signal_name = ""); private: + bool ForeachMatchedSignal(void* object, std::string const& signal_name, std::function action, bool erase_after = false); static void OnObjectDestroyed(SignalManager* self, GObject* old_obj); protected: -- cgit v1.2.3 From d3260165470b21c4a15226108e72507b5b46ecdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 12 Jul 2017 18:56:01 +0200 Subject: GLibSignal: add Block/Unblock calls to SignalManager (bzr r4245.2.5) --- UnityCore/GLibSignal.cpp | 14 ++++++++++++++ UnityCore/GLibSignal.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/UnityCore/GLibSignal.cpp b/UnityCore/GLibSignal.cpp index 447785a12..0a155aede 100644 --- a/UnityCore/GLibSignal.cpp +++ b/UnityCore/GLibSignal.cpp @@ -152,6 +152,20 @@ void SignalManager::OnObjectDestroyed(SignalManager* self, GObject* old_obj) self->ForeachMatchedSignal(nullptr, "", nullptr, /*erase_after*/ true); } +bool SignalManager::Block(void* object, std::string const& signal_name) +{ + return ForeachMatchedSignal(object, signal_name, [this] (SignalBase::Ptr const& signal) { + signal->Block(); + }); +} + +bool SignalManager::Unblock(void* object, std::string const& signal_name) +{ + return ForeachMatchedSignal(object, signal_name, [this] (SignalBase::Ptr const& signal) { + signal->Unblock(); + }); +} + bool SignalManager::Disconnect(void* object, std::string const& signal_name) { return ForeachMatchedSignal(object, signal_name, [this] (SignalBase::Ptr const& signal) { diff --git a/UnityCore/GLibSignal.h b/UnityCore/GLibSignal.h index fe78853a8..d60ebc249 100644 --- a/UnityCore/GLibSignal.h +++ b/UnityCore/GLibSignal.h @@ -94,6 +94,9 @@ public: template SignalBase::Ptr Add(G object, std::string const& signal_name, typename Signal::SignalCallback const&); + bool Block(void* object, std::string const& signal_name = ""); + bool Unblock(void* object, std::string const& signal_name = ""); + bool Disconnect(void* object, std::string const& signal_name = ""); private: -- cgit v1.2.3 From 89fe82edacac0500dc84c675c12a44c96ac5b178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 12 Jul 2017 18:58:23 +0200 Subject: TestGLibSignals: add tests for signal blocks unblock (bzr r4245.2.6) --- tests/test_glib_signals.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/test_glib_signals.cpp b/tests/test_glib_signals.cpp index a514f8d86..5e3abd320 100644 --- a/tests/test_glib_signals.cpp +++ b/tests/test_glib_signals.cpp @@ -469,6 +469,23 @@ TEST_F(TestGLibSignals, TestManagerDisconnection) EXPECT_FALSE(signal0_received_); } +TEST_F(TestGLibSignals, TestManagerBlock) +{ + SignalManager manager; + + manager.Add(test_signals_, + "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); + manager.Block(test_signals_, "signal0"); + + g_signal_emit_by_name(test_signals_, "signal0"); + EXPECT_FALSE(signal0_received_); + + manager.Unblock(test_signals_, "signal0"); + g_signal_emit_by_name(test_signals_, "signal0"); + EXPECT_TRUE(signal0_received_); +} + TEST_F(TestGLibSignals, TestManagerObjectDisconnection) { SignalManager manager; -- cgit v1.2.3 From 5af1db7e331deb01e7dbb0a8f24eed302af5bb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 12 Jul 2017 19:10:36 +0200 Subject: TestGLibSignals: add tests for block unblocking for all objects (bzr r4245.2.7) --- tests/test_glib_signals.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/tests/test_glib_signals.cpp b/tests/test_glib_signals.cpp index 5e3abd320..100b1bca9 100644 --- a/tests/test_glib_signals.cpp +++ b/tests/test_glib_signals.cpp @@ -476,16 +476,41 @@ TEST_F(TestGLibSignals, TestManagerBlock) manager.Add(test_signals_, "signal0", sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); - manager.Block(test_signals_, "signal0"); + EXPECT_TRUE(manager.Block(test_signals_, "signal0")); g_signal_emit_by_name(test_signals_, "signal0"); EXPECT_FALSE(signal0_received_); - manager.Unblock(test_signals_, "signal0"); + EXPECT_TRUE(manager.Unblock(test_signals_, "signal0")); g_signal_emit_by_name(test_signals_, "signal0"); EXPECT_TRUE(signal0_received_); } +TEST_F(TestGLibSignals, TestManagerBlockAll) +{ + SignalManager manager; + + manager.Add(test_signals_, + "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); + manager.Add(test_signals_, + "signal1", + sigc::mem_fun(this, &TestGLibSignals::Signal1Callback)); + EXPECT_TRUE(manager.Block(test_signals_)); + + g_signal_emit_by_name(test_signals_, "signal0"); + g_signal_emit_by_name(test_signals_, "signal1", "blocked"); + EXPECT_FALSE(signal0_received_); + EXPECT_FALSE(signal1_received_); + + EXPECT_TRUE(manager.Unblock(test_signals_)); + + g_signal_emit_by_name(test_signals_, "signal0"); + EXPECT_TRUE(signal0_received_); + g_signal_emit_by_name(test_signals_, "signal1", "unblocked"); + EXPECT_TRUE(signal1_received_); +} + TEST_F(TestGLibSignals, TestManagerObjectDisconnection) { SignalManager manager; -- cgit v1.2.3 From 1bc51823be590e56e6a3efeff626506640e7b508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 12 Jul 2017 19:45:57 +0200 Subject: GLibSignal: allow to block/unblock all signals for a signal manager (bzr r4245.2.8) --- UnityCore/GLibSignal.cpp | 5 +++-- UnityCore/GLibSignal.h | 5 +++-- tests/test_glib_signals.cpp | 28 +++++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/UnityCore/GLibSignal.cpp b/UnityCore/GLibSignal.cpp index 0a155aede..d577c2f2e 100644 --- a/UnityCore/GLibSignal.cpp +++ b/UnityCore/GLibSignal.cpp @@ -122,13 +122,14 @@ SignalBase::Ptr SignalManager::Add(SignalBase::Ptr const& signal) bool SignalManager::ForeachMatchedSignal(void* object, std::string const& signal_name, std::function action, bool erase_after) { bool action_performed = false; - bool all_signals = signal_name.empty(); + bool all_objects = (object == reinterpret_cast(std::numeric_limits::max())); + bool all_signals = all_objects || signal_name.empty(); for (auto it = connections_.begin(); it != connections_.end();) { auto const& signal = *it; - if (signal->object() == object && (all_signals || signal->name() == signal_name)) + if ((all_objects || signal->object() == object) && (all_signals || signal->name() == signal_name)) { if (action) { diff --git a/UnityCore/GLibSignal.h b/UnityCore/GLibSignal.h index d60ebc249..6dc536111 100644 --- a/UnityCore/GLibSignal.h +++ b/UnityCore/GLibSignal.h @@ -21,6 +21,7 @@ #ifndef UNITY_GLIB_SIGNAL_H #define UNITY_GLIB_SIGNAL_H +#include #include #include #include @@ -94,8 +95,8 @@ public: template SignalBase::Ptr Add(G object, std::string const& signal_name, typename Signal::SignalCallback const&); - bool Block(void* object, std::string const& signal_name = ""); - bool Unblock(void* object, std::string const& signal_name = ""); + bool Block(void* object = (void*) std::numeric_limits::max(), std::string const& signal_name = ""); + bool Unblock(void* object = (void*) std::numeric_limits::max(), std::string const& signal_name = ""); bool Disconnect(void* object, std::string const& signal_name = ""); diff --git a/tests/test_glib_signals.cpp b/tests/test_glib_signals.cpp index 100b1bca9..724e18fec 100644 --- a/tests/test_glib_signals.cpp +++ b/tests/test_glib_signals.cpp @@ -34,7 +34,8 @@ public: virtual ~TestGLibSignals() { - g_object_unref(test_signals_); + if (test_signals_) + g_object_unref(test_signals_); } void Signal0Callback(TestSignals* signals) @@ -511,6 +512,31 @@ TEST_F(TestGLibSignals, TestManagerBlockAll) EXPECT_TRUE(signal1_received_); } +TEST_F(TestGLibSignals, TestManagerBlockAllObjects) +{ + SignalManager manager; + + manager.Add(test_signals_, + "signal0", + sigc::mem_fun(this, &TestGLibSignals::Signal0Callback)); + manager.Add(test_signals_, + "signal1", + sigc::mem_fun(this, &TestGLibSignals::Signal1Callback)); + EXPECT_TRUE(manager.Block()); + + g_signal_emit_by_name(test_signals_, "signal0"); + g_signal_emit_by_name(test_signals_, "signal1", "blocked"); + EXPECT_FALSE(signal0_received_); + EXPECT_FALSE(signal1_received_); + + EXPECT_TRUE(manager.Unblock()); + + g_signal_emit_by_name(test_signals_, "signal0"); + EXPECT_TRUE(signal0_received_); + g_signal_emit_by_name(test_signals_, "signal1", "unblocked"); + EXPECT_TRUE(signal1_received_); +} + TEST_F(TestGLibSignals, TestManagerObjectDisconnection) { SignalManager manager; -- cgit v1.2.3