DSSignalBroker: added registerSignal and add DSObject argument for signal methods 50/242950/1
authorJunseok, Kim <juns.kim@samsung.com>
Fri, 28 Aug 2020 11:06:06 +0000 (20:06 +0900)
committerSung-Jin Park <sj76.park@samsung.com>
Wed, 2 Sep 2020 05:18:13 +0000 (14:18 +0900)
Change-Id: I2b97b60b195740b134a2cdd1d7fbcaa082679c9b
Signed-off-by: Junseok, Kim <juns.kim@samsung.com>
src/DSSignal/DSSignalBroker.cpp
src/DSSignal/DSSignalBroker.h
tests/DSSignalBroker-test.cpp

index f8e4cfa..58c53c2 100644 (file)
@@ -41,7 +41,7 @@ DSSignalBroker::~DSSignalBroker()
                {
                        for (auto hashpairs : __signalBroker->__signalHash)
                        {
-                               delete hashpairs.second;
+                               delete hashpairs.second.signal;
                        }
                }
        }
index 27a55dd..5674ade 100644 (file)
@@ -37,19 +37,38 @@ public:
        static DSSignalBroker *getInstance();
        static void releaseInstance();
 
-       // TODO: needs arguments using signal (now only supports void*)
+       template <typename... Args>
+       bool registerSignal(std::string signalStr, DSObject *obj);
+       template <typename... Args>
+       bool emitSignal(std::string signalStr, DSObject *obj, Args...);
        template <typename... Args>
        bool registerCallback(std::string signalStr, DSObject *slot, std::function<void(Args...)> func);
        template <typename... Args>
        bool deregisterCallback(std::string signalStr, DSObject *slot, std::function<void(Args...)> func);
-       template <typename... Args>
-       bool emitSignal(std::string signalStr, Args...);
 
 private:
        static std::mutex __mutex;
        static DSSignalBroker *__signalBroker;
 
-       std::unordered_map<std::string, DSSignal<void *> *> __signalHash;
+       struct stRegisteredSignal
+       {
+               std::string          signalName;
+               std::string                      className;
+               DSObject                        *obj;
+               DSSignal<void *>        *signal;
+
+       public:
+               stRegisteredSignal(std::string sn, DSObject *inpObj, DSSignal<void *> *inpSignal)
+               {
+                       signalName = sn;
+                       className = inpObj->getName();
+                       obj = inpObj;
+                       signal = inpSignal;
+               }
+
+       };
+
+       std::unordered_multimap<std::string, stRegisteredSignal> __signalHash;
 
        DSSignalBroker() = delete;
        ~DSSignalBroker();
@@ -57,56 +76,121 @@ private:
 };
 
 template <typename... Args>
-bool DSSignalBroker::registerCallback(std::string signalStr, DSObject *slot, std::function<void(Args...)> func)
+bool DSSignalBroker::registerSignal(std::string signalStr, DSObject *obj)
 {
        if (!__signalBroker) return false;
 
-       if (__signalBroker->__signalHash.find(signalStr) == __signalBroker->__signalHash.end())
+       if (__signalBroker->__signalHash.find(signalStr) != __signalBroker->__signalHash.end())
                {
-                       DSLOG_INF("DSSignalBroker","registerCallback:: cannot find signal, add new one %s", signalStr.c_str());
-
-                       __signalBroker->__signalHash[signalStr] = reinterpret_cast<DSSignal<void *> *> (new DSSignal<Args...>());
+                       auto range = __signalBroker->__signalHash.equal_range(signalStr);
+                       for (auto iter = range.first;
+                               iter != range.second;
+                               iter++)
+                       {
+                               if (iter->second.obj == obj)
+                               {
+                                       DSLOG_INF("DSSignalBroker","emitSignal:: already registered signal: %s", signalStr.c_str());
+                                       return false;
+                               }
+                               else
+                               {
+                                       DSLOG_DBG("DSSignalBroker", "searching same item: %s, obj(%p):%s", iter->second.signalName.c_str(), iter->second.obj, iter->second.className.c_str());
+                               }
+
+                       }
                }
+       DSSignal<void *> *signal = reinterpret_cast<DSSignal<void *> *> (new DSSignal<Args...>());
+       __signalBroker->__signalHash.insert(std::make_pair(signalStr, stRegisteredSignal(signalStr, obj, signal)));
 
-       DSSignal<Args...> *signal = reinterpret_cast<DSSignal<Args...> *>(__signalBroker->__signalHash[signalStr]);
-       if (signal)
-               signal->connect(slot, func);
+       DSLOG_DBG("DSSignalBroker","registerSignal:: registered new signal (name:%s, class(%p):%s, signal:%p)",
+               signalStr.c_str(), obj, obj->getName().c_str(), signal);
 
        return true;
 }
 
 template <typename... Args>
