diff options
-rw-r--r-- | src/FbTk/Signal.hh | 43 |
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 | ||
30 | namespace FbTk { | 31 | namespace FbTk { |
31 | 32 | ||
@@ -39,6 +40,14 @@ namespace SigImpl { | |||
39 | */ | 40 | */ |
40 | class SignalHolder { | 41 | class SignalHolder { |
41 | public: | 42 | public: |
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 | |||
62 | protected: | 86 | protected: |
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 | ||
74 | private: | 98 | private: |
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 | */ |
191 | class SignalTracker { | 217 | class SignalTracker: public SigImpl::SignalHolder::Tracker { |
192 | public: | 218 | public: |
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 | |||
275 | protected: | ||
276 | |||
277 | void disconnect(SigImpl::SignalHolder& signal) { | ||
278 | m_connections.erase(&signal); | ||
279 | } | ||
280 | |||
244 | private: | 281 | private: |
245 | typedef Connections::value_type ValueType; | 282 | typedef Connections::value_type ValueType; |
246 | typedef Connections::iterator Iterator; | 283 | typedef Connections::iterator Iterator; |