DSSignal: use std::function as the paremeter of the connect method. 41/241541/1
authorSooChan Lim <sc1.lim@samsung.com>
Mon, 22 Jun 2020 01:47:12 +0000 (10:47 +0900)
committerSung-Jin Park <sj76.park@samsung.com>
Thu, 20 Aug 2020 09:44:58 +0000 (18:44 +0900)
use std::function instead of the raw function pointer.

Change-Id: I02e368c09e6f673fc8881842694296d171ff9369

src/DSObject/IDSObjectObserver.h
src/DSSignal/DSSignal.h
tests/DSSignal-test.cpp [new file with mode: 0644]
tests/meson.build

index 494633a..6f36717 100644 (file)
@@ -10,7 +10,7 @@ class IDSObjectObserver
 {
 public:
        virtual ~IDSObjectObserver() = default;
-       virtual void destroyed(DSObject *obj) = 0;
+       virtual void destroyed(DSObject *slot) = 0;
 };
 
 }
index fd40342..eedf0a7 100644 (file)
@@ -2,10 +2,11 @@
 #define __DS_SIGNAL_H_
 
 #include "DSObject.h"
-#include <list>
-#include <memory>
 #include <iostream>
 #include <string>
+#include <list>
+#include <memory>
+#include <functional>
 
 namespace display_server
 {
@@ -13,10 +14,10 @@ namespace display_server
 class DSSlotsObserver : public IDSObjectObserver
 {
 public:
-       DSSlotsObserver() {}
-       ~DSSlotsObserver() {}
+       DSSlotsObserver() = default;
+       ~DSSlotsObserver() = default;
 
-       virtual void destroyed(DSObject *obj);
+       virtual void destroyed(DSObject *slot);
        virtual void addSlot(DSObject *slot);
 
 protected:
@@ -28,14 +29,14 @@ class DSSlotConnection : public DSSlotsObserver
 {
 public:
        DSSlotConnection()
-       {}
-
-       DSSlotConnection(DSObject *slot, void (*func)(Args...))
-               : __callback(func)
+               : __func(nullptr)
+       {};
+       DSSlotConnection(DSObject *slot, std::function<void(Args...)> func)
+               : __func(std::move(func))
        {
                //TODO: make callback as callback iface
                //std::unique_ptr<DSCallbackIface> ptr(new DSCallbackIface(func));
-               //__callback = std::move(ptr);
+               //__func = std::move(ptr);
                addSlot(slot);
        }
 
@@ -49,8 +50,9 @@ public:
 
        void addSlot(DSObject *slot) override
        {
-               _slotList.push_back(slot);
                slot->attachDestroyObserver(this);
+
+               _slotList.push_back(slot);
        }
 
        void destroyed(DSObject *slot) override
@@ -64,13 +66,13 @@ public:
        void invoke(Args... args)
        {
                if (!_slotList.empty())
-                       __callback(args...);
+                       std::invoke(__func, args...);
        }
 
 private:
        //TODO: make callback as callback iface
-       //std::unique_ptr<DSCallbackIface> __callback;
-       void (*__callback)(Args...);
+       //std::unique_ptr<DSCallbackIface> __func;
+       std::function<void(Args...)> __func;
        template <typename... _Args>
        friend class DSSignal;
 };
@@ -79,10 +81,8 @@ template <typename... Args>
 class DSSignal
 {
 public:
-       DSSignal()
-       {}
-       virtual ~DSSignal()
-       {}
+       DSSignal() = default;
+       virtual ~DSSignal() = default;
 
        // functor
        DSSignal<Args...> &operator()(void)
@@ -90,7 +90,7 @@ public:
                return *this;
        }
 
-       void connect(DSObject *slot, void (*func)(Args...))
+       void connect(DSObject *slot, std::function<void(Args...)> func)
        {
                if ((!slot) || (!func))
                        return;
@@ -108,10 +108,10 @@ public:
        }
 
 private:
-       DSSlotConnection<Args...> *__findConnection(void (*func)(Args...))
+       DSSlotConnection<Args...> *__findConnection(std::function<void(Args...)> func)
        {
                for (auto &&connection : __connectionList) {
-                       if (connection->__callback == func)
+                       if (&connection->__func == &func)
                                return connection.get();
                }
 
diff --git a/tests/DSSignal-test.cpp b/tests/DSSignal-test.cpp
new file mode 100644 (file)
index 0000000..7348b3f
--- /dev/null
@@ -0,0 +1,74 @@
+#include "libds-tests.h"
+#include "DSSignal.h"
+#include "DSDebugLog.h"
+
+using namespace display_server;
+
+class DSSignalTest : public ::testing::Test
+{
+public:
+       void SetUp(void) override
+       {}
+       void TearDown(void) override
+       {}
+};
+
+class SenderMock : public DSObject
+{
+public:
+       SenderMock()
+               : signalA(std::make_unique<DSSignal<int>>()),
+                 signalB(std::make_unique<DSSignal<double>>())
+       {}
+       ~SenderMock() = default;
+
+       void emitSignalA(int value) {
+               signalA->emit(value);
+       }
+
+       void emitSignalB(double value) {
+               signalB->emit(value);
+       }
+
+       std::unique_ptr<DSSignal<int>> signalA;
+       std::unique_ptr<DSSignal<double>> signalB;
+};
+
+class ReceiverMock : public DSObject
+{
+public:
+       ReceiverMock(std::shared_ptr<SenderMock> sender)
+               : __sender(sender)
+       {
+               sender->signalA->connect(this, std::bind(&ReceiverMock::slotA, this, std::placeholders::_1));
+               sender->signalB->connect(this, std::bind(&ReceiverMock::slotB, this, std::placeholders::_1));
+       }
+       ~ReceiverMock() = default;
+
+       void slotA(int value) {
+               DSLOG_INF("DSTEST", "%s is invoked! : value, %d\n", __func__, value);
+       }
+
+       void slotB(double value) {
+               DSLOG_INF("DSTEST", "%s is invoked! : value, %lf\n", __func__, value);
+       }
+
+private:
+       std::shared_ptr<SenderMock> __sender;
+};
+
+TEST_F(DSSignalTest, CreateSignal)
+{
+       DSSignal<int> *signal = new DSSignal<int>();
+       delete signal;
+       ASSERT_TRUE(true);
+}
+
+TEST_F(DSSignalTest, ConnectSignal)
+{
+       auto sender1 = std::make_shared<SenderMock>();
+       auto receiver = std::make_unique<ReceiverMock>(sender1);
+
+       sender1->emitSignalA(30);
+       sender1->emitSignalB(3.0);
+}
index 03e11ea..e181ae3 100644 (file)
@@ -14,6 +14,7 @@ libds_tests_srcs = [
        'DSDisplayArea-test.cpp',
        'DSDebugLog-test.cpp',
        'DSDisplayDeviceTDMImpl-test.cpp',
+       'DSSignal-test.cpp',
        ]
 
 gmock_dep = dependency('gmock', method : 'pkg-config')