signals: allow to copy connections 28/111128/3
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Thu, 19 Jan 2017 11:35:04 +0000 (12:35 +0100)
committerLukasz Stanislawski <l.stanislaws@samsung.com>
Thu, 19 Jan 2017 15:25:16 +0000 (07:25 -0800)
Make signal connection shared_ptr to connection data. When there is no more
references to connection data, the connection will be automatically
disconnected from signal.

Additionally make signal to keep weak_ref to connection data.
In case when signal is destructed, all connection will be auto
disconnected.

Change-Id: Ic1788057df7100d9746f4781a8b95370d9f7f3e0

clock-tests/.cproject
clock-tests/src/SignalTest.cpp
clock-tests/unittest.xml
clock/inc/Utils/Signal.h

index 979bf05b69eccf79661e1b349f70ae3e459c420b..cbc4c97b6907778de37dd71fa86966067225bb6e 100644 (file)
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/MainController.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/RingController.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Alarm.o&quot;"/>
-                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmBinaryStorage.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmProvider.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Ring.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/RingEvent.o&quot;"/>
index d29397870e3bdcf4941900f53750ee305ec6c169..c4639353d87113e0a8d161a8df7c55070f77f3c4 100644 (file)
@@ -100,6 +100,12 @@ TEST(SignalTestSuite, listener_in_vector)
 
        EXPECT_EQ(s1.times_, 1);
        EXPECT_EQ(s2.times_, 1);
+
+       listeners.clear();
+       event(1);
+
+       EXPECT_EQ(s1.times_, 1);
+       EXPECT_EQ(s2.times_, 1);
 }
 
 TEST(SignalTestSuite, listener_in_vector2)
