aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/FbTk/Signal.hh49
-rw-r--r--src/FbTk/Slot.hh275
2 files changed, 70 insertions, 254 deletions
diff --git a/src/FbTk/Signal.hh b/src/FbTk/Signal.hh
index 79d001f..71a4d6e 100644
--- a/src/FbTk/Signal.hh
+++ b/src/FbTk/Signal.hh
@@ -22,6 +22,7 @@
22#ifndef FBTK_SIGNAL_HH 22#ifndef FBTK_SIGNAL_HH
23#define FBTK_SIGNAL_HH 23#define FBTK_SIGNAL_HH
24 24
25#include "RefCount.hh"
25#include "Slot.hh" 26#include "Slot.hh"
26#include <list> 27#include <list>
27#include <map> 28#include <map>
@@ -49,7 +50,7 @@ public:
49 }; 50 };
50 51
51 /// Do not use this type outside this class 52 /// Do not use this type outside this class
52 typedef std::list<SlotHolder> SlotList; 53 typedef std::list<RefCount<SlotBase> > SlotList;
53 54
54 typedef SlotList::iterator Iterator; 55 typedef SlotList::iterator Iterator;
55 typedef Iterator SlotID; 56 typedef Iterator SlotID;
@@ -91,7 +92,7 @@ protected:
91 Iterator end() { return m_slots.end(); } 92 Iterator end() { return m_slots.end(); }
92 93
93 /// Connect a slot to this signal. Must only be called by child classes. 94 /// Connect a slot to this signal. Must only be called by child classes.
94 SlotID connect(const SlotHolder& slot) { 95 SlotID connect(const RefCount<SlotBase>& slot) {
95 return m_slots.insert(m_slots.end(), slot); 96 return m_slots.insert(m_slots.end(), slot);
96 } 97 }
97 98
@@ -111,16 +112,17 @@ template <typename ReturnType,
111 typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg > 112 typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg >
112class Signal: public SigImpl::SignalHolder { 113class Signal: public SigImpl::SignalHolder {
113public: 114public:
114 typedef SigImpl::Slot3<ReturnType, Arg1, Arg2, Arg3> SlotType;
115
116 void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) { 115 void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
117 for ( Iterator it = begin(); it != end(); ++it ) { 116 for ( Iterator it = begin(); it != end(); ++it ) {
118 static_cast<SlotType&>(*it)(arg1, arg2, arg3); 117 static_cast<SigImpl::SlotBase3<ReturnType, Arg1, Arg2, Arg3> &>(**it)(arg1, arg2, arg3);
119 } 118 }
120 } 119 }
121 120
122 SlotID connect(const SlotType& slot) { 121 template<typename Functor>
123 return SignalHolder::connect(slot); 122 SlotID connect(const Functor& functor) {
123 return SignalHolder::connect(FbTk::RefCount<SigImpl::SlotBase>(
124 new SigImpl::Slot3<ReturnType, Arg1, Arg2, Arg3, Functor>(functor)
125 ));
124 } 126 }
125}; 127};
126 128
@@ -128,16 +130,17 @@ public:
128template <typename ReturnType, typename Arg1, typename Arg2> 130template <typename ReturnType, typename Arg1, typename Arg2>
129class Signal<ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SignalHolder { 131class Signal<ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SignalHolder {
130public: 132public:
131 typedef SigImpl::Slot2<ReturnType, Arg1, Arg2> SlotType;
132
133 void emit(Arg1 arg1, Arg2 arg2) { 133 void emit(Arg1 arg1, Arg2 arg2) {
134 for ( Iterator it = begin(); it != end(); ++it ) { 134 for ( Iterator it = begin(); it != end(); ++it ) {
135 static_cast<SlotType&>(*it)(arg1, arg2); 135 static_cast<SigImpl::SlotBase2<ReturnType, Arg1, Arg2> &>(**it)(arg1, arg2);
136 } 136 }
137 } 137 }
138 138
139 SlotID connect(const SlotType& slot) { 139 template<typename Functor>
140 return SignalHolder::connect(slot); 140 SlotID connect(const Functor& functor) {
141 return SignalHolder::connect(FbTk::RefCount<SigImpl::SlotBase>(
142 new SigImpl::Slot2<ReturnType, Arg1, Arg2, Functor>(functor)
143 ));
141 } 144 }
142}; 145};
143 146
@@ -145,16 +148,17 @@ public:
145template <typename ReturnType, typename Arg1> 148template <typename ReturnType, typename Arg1>
146class Signal<ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder { 149class Signal<ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder {
147public: 150public:
148 typedef SigImpl::Slot1<ReturnType, Arg1> SlotType;
149
150 void emit(Arg1 arg) { 151 void emit(Arg1 arg) {
151 for ( Iterator it = begin(); it != end(); ++it ) { 152 for ( Iterator it = begin(); it != end(); ++it ) {
152 static_cast<SlotType&>(*it)(arg); 153 static_cast<SigImpl::SlotBase1<ReturnType, Arg1> &>(**it)(arg);
153 } 154 }
154 } 155 }
155 156
156 SlotID connect(const SlotType& slot) { 157 template<typename Functor>
157 return SignalHolder::connect(slot); 158 SlotID connect(const Functor& functor) {
159 return SignalHolder::connect(FbTk::RefCount<SigImpl::SlotBase>(
160 new SigImpl::Slot1<ReturnType, Arg1, Functor>(functor)
161 ));
158 } 162 }
159}; 163};
160 164
@@ -162,16 +166,17 @@ public:
162template <typename ReturnType> 166template <typename ReturnType>
163class Signal<ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder { 167class Signal<ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder {
164public: 168public:
165 typedef SigImpl::Slot0<ReturnType> SlotType;
166
167 void emit() { 169 void emit() {
168 for ( Iterator it = begin(); it != end(); ++it ) { 170 for ( Iterator it = begin(); it != end(); ++it ) {
169 static_cast<SlotType&>(*it)(); 171 static_cast<SigImpl::SlotBase0<ReturnType> &>(**it)();
170 } 172 }
171 } 173 }
172 174
173 SlotID connect(const SlotType& slot) { 175 template<typename Functor>
174 return SignalHolder::connect(slot); 176 SlotID connect(const Functor& functor) {
177 return SignalHolder::connect(FbTk::RefCount<SigImpl::SlotBase>(
178 new SigImpl::Slot0<ReturnType, Functor>(functor)
179 ));
175 } 180 }
176}; 181};
177 182
diff --git a/src/FbTk/Slot.hh b/src/FbTk/Slot.hh
index 9080d53..3daca4e 100644
--- a/src/FbTk/Slot.hh
+++ b/src/FbTk/Slot.hh
@@ -27,268 +27,79 @@ namespace FbTk {
27/// \namespace Implementation details for signals, do not use anything in this namespace 27/// \namespace Implementation details for signals, do not use anything in this namespace
28namespace SigImpl { 28namespace SigImpl {
29 29
30class CallbackHolder; 30class SlotBase {
31
32/// Placeholder type for typed callbacks
33typedef void* (*CallbackFunc)(void *);
34/// Clone function callback type for cloning typed callback holders
35typedef CallbackHolder* (*CloneFunc)(CallbackHolder*);
36/// Kill function callback type for destroying type specific information in
37/// FunctorHolder
38typedef void (*KillFunc)(CallbackHolder*);
39
40/// Holds clone, functor callback, and the kill function for FunctorHolder.
41class CallbackHolder {
42public: 31public:
43 /** 32 virtual ~SlotBase() {}
44 * @param callback The callback to call when a slot receives a signal.
45 * @param clone The callback to use for cloning a type specific instance of
46 * this classinstance.
47 * @param kill The callback that knows how to free the memory in type
48 * specific instance of this class.
49 */
50 CallbackHolder(CallbackFunc callback,
51 CloneFunc clone,
52 KillFunc kill):
53 m_callback(callback),
54 m_kill(kill),
55 m_clone(clone) { }
56
57 ~CallbackHolder() {
58 (*m_kill)(this);
59 }
60
61 /// @return a clone of this instance
62 CallbackHolder* clone() {
63 return (*m_clone)(this);
64 }
65
66 /// \c Callback to \c Functor specific callback
67 CallbackFunc m_callback;
68
69protected:
70
71 CallbackHolder& operator = (const CallbackHolder& other) {
72 if ( this == &other ) {
73 return *this;
74 }
75 m_callback = other.m_callback;
76 m_clone = other.m_clone;
77 m_kill = other.m_kill;
78
79 return *this;
80 }
81
82 CallbackHolder(const CallbackHolder& other) {
83 *this = other;
84 }
85
86private:
87 /// This function is called to kill this instance
88 KillFunc m_kill;
89 /// Functions that knows how to clone a specific \c Functor type
90 CloneFunc m_clone;
91}; 33};
92 34
93 35template<typename ReturnType>
94/// Holds the functor and creates a clone callback for \c Functor specific type 36class SlotBase0: public SlotBase {
95template <typename Functor>
96class FunctorHolder: public CallbackHolder {
97public: 37public:
98 /// This type. 38 virtual ReturnType operator()() = 0;
99 typedef FunctorHolder<Functor> Self;
100 /**
101 * @param functor The functor to be used when a signal is emitted.
102 * @param callback The callback to call when a signal is emitted.
103 */
104 FunctorHolder(const Functor& functor, CallbackFunc callback):
105 CallbackHolder(callback, &clone, &kill),
106 m_functor(functor) {
107 }
108
109 /// Specific clone for this Functor type
110 static CallbackHolder* clone(CallbackHolder* self) {
111 return new Self( static_cast<Self&>(*self));
112 }
113
114 static void kill(CallbackHolder* self) {
115 // Destroy functor
116 static_cast<Self*>( self )->m_functor.~Functor();
117 }
118
119 Functor m_functor; ///< the functor to use when a signal is emitted.
120};
121
122
123
124/// Callback with no arguments.
125template <typename Functor, typename ReturnType >
126struct Callback0 {
127 static ReturnType callback(CallbackHolder* base) {
128 static_cast< FunctorHolder<Functor>* >( base )->m_functor();
129 return ReturnType();
130 }
131
132 static CallbackFunc functionAddress() {
133 return reinterpret_cast<CallbackFunc>(&callback);
134 }
135}; 39};
136 40
137/// Callback with one argument 41template<typename ReturnType, typename Functor>
138template <typename Functor, typename ReturnType, typename Arg1> 42class Slot0: public SlotBase0<ReturnType> {
139struct Callback1 { 43public:
140 typedef ReturnType (Functor::* CallbackType)(CallbackHolder*, Arg1); 44 virtual ReturnType operator()() { return m_functor(); }
141
142 static ReturnType callback(CallbackHolder* base, Arg1 arg1) {
143 static_cast< FunctorHolder<Functor>* >( base )->m_functor(arg1);
144 return ReturnType();
145 }
146
147 static CallbackFunc functionAddress() {
148 return reinterpret_cast<CallbackFunc>(&callback);
149 }
150};
151
152/// Callback with two arguments
153template <typename Functor, typename ReturnType,
154 typename Arg1, typename Arg2>
155struct Callback2 {
156 typedef ReturnType (Functor::* CallbackType)(CallbackHolder*, Arg1, Arg2);
157 45
158 static ReturnType callback(CallbackHolder* base, Arg1 arg1, Arg2 arg2) { 46 Slot0(Functor functor) : m_functor(functor) {}
159 static_cast< FunctorHolder<Functor>* >( base )->m_functor(arg1, arg2);
160 return ReturnType();
161 }
162 47
163 static CallbackFunc functionAddress() { 48private:
164 return reinterpret_cast<CallbackFunc>(&callback); 49 Functor m_functor;
165 }
166}; 50};
167 51
168/// Callback with three arguments 52template<typename ReturnType, typename Arg1>
169template <typename Functor, typename ReturnType, 53class SlotBase1: public SlotBase {
170 typename Arg1, typename Arg2, typename Arg3> 54public:
171struct Callback3 { 55 virtual ReturnType operator()(Arg1) = 0;
172 typedef ReturnType (Functor::* CallbackType)(CallbackHolder*, Arg1, Arg2, Arg3);
173
174 static ReturnType callback(CallbackHolder* base, Arg1 arg1, Arg2 arg2, Arg3 arg3) {
175 static_cast< FunctorHolder<Functor>* >( base )->m_functor( arg1, arg2, arg3 );
176 return ReturnType();
177 }
178
179 static CallbackFunc functionAddress() {
180 return reinterpret_cast<CallbackFunc>(&callback);
181 }
182}; 56};
183 57
184/// Holds callback holder and handles the copying of callback holders for the 58template<typename ReturnType, typename Arg1, typename Functor>
185/// \c Slots. 59class Slot1: public SlotBase1<ReturnType, Arg1> {
186class SlotHolder {
187public: 60public:
188 SlotHolder(const SlotHolder& other): 61 virtual ReturnType operator()(Arg1 arg1) { return m_functor(arg1); }
189 m_holder( other.m_holder ? other.m_holder->clone() : 0 ) {
190 }
191
192 ~SlotHolder() {
193 delete m_holder;
194 }
195
196 SlotHolder& operator = (const SlotHolder& other) {
197 if ( &other == this ) {
198 return *this;
199 }
200 delete m_holder;
201 if ( other.m_holder ) {
202 m_holder = other.m_holder->clone();
203 } else {
204 m_holder = 0;
205 }
206 return *this;
207 }
208 62
209 SlotHolder():m_holder( 0 ) { } 63 Slot1(Functor functor) : m_functor(functor) {}
210 64
211protected: 65private:
212 explicit SlotHolder(CallbackHolder* holder): 66 Functor m_functor;
213 m_holder( holder ) {
214 }
215
216 CallbackHolder* m_holder;
217}; 67};
218 68
219/// Slot with no argument. 69template<typename ReturnType, typename Arg1, typename Arg2>
220template <typename ReturnType> 70class SlotBase2: public SlotBase {
221class Slot0: public SlotHolder {
222public: 71public:
223 typedef ReturnType (*CallbackType)(CallbackHolder*); 72 virtual ReturnType operator()(Arg1, Arg2) = 0;
224
225 template <typename Functor>
226 Slot0( const Functor& functor ):
227 SlotHolder( new FunctorHolder<Functor>
228 (functor, Callback0<Functor, ReturnType>::functionAddress())) {
229 }
230
231 void operator()() {
232 if (m_holder)
233 reinterpret_cast<CallbackType>(m_holder->m_callback)( m_holder );
234 }
235}; 73};
236 74
237/// Slot with one argument. 75template<typename ReturnType, typename Arg1, typename Arg2, typename Functor>
238template <typename ReturnType, typename Arg1> 76class Slot2: public SlotBase2<ReturnType, Arg1, Arg2> {
239class Slot1:public SlotHolder {
240public: 77public:
241 typedef ReturnType (*CallbackType)(CallbackHolder*, Arg1); 78 virtual ReturnType operator()(Arg1 arg1, Arg2 arg2) { return m_functor(arg1, arg2); }
242
243 template <typename Functor>
244 Slot1( const Functor& functor ):
245 SlotHolder( new FunctorHolder<Functor>
246 (functor, Callback1<Functor, ReturnType, Arg1>::functionAddress())){
247
248 }
249 79
250 void operator()(Arg1 arg) { 80 Slot2(Functor functor) : m_functor(functor) {}
251 if (m_holder)
252 reinterpret_cast<CallbackType>(m_holder->m_callback)(m_holder, arg);
253 }
254 81
82private:
83 Functor m_functor;
255}; 84};
256 85
257/// Slot with two arguments 86template<typename ReturnType, typename Arg1, typename Arg2, typename Arg3>
258template <typename ReturnType, typename Arg1, typename Arg2> 87class SlotBase3: public SlotBase {
259class Slot2: public SlotHolder {
260public: 88public:
261 typedef ReturnType (*CallbackType)(CallbackHolder*, Arg1, Arg2); 89 virtual ReturnType operator()(Arg1, Arg2, Arg3) = 0;
262 template <typename Functor> 90 virtual ~SlotBase3() {}
263 Slot2( const Functor& functor ):
264 SlotHolder( new FunctorHolder<Functor>
265 (functor, Callback2<Functor, ReturnType, Arg1, Arg2>::functionAddress())){
266
267 }
268
269 void operator()(Arg1 arg1, Arg2 arg2) {
270 if (m_holder)
271 reinterpret_cast<CallbackType>(m_holder->m_callback)(m_holder, arg1, arg2);
272 }
273}; 91};
274 92
275/// Slot with three arguments 93template<typename ReturnType, typename Arg1, typename Arg2, typename Arg3, typename Functor>
276template <typename ReturnType, typename Arg1, typename Arg2, typename Arg3> 94class Slot3: public SlotBase3<ReturnType, Arg1, Arg2, Arg3> {
277class Slot3: public SlotHolder {
278public: 95public:
279 typedef ReturnType (*CallbackType)(CallbackHolder*, Arg1, Arg2, Arg3); 96 virtual ReturnType operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3)
280 template <typename Functor> 97 { return m_functor(arg1, arg2, arg3); }
281 Slot3( const Functor& functor ):
282 SlotHolder( new FunctorHolder<Functor>
283 (functor, Callback3<Functor, ReturnType, Arg1, Arg2, Arg3>::functionAddress())){
284
285 }
286 98
287 void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) { 99 Slot3(Functor functor) : m_functor(functor) {}
288 if (m_holder) 100
289 reinterpret_cast<CallbackType>(m_holder->m_callback) 101private:
290 ( m_holder, arg1, arg2, arg3 ); 102 Functor m_functor;
291 }
292}; 103};
293 104
294} // namespace SigImpl 105} // namespace SigImpl