-bool DSSignalBroker::deregisterCallback(std::string signalStr, DSObject *slot, std::function<void(Args...)> func)
+bool DSSignalBroker::emitSignal(std::string signalStr, DSObject *obj, Args... args)
 {
        if (!__signalBroker) return false;
 
-       if (__signalBroker->__signalHash.find(signalStr) == __signalBroker->__signalHash.end())
+       if (__signalBroker->__signalHash.find(signalStr) != __signalBroker->__signalHash.end())
+       {
+               auto range = __signalBroker->__signalHash.equal_range(signalStr);
+               for (auto iter = range.first;
+                       iter != range.second;
+                       iter++)
+               {
+                       if (iter->second.obj == obj)// || iter->second.className == obj->getName())
+                       {
+                               DSSignal<Args...> *signal = reinterpret_cast<DSSignal<Args...> *>(iter->second.signal);
+                               if (signal)
+                               {
+                                       signal->emit(args...);
+                                       DSLOG_DBG("DSSignalBroker","emitSignal:: signal emit (name:%s, class(%p):%s, signal:%p)",
+                                               iter->second.signalName.c_str(), iter->second.obj, iter->second.obj->getName().c_str(), iter->second.signal);
+                               }
+                               else
+                                       return false;
+
+                               return true;
+                       }
+               }
+       }
+       else
+       {
+               DSLOG_INF("DSSignalBroker","emitSignal:: cannot find registered signal: %s", signalStr.c_str());
                return false;
+       }
 
-       // TODO: have to impl disconnect method in DSSignal
-       //DSSignal<Args...> *signal = reinterpret_cast<DSSignal<Args...> *>(__signalBroker->__signalHash[signalStr]);
-       //if (signal)
-               //signal->disconnect(slot, func);
-
-       return true;
+       return false;
 }
 
 template <typename... Args>
-bool DSSignalBroker::emitSignal(std::string signalStr, Args... args)
+bool DSSignalBroker::registerCallback(std::string signalStr, DSObject *slot, std::function<void(Args...)> func)
 {
        if (!__signalBroker) return false;
 
-       if (__signalBroker->__signalHash.find(signalStr) == __signalBroker->__signalHash.end())
+       if (__signalBroker->__signalHash.find(signalStr) != __signalBroker->__signalHash.end())
+       {
+               auto range = __signalBroker->__signalHash.equal_range(signalStr);
+               for (auto iter = range.first;
+                       iter != range.second;
+                       iter++)
                {
-                       DSLOG_INF("DSSignalBroker","emitSignal:: cannot find signal, add new one %s", signalStr.c_str());
-
-                       __signalBroker->__signalHash[signalStr] = reinterpret_cast<DSSignal<void *> *> (new DSSignal<Args...>());
+                       DSSignal<Args...> *signal = reinterpret_cast<DSSignal<Args...> *>(iter->second.signal);
+                       if (signal)
+                               signal->connect(slot, func);
                }
+       }
+       else
+       {
+               DSLOG_INF("DSSignalBroker","registerCallback:: cannot find signal: %s", signalStr.c_str());
+               return false;
+       }
+
+       return true;
+}
 
