aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/FbTk/Signal.hh91
-rw-r--r--src/FbTk/Slot.hh90
2 files changed, 117 insertions, 64 deletions
diff --git a/src/FbTk/Signal.hh b/src/FbTk/Signal.hh
index 0148a17..31fd840 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 <algorithm> 27#include <algorithm>
27#include <list> 28#include <list>
@@ -120,66 +121,90 @@ private:
120 unsigned m_emitting; 121 unsigned m_emitting;
121}; 122};
122 123
123template <typename Arg1, typename Arg2, typename Arg3> 124} // namespace SigImpl
124class SignalTemplate: public SignalHolder {
125public:
126 template<typename Functor>
127 SlotID connect(const Functor& functor) {
128 return SignalHolder::connect(SlotPtr( new Slot<Arg1, Arg2, Arg3, Functor>(functor) ));
129 }
130 125
131protected: 126
132 void emit_(Arg1 arg1, Arg2 arg2, Arg3 arg3) { 127/// Specialization for three arguments.
128template <typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg >
129class Signal: public SigImpl::SignalHolder {
130public:
131 void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
133 begin_emitting(); 132 begin_emitting();
134 for ( Iterator it = begin(); it != end(); ++it ) { 133 for ( Iterator it = begin(); it != end(); ++it ) {
135 if(*it) 134 if(*it)
136 static_cast<SigImpl::SlotTemplate<Arg1, Arg2, Arg3> &>(**it)(arg1, arg2, arg3); 135 static_cast<Slot<void, Arg1, Arg2, Arg3> &>(**it)(arg1, arg2, arg3);
137 } 136 }
138 end_emitting(); 137 end_emitting();
139 } 138 }
140};
141
142} // namespace SigImpl
143 139
144 140 template<typename Functor>
145/// Base template for three arguments. 141 SlotID connect(const Functor& functor) {
146template <typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg > 142 return SignalHolder::connect(SlotPtr(
147class Signal: public SigImpl::SignalTemplate<Arg1, Arg2, Arg3> { 143 new SlotImpl<Functor, void, Arg1, Arg2, Arg3>(functor)
148public: 144 ));
149 void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) 145 }
150 { SigImpl::SignalTemplate<Arg1, Arg2, Arg3>::emit_(arg1, arg2, arg3); }
151}; 146};
152 147
153/// Specialization for two arguments. 148/// Specialization for two arguments.
154template <typename Arg1, typename Arg2> 149template <typename Arg1, typename Arg2>
155class Signal<Arg1, Arg2, SigImpl::EmptyArg>: 150class Signal<Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SignalHolder {
156 public SigImpl::SignalTemplate<Arg1, Arg2, SigImpl::EmptyArg> {
157public: 151public:
158 void emit(Arg1 arg1, Arg2 arg2) { 152 void emit(Arg1 arg1, Arg2 arg2) {
159 SigImpl::SignalTemplate<Arg1, Arg2, SigImpl::EmptyArg>:: 153 begin_emitting();
160 emit_(arg1, arg2, SigImpl::EmptyArg()); 154 for ( Iterator it = begin(); it != end(); ++it ) {
155 if(*it)
156 static_cast<Slot<void, Arg1, Arg2> &>(**it)(arg1, arg2);
157 }
158 end_emitting();
159 }
160
161 template<typename Functor>
162 SlotID connect(const Functor& functor) {
163 return SignalHolder::connect(SlotPtr(
164 new SlotImpl<Functor, void, Arg1, Arg2>(functor)
165 ));
161 } 166 }
162}; 167};
163 168
164/// Specialization for one argument. 169/// Specialization for one argument.
165template <typename Arg1> 170template <typename Arg1>
166class Signal<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: 171class Signal<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder {
167 public SigImpl::SignalTemplate<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg> {
168public: 172public:
169 void emit(Arg1 arg1) { 173 void emit(Arg1 arg) {
170 SigImpl::SignalTemplate<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg> 174 begin_emitting();
171 ::emit_(arg1, SigImpl::EmptyArg(), SigImpl::EmptyArg()); 175 for ( Iterator it = begin(); it != end(); ++it ) {
176 if(*it)
177 static_cast<Slot<void, Arg1> &>(**it)(arg);
178 }
179 end_emitting();
180 }
181
182 template<typename Functor>
183 SlotID connect(const Functor& functor) {
184 return SignalHolder::connect(SlotPtr(
185 new SlotImpl<Functor, void, Arg1>(functor)
186 ));
172 } 187 }
173}; 188};
174 189
175/// Specialization for no arguments. 190/// Specialization for no arguments.
176template <> 191template <>
177class Signal<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: 192class Signal<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder {
178 public SigImpl::SignalTemplate<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg> {
179public: 193public:
180 void emit() { 194 void emit() {
181 SigImpl::SignalTemplate<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg> 195 begin_emitting();
182 ::emit_(SigImpl::EmptyArg(), SigImpl::EmptyArg(), SigImpl::EmptyArg()); 196 for ( Iterator it = begin(); it != end(); ++it ) {
197 if(*it)
198 static_cast<Slot<void> &>(**it)();
199 }
200 end_emitting();
201 }
202
203 template<typename Functor>
204 SlotID connect(const Functor& functor) {
205 return SignalHolder::connect(SlotPtr(
206 new SlotImpl<Functor, void>(functor)
207 ));
183 } 208 }
184}; 209};
185 210
diff --git a/src/FbTk/Slot.hh b/src/FbTk/Slot.hh
index ea7ee2f..71bf6ab 100644
--- a/src/FbTk/Slot.hh
+++ b/src/FbTk/Slot.hh
@@ -22,7 +22,7 @@
22#ifndef FBTK_SLOT_HH 22#ifndef FBTK_SLOT_HH
23#define FBTK_SLOT_HH 23#define FBTK_SLOT_HH
24 24
25#include "RefCount.hh" 25#include "NotCopyable.hh"
26 26
27namespace FbTk { 27namespace FbTk {
28 28
@@ -31,71 +31,99 @@ namespace SigImpl {
31 31
32struct EmptyArg {}; 32struct EmptyArg {};
33 33
34class SlotBase { 34/** A base class for all slots. It's purpose is to provide a virtual destructor and to enable the
35 * Signal class to hold a pointer to a generic slot.
36 */
37class SlotBase: private FbTk::NotCopyable {
35public: 38public:
36 virtual ~SlotBase() {} 39 virtual ~SlotBase() {}
37}; 40};
38 41
39template<typename Arg1, typename Arg2, typename Arg3> 42} // namespace SigImpl
40class SlotTemplate: public SlotBase { 43
44/** Declares a pure virtual function call operator with a specific number of arguments (depending
45 * on the template specialization). This allows us to "call" any functor in an opaque way.
46 */
47template<typename ReturnType, typename Arg1 = SigImpl::EmptyArg,
48 typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg>
49class Slot: public SigImpl::SlotBase {
50public:
51 virtual ReturnType operator()(Arg1, Arg2, Arg3) = 0;
52};
53
54/// Specialization for two arguments
55template<typename ReturnType, typename Arg1, typename Arg2>
56class Slot<ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SlotBase {
57public:
58 virtual ReturnType operator()(Arg1, Arg2) = 0;
59};
60
61/// Specialization for one argument
62template<typename ReturnType, typename Arg1>
63class Slot<ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SlotBase {
64public:
65 virtual ReturnType operator()(Arg1) = 0;
66};
67
68/// Specialization for no arguments
69template<typename ReturnType>
70class Slot<ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SlotBase {
41public: 71public:
42 virtual void operator()(Arg1, Arg2, Arg3) = 0; 72 virtual ReturnType operator()() = 0;
43}; 73};
44 74
45template<typename Arg1, typename Arg2, typename Arg3, typename Functor> 75/** A class which knows how to call a specific functor. It inherits from Slot and implemetents
46class Slot: public SlotTemplate<Arg1, Arg2, Arg3> { 76 * the function call operator
77 */
78template<typename Functor, typename ReturnType, typename Arg1 = SigImpl::EmptyArg,
79 typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg>
80class SlotImpl: public Slot<ReturnType, Arg1, Arg2, Arg3> {
47public: 81public:
48 virtual void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) 82 virtual ReturnType operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3)
49 { m_functor(arg1, arg2, arg3); } 83 { return m_functor(arg1, arg2, arg3); }
50 84
51 Slot(Functor functor) : m_functor(functor) {} 85 SlotImpl(Functor functor) : m_functor(functor) {}
52 86
53private: 87private:
54 Functor m_functor; 88 Functor m_functor;
55}; 89};
56 90
57// specialization for two arguments 91/// Specialization for two arguments
58template<typename Arg1, typename Arg2, typename Functor> 92template<typename Functor, typename ReturnType, typename Arg1, typename Arg2>
59class Slot<Arg1, Arg2, EmptyArg, Functor>: public SlotTemplate<Arg1, Arg2, EmptyArg> { 93class SlotImpl<Functor, ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public Slot<ReturnType, Arg1, Arg2> {
60public: 94public:
61 virtual void operator()(Arg1 arg1, Arg2 arg2, EmptyArg) 95 virtual ReturnType operator()(Arg1 arg1, Arg2 arg2) { return m_functor(arg1, arg2); }
62 { m_functor(arg1, arg2); }
63 96
64 Slot(Functor functor) : m_functor(functor) {} 97 SlotImpl(Functor functor) : m_functor(functor) {}
65 98
66private: 99private:
67 Functor m_functor; 100 Functor m_functor;
68}; 101};
69 102
70// specialization for one argument 103/// Specialization for one argument
71template<typename Arg1, typename Functor> 104template<typename Functor, typename ReturnType, typename Arg1>
72class Slot<Arg1, EmptyArg, EmptyArg, Functor>: public SlotTemplate<Arg1, EmptyArg, EmptyArg> { 105class SlotImpl<Functor, ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public Slot<ReturnType, Arg1> {
73public: 106public:
74 virtual void operator()(Arg1 arg1, EmptyArg, EmptyArg) 107 virtual ReturnType operator()(Arg1 arg1) { return m_functor(arg1); }
75 { m_functor(arg1); }
76 108
77 Slot(Functor functor) : m_functor(functor) {} 109 SlotImpl(Functor functor) : m_functor(functor) {}
78 110
79private: 111private:
80 Functor m_functor; 112 Functor m_functor;
81}; 113};
82 114
83// specialization for no arguments 115/// Specialization for no arguments
84template<typename Functor> 116template<typename Functor, typename ReturnType>
85class Slot<EmptyArg, EmptyArg, EmptyArg, Functor>: public SlotTemplate<EmptyArg, EmptyArg, EmptyArg> { 117class SlotImpl<Functor, ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public Slot<ReturnType> {
86public: 118public:
87 virtual void operator()(EmptyArg, EmptyArg, EmptyArg) 119 virtual ReturnType operator()() { return m_functor(); }
88 { m_functor(); }
89 120
90 Slot(Functor functor) : m_functor(functor) {} 121 SlotImpl(Functor functor) : m_functor(functor) {}
91 122
92private: 123private:
93 Functor m_functor; 124 Functor m_functor;
94}; 125};
95 126
96} // namespace SigImpl
97
98} // namespace FbTk 127} // namespace FbTk
99 128
100
101#endif // FBTK_SLOT_H 129#endif // FBTK_SLOT_H