index 80e7b7a3a1986e44c7f327fcb3b24e2ccd654b9e..06c95de36901aa7e4e9b211464ad0b3dd0e3f49e 100644 (file)
@@ -6,7 +6,6 @@
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/MainController.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/RingController.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Alarm.o</targetObjectFile>
-<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmBinaryStorage.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmProvider.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Ring.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/RingEvent.o</targetObjectFile>
index f93f2f3a204ae9fa0b297405a87946f5e5d9835d..86eba597c49762d492d1b5dabbc41fe5d7bb9be5 100644 (file)
@@ -62,30 +62,31 @@ namespace utils {
        template <typename... T_arg>
        struct Slot;
 
-       /**
-        * @brief Class representing signal connection
-        */
-       template <typename... T_arg>
-       class SignalConnection;
-
        /**
         * @brief Base class for all signal connections.
         */
        class SignalBaseConnection;
 
-       typedef std::unique_ptr<SignalBaseConnection> Connection;
+       typedef std::shared_ptr<SignalBaseConnection> Connection;
 
        /**
-        * @brief Call context
+        * @brief Slot definition
         */
        template <typename... T_arg>
        struct Slot<void(T_arg...)>
        {
-               Slot(std::function<void(T_arg...)> f) : func(f), delete_me(false) {}
+               /**
+                * @brief Construct slot object
+                *
+                * @param[in] f callback
+                * @param[in] ptr shared pointer to connection data
+                */
+               Slot(std::function<void(T_arg...)> f, std::shared_ptr<SignalBaseConnection> ptr)
+                       : func(f), conn(ptr) {}
                /** @brief Function to call */
                std::function<void(T_arg...)> func;
-               /** @brief slot has been marked for deletion */
-               bool delete_me;
+               /** @brief connection to slot */
+               std::weak_ptr<SignalBaseConnection> conn;
        };
 
        /**
@@ -157,7 +158,8 @@ namespace utils {
                                recursive_count_++;
                                auto it = slots_.begin();
                                while (it != slots_.end()) {
-                                       if (!it->delete_me) it->func(a...);
+                                       if (auto ref = it->conn.lock())
+                                               if (ref->IsConnected()) it->func(a...);
                                        if (on_delete_) return;
                                        ++it;
                                }
@@ -174,10 +176,10 @@ namespace utils {
                         */
                        Connection Connect(std::function<void(T_arg...)> f)
                        {
-                               Slot<void(T_arg...)> slot(f);
+                               auto conn = std::make_shared<SignalBaseConnection>();
+                               Slot<void(T_arg...)> slot(f, conn);
                                slots_.push_back(slot);
-                               auto ptr = new SignalConnection<void(T_arg...)>(&slots_.back());
-                               return std::unique_ptr<SignalBaseConnection>(ptr);
+                               return conn;
                        }
 
                        /**
@@ -187,18 +189,25 @@ namespace utils {
                         */
                        ~Signal()
                        {
+                               auto it = slots_.begin();
+                               while (it != slots_.end()) {
+                                       if (auto ref = it->conn.lock())
+                                               ref->Disconnect();
+                                       ++it;
+                               }
                                on_delete_ = true;
                                slots_.clear();
                        }
                protected:
                        /**
-                        * @brief Clear-up deleted slots
+                        * @brief Clean-up disconnected slots
                         */
                        void clean_slots()
                        {
                                auto it = slots_.begin();
                                while (it != slots_.end()) {
-                                       if (it->delete_me)
+                                       auto ref = it->conn.lock();
+                                       if (!ref || (ref && !ref->IsConnected()))
                                                it = slots_.erase(it);
                                        else
                                                ++it;
@@ -207,7 +216,9 @@ namespace utils {
 
                        /** @brief generic storage for slots */
                        std::list<Slot<void(T_arg...)>> slots_;
+                       /** Flag for handling destruction while calling slots functions */
                        bool on_delete_;
+                       /** Count of recursion calls */
                        int recursive_count_;
        };
 
@@ -218,65 +229,27 @@ namespace utils {
        class SignalBaseConnection
        {
                public:
-                       SignalBaseConnection() {}
-                       /** @brief Disconnects registered function from signal. */
-                       virtual void Disconnect() {}
-                       virtual ~SignalBaseConnection() {}
-       };
+                       SignalBaseConnection() : connected_(true) {}
 
-       /**
-        * @brief Specialized template for signal connections with functions of type
-        * void (*)(T_arg...)
-        */
-       template <typename... T_arg>
-       class SignalConnection<void(T_arg...)> : public SignalBaseConnection
-       {
-               public:
-               /**
-                * @brief Constructor
-                *
-                * @param[in] it iterator to list element
-                */
-               SignalConnection(Slot<void(T_arg...)> *slot) : slot_(slot) {}
-
-               ~SignalConnection() { Disconnect(); }
-
-               void Disconnect() override
-               {
-                       if (slot_) {
-                               slot_->delete_me = true;
-                               slot_ = nullptr;
+                       /** @brief Disconnects registered function from signal. */
+                       void Disconnect()
+                       {
+                               connected_ = false;
                        }
-               }
 
-               bool IsConnected() const
-               {
-                       return slot_ != nullptr;
-               }
-
-               /**
-                * @brief R-Value constructor
-                */
-               SignalConnection(SignalConnection&& ref)
-               {
-                       slot_ = ref.slot_;
-                       ref.slot_ = nullptr;
-               }
-
-               /**
-                * @brief Delete copy constructor
-                */
-               SignalConnection(const SignalConnection& ln) = delete;
-
-               /**
-                * @brief Delete assign operator
-                */
-               SignalConnection<T_arg...> operator=(const SignalConnection& ln) = delete;
+                       /** @brief Returns connection status */
+                       bool IsConnected()
+                       {
+                               return connected_;
+                       }
 
+                       ~SignalBaseConnection()
+                       {
+                               Disconnect();
+                       }
                private:
-                       Slot<void(T_arg...)> *slot_;
+                       bool connected_;
        };
-
 }; /* utils */
 
 #endif