-       DSSignal<Args...> *signal = reinterpret_cast<DSSignal<Args...> *>(__signalBroker->__signalHash[signalStr]);
-       if (signal)
-               signal->emit(args...);
+template <typename... Args>
+bool DSSignalBroker::deregisterCallback(std::string signalStr, DSObject *slot, std::function<void(Args...)> func)
+{
+       // TODO: have to impl disconnect method in DSSignal
+       /*
+       if (!__signalBroker) return false;
 
+       if (__signalBroker->__signalHash.find(signalStr) != __signalBroker->__signalHash.end())
+       {
+               auto range = __signalBroker->__signalHash.equal_range(signalStr);
+               for (auto iter = range.first;
+                       iter != range.second;
+                       iter++)
+                       {
+                               DSSignal<Args...> *signal = reinterpret_cast<DSSignal<Args...> *>(iter->second.signal);
+                               if (signal)
+                                       signal->disconnect(slot, func);
+                       }
+               }
+       */
        return true;
 }
 
index a4532b9..4484885 100644 (file)
 
 using namespace display_server;
 
-class DSSignalBrokerTest : public ::testing::Test
+struct stItem
 {
-public:
-       void SetUp(void) override
-       {}
-       void TearDown(void) override
-       {}
+       std::string str1;
+       std::string str2;
 };
 
-class MockSignalBrokerSender : public DSObject
+class MockSender : public DSObject
 {
 public:
-       MockSignalBrokerSender() {}
-       ~MockSignalBrokerSender() {}
+       MockSender() {}
+       ~MockSender() {}
 
-       bool sendSignal(std::string signalString)
+       bool registerSignal(std::string signalString)
        {
                DSSignalBroker *sigbro = DSSignalBroker::getInstance();
                bool res = false;
@@ -52,7 +49,57 @@ public:
                if (sigbro == nullptr)
                        return false;
 
-               res = sigbro->emitSignal(signalString, true);
+               res = sigbro->registerSignal(signalString, this);
+
+               if (sigbro)
+                       sigbro->releaseInstance();
+
+               return res;
+       }
+
+       bool sendSignal1(std::string signalString, int data)
+       {
+               DSSignalBroker *sigbro = DSSignalBroker::getInstance();
+               bool res = false;
+
+               if (sigbro == nullptr)
+                       return false;
+
+               res = sigbro->emitSignal(signalString, this, data);
+
+               if (sigbro)
+                       sigbro->releaseInstance();
+
+               return res;
+       }
+
+       bool sendSignal2(std::string signalString, double data)
+       {
+               DSSignalBroker *sigbro = DSSignalBroker::getInstance();
+               bool res = false;
+
+               if (sigbro == nullptr)
+                       return false;
+
+               res = sigbro->emitSignal(signalString, this, data);
+
+               if (sigbro)
+                       sigbro->releaseInstance();
+
+               return res;
+       }
+
+       bool sendSignal3(std::string signalString, std::string data1, std::string data2, std::string data3)
+       {
+               DSSignalBroker *sigbro = DSSignalBroker::getInstance();
+               bool res = false;
+
+               if (sigbro == nullptr)
+                       return false;
+
+               struct stItem testItem = {data2, data3};
+
+               res = sigbro->emitSignal(signalString, this, data1, testItem);
 
                if (sigbro)
                        sigbro->releaseInstance();
@@ -61,29 +108,46 @@ public:
        }
 };
 
