aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/FbTk/Signal.hh43
1 files changed, 40 insertions, 3 deletions
diff --git a/src/FbTk/Signal.hh b/src/FbTk/Signal.hh
index 7ad4d00..af9b043 100644
--- a/src/FbTk/Signal.hh
+++ b/src/FbTk/Signal.hh
@@ -26,6 +26,7 @@
26#include <list> 26#include <list>
27#include <map> 27#include <map>
28#include <vector> 28#include <vector>
29#include <set>
29 30
30namespace FbTk { 31namespace FbTk {
31 32
@@ -39,6 +40,14 @@ namespace SigImpl {
39 */ 40 */
40class SignalHolder { 41class SignalHolder {
41public: 42public:
43 /// Special tracker interface used by SignalTracker.
44 class Tracker {
45 public:
46 virtual ~Tracker() { }
47 /// Disconnect this holder.
48 virtual void disconnect(SignalHolder& signal) = 0;
49 };
50
42 /// Do not use this type outside this class 51 /// Do not use this type outside this class
43 typedef std::list<SlotHolder> SlotList; 52 typedef std::list<SlotHolder> SlotList;
44 53
@@ -46,7 +55,14 @@ public:
46 typedef Iterator SlotID; 55 typedef Iterator SlotID;
47 typedef SlotList::const_iterator ConstIterator; 56 typedef SlotList::const_iterator ConstIterator;
48 57
49 ~SignalHolder() { } 58 ~SignalHolder() {
59 // Disconnect this holder from all trackers.
60 for (Trackers::iterator it = m_trackers.begin(),
61 it_end = m_trackers.end();
62 it != it_end; ++it ) {
63 (*it)->disconnect(*this);
64 }
65 }
50 66
51 /// Remove a specific slot \c id from this signal 67 /// Remove a specific slot \c id from this signal
52 void disconnect(SlotID slotIt) { 68 void disconnect(SlotID slotIt) {
@@ -59,6 +75,14 @@ public:
59 m_slots.clear(); 75 m_slots.clear();
60 } 76 }
61 77
78 void connectTracker(SignalHolder::Tracker& tracker) {
79 m_trackers.insert(&tracker);
80 }
81
82 void disconnectTracker(SignalHolder::Tracker& tracker) {
83 m_trackers.erase(&tracker);
84 }
85
62protected: 86protected:
63 ConstIterator begin() const { return m_slots.begin(); } 87 ConstIterator begin() const { return m_slots.begin(); }
64 ConstIterator end() const { return m_slots.end(); } 88 ConstIterator end() const { return m_slots.end(); }
@@ -72,7 +96,9 @@ protected:
72 } 96 }
73 97
74private: 98private:
99 typedef std::set<Tracker*> Trackers;
75 SlotList m_slots; ///< all slots connected to a signal 100 SlotList m_slots; ///< all slots connected to a signal
101 Trackers m_trackers; ///< all instances that tracks this signal.
76}; 102};
77 103
78/// Signal with no argument 104/// Signal with no argument
@@ -188,7 +214,7 @@ public:
188 * Tracks a signal during it's life time. All signals connected using \c 214 * Tracks a signal during it's life time. All signals connected using \c
189 * SignalTracker::join will be erased when this instance dies. 215 * SignalTracker::join will be erased when this instance dies.
190 */ 216 */
191class SignalTracker { 217class SignalTracker: public SigImpl::SignalHolder::Tracker {
192public: 218public:
193 /// Internal type, do not use. 219 /// Internal type, do not use.
194 typedef std::map<SigImpl::SignalHolder*, 220 typedef std::map<SigImpl::SignalHolder*,
@@ -200,7 +226,7 @@ public:
200 } 226 }
201 227
202 /// Starts tracking a signal. 228 /// Starts tracking a signal.
203 /// @return A tracking ID ( not unique ) 229 /// @return A tracking ID
204 template <typename Signal, typename Functor> 230 template <typename Signal, typename Functor>
205 TrackID join(Signal& sig, const Functor& functor) { 231 TrackID join(Signal& sig, const Functor& functor) {
206 ValueType value = ValueType(&sig, sig.connect(functor)); 232 ValueType value = ValueType(&sig, sig.connect(functor));
@@ -209,6 +235,9 @@ public:
209 // failed to insert this functor 235 // failed to insert this functor
210 sig.disconnect(value.second); 236 sig.disconnect(value.second);
211 } 237 }
238
239 sig.connectTracker(*this);
240
212 return ret.first; 241 return ret.first;
213 } 242 }
214 243
@@ -239,8 +268,16 @@ public:
239 ValueType tmp = *conIt; 268 ValueType tmp = *conIt;
240 m_connections.erase(conIt); 269 m_connections.erase(conIt);
241 tmp.first->disconnect(tmp.second); 270 tmp.first->disconnect(tmp.second);
271 tmp.first->disconnectTracker(*this);
242 } 272 }
243 } 273 }
274
275protected:
276
277 void disconnect(SigImpl::SignalHolder& signal) {
278 m_connections.erase(&signal);
279 }
280
244private: 281private:
245 typedef Connections::value_type ValueType; 282 typedef Connections::value_type ValueType;
246 typedef Connections::iterator Iterator; 283 typedef Connections::iterator Iterator;