-class MockSignalBrokerReceiver : public DSObject
+class MockReceiver : public DSObject
 {
 public:
-       MockSignalBrokerReceiver() = delete;
-       MockSignalBrokerReceiver(std::string targetSignal)
+       MockReceiver() :
+               result1(0),
+               result2(0.0),
+               result3("")
        {
-               __targetSignal = targetSignal;
        }
-       ~MockSignalBrokerReceiver() {}
+       ~MockReceiver() {}
 
 public:
-       std::string __targetSignal;
-       bool __result;
+       int result1;
+       double result2;
+       std::string result3;
 
 public:
-       bool registerCallback()
+       bool registerCallback1(std::string targetSignal)
+       {
+               bool res = false;
+               DSSignalBroker *sigbro = DSSignalBroker::getInstance();
+               if (sigbro == nullptr) return false;
+
+               std::function<void(int)> func = std::bind(&MockReceiver::UserCallback1, this, std::placeholders::_1);
+               res = sigbro->registerCallback(targetSignal, this, func);
+
+               if (sigbro)
+                       sigbro->releaseInstance();
+
+               return res;
+       }
+
+       bool registerCallback2(std::string targetSignal)
        {
                bool res = false;
                DSSignalBroker *sigbro = DSSignalBroker::getInstance();
                if (sigbro == nullptr) return false;
 
-               std::function<void(bool)> func = std::bind(&MockSignalBrokerReceiver::callbackTestSignalBroker, this, std::placeholders::_1);
-               res = sigbro->registerCallback(__targetSignal, this, func);
+               std::function<void(double)> func = std::bind(&MockReceiver::UserCallback2, this, std::placeholders::_1);
+               res = sigbro->registerCallback(targetSignal, this, func);
 
                if (sigbro)
                        sigbro->releaseInstance();
@@ -91,18 +155,52 @@ public:
                return res;
        }
 
-       void callbackTestSignalBroker(bool arg)
+       bool registerCallback3(std::string targetSignal)
+       {
+               bool res = false;
+               DSSignalBroker *sigbro = DSSignalBroker::getInstance();
+               if (sigbro == nullptr) return false;
+
+               std::function<void(std::string, struct stItem)> func = std::bind(&MockReceiver::UserCallback3, this, std::placeholders::_1, std::placeholders::_2);
+               res = sigbro->registerCallback(targetSignal, this, func);
+
+               if (sigbro)
+                       sigbro->releaseInstance();
+
+               return res;
+       }
+
+       void UserCallback1(int arg)
        {
                DSLOG_INF("DSTEST", "%s is invoked!, arg: %d", __func__, arg);
-               __result = arg;
+               result1 = arg;
        }
 
-       bool getResult()
+       void UserCallback2(double arg)
        {
-               return __result;
+               DSLOG_INF("DSTEST", "%s is invoked!, arg: %d", __func__, arg);
+               result2 = arg;
+       }
+
+       void UserCallback3(std::string arg1, struct stItem arg2)
+       {
+               DSLOG_INF("DSTEST", "%s is invoked!, arg1: %s, arg2{%s, %s}", __func__, arg1.c_str(), arg2.str1.c_str(), arg2.str2.c_str());
+               result3 = arg1;
        }
 };
 
+class DSSignalBrokerTest : public ::testing::Test
+{
+public:
+       void SetUp(void) override
+       {}
+       void TearDown(void) override
+       {}
+};
+
+std::shared_ptr<MockReceiver> __receiver;
+std::shared_ptr<MockSender> __sender;
+
 TEST_F(DSSignalBrokerTest, getInstance)
 {
        DSSignalBroker *sigbro = DSSignalBroker::getInstance();
@@ -112,39 +210,78 @@ TEST_F(DSSignalBrokerTest, getInstance)
                sigbro->releaseInstance();
 }
 
+TEST_F(DSSignalBrokerTest, registerSignal)
+{
+       __sender = std::make_shared<MockSender>();
+       ASSERT_TRUE(__sender != nullptr);
+
+       __sender->registerSignal("SampleSignal1");
+}
+
 TEST_F(DSSignalBrokerTest, registerCallback)
 {
-       auto receiver = std::make_shared<MockSignalBrokerReceiver>("TestSignalBroker");
-       receiver->registerCallback();
+       __receiver = std::make_shared<MockReceiver>();
+       ASSERT_TRUE(__receiver != nullptr);
+
+       __receiver->registerCallback1("SampleSignal1");
 }
 
 TEST_F(DSSignalBrokerTest, emitSignal)
 {
-       auto receiver = std::make_shared<MockSignalBrokerReceiver>("TestSignalBroker");
-       auto sender = std::make_shared<MockSignalBrokerSender>();
-       ASSERT_TRUE(receiver != nullptr);
-       ASSERT_TRUE(sender != nullptr);
-
-       receiver->registerCallback();
-       EXPECT_TRUE(sender->sendSignal("TestSignalBroker"));
-       EXPECT_TRUE(receiver->getResult());
+       ASSERT_TRUE(__sender != nullptr);
+       ASSERT_TRUE(__receiver != nullptr);
+
+       EXPECT_TRUE(__sender->sendSignal1("SampleSignal1", 1));
+       EXPECT_TRUE(__receiver->result1 == 1);
 }
 
-TEST_F(DSSignalBrokerTest, emitSignal2)
+TEST_F(DSSignalBrokerTest, registerAndEmit1)
 {
-       auto receiver1 = std::make_shared<MockSignalBrokerReceiver>("TestSignalBroker");
-       auto receiver2 = std::make_shared<MockSignalBrokerReceiver>("TestSignalBroker2");
-       auto sender = std::make_shared<MockSignalBrokerSender>();
-       ASSERT_TRUE(receiver1 != nullptr);
-       ASSERT_TRUE(receiver2 != nullptr);
-       ASSERT_TRUE(sender != nullptr);
-
-       receiver1->registerCallback();
-       receiver2->registerCallback();
-       EXPECT_TRUE(sender->sendSignal("TestSignalBroker"));
-       EXPECT_TRUE(receiver1->getResult());
-       EXPECT_TRUE(receiver2->getResult() != true);
-
-       EXPECT_TRUE(sender->sendSignal("TestSignalBroker2"));
-       EXPECT_TRUE(receiver2->getResult());
+       auto sender1 = std::make_shared<MockSender>();
+       auto sender2 = std::make_shared<MockSender>();
+
+       auto receiver1 = std::make_shared<MockReceiver>();
+       auto receiver2 = std::make_shared<MockReceiver>();
+
+       ASSERT_TRUE(sender1 != nullptr &&
+               sender2 != nullptr &&
+               receiver1 != nullptr &&
+               receiver2 != nullptr);
+
+       // 1. register Signal
+       EXPECT_TRUE(sender1->registerSignal("SampleSignal1"));
+       EXPECT_TRUE(sender2->registerSignal("SampleSignal2"));
+
+       // 2. register Callback
+       EXPECT_TRUE(receiver1->registerCallback1("SampleSignal1"));
+       EXPECT_TRUE(receiver2->registerCallback2("SampleSignal2"));
+
+       // 3. emit Signal
+       EXPECT_TRUE(sender1->sendSignal1("SampleSignal1", 11));
+       EXPECT_TRUE(sender2->sendSignal2("SampleSignal2", 10.10));
+
+       // 4. see Changes
+       EXPECT_TRUE(receiver1->result1 == 11);
+       EXPECT_TRUE(receiver2->result2 == 10.10);
 }
+
+TEST_F(DSSignalBrokerTest, emitMultiItems)
+{
+       auto sender = std::make_shared<MockSender>();
+       auto receiver = std::make_shared<MockReceiver>();
+
+       ASSERT_TRUE(sender != nullptr &&
+               receiver != nullptr);
+
+       // 1. register Signal
+       EXPECT_TRUE(sender->registerSignal("SampleSignal3"));
+
+       // 2. register Callback
+       EXPECT_TRUE(receiver->registerCallback3("SampleSignal3"));
+
+       // 3. emit Signal
+       EXPECT_TRUE(sender->sendSignal3("SampleSignal3", "Test", "Hello", "signal"));
+
+       // 4. see Changes
+       EXPECT_TRUE(receiver->result3 == "Test");
+}
\ No newline at end of file