diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/FbTk/Signal.hh | 91 | ||||
-rw-r--r-- | src/FbTk/Slot.hh | 90 |
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 | ||
123 | template <typename Arg1, typename Arg2, typename Arg3> | 124 | } // namespace SigImpl |
124 | class SignalTemplate: public SignalHolder { | ||
125 | public: | ||
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 | ||
131 | protected: | 126 | |
132 | void emit_(Arg1 arg1, Arg2 arg2, Arg3 arg3) { | 127 | /// Specialization for three arguments. |
128 | template <typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg > | ||
129 | class Signal: public SigImpl::SignalHolder { | ||
130 | public: | ||
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) { |
146 | template <typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg > | 142 | return SignalHolder::connect(SlotPtr( |
147 | class Signal: public SigImpl::SignalTemplate<Arg1, Arg2, Arg3> { | 143 | new SlotImpl<Functor, void, Arg1, Arg2, Arg3>(functor) |
148 | public: | 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. |
154 | template <typename Arg1, typename Arg2> | 149 | template <typename Arg1, typename Arg2> |
155 | class Signal<Arg1, Arg2, SigImpl::EmptyArg>: | 150 | class Signal<Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SignalHolder { |
156 | public SigImpl::SignalTemplate<Arg1, Arg2, SigImpl::EmptyArg> { | ||
157 | public: | 151 | public: |
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. |
165 | template <typename Arg1> | 170 | template <typename Arg1> |
166 | class Signal<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: | 171 | class Signal<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder { |
167 | public SigImpl::SignalTemplate<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg> { | ||
168 | public: | 172 | public: |
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. |
176 | template <> | 191 | template <> |
177 | class Signal<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: | 192 | class Signal<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder { |
178 | public SigImpl::SignalTemplate<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg> { | ||
179 | public: | 193 | public: |
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 | ||
27 | namespace FbTk { | 27 | namespace FbTk { |
28 | 28 | ||
@@ -31,71 +31,99 @@ namespace SigImpl { | |||
31 | 31 | ||
32 | struct EmptyArg {}; | 32 | struct EmptyArg {}; |
33 | 33 | ||
34 | class 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 | */ | ||
37 | class SlotBase: private FbTk::NotCopyable { | ||
35 | public: | 38 | public: |
36 | virtual ~SlotBase() {} | 39 | virtual ~SlotBase() {} |
37 | }; | 40 | }; |
38 | 41 | ||
39 | template<typename Arg1, typename Arg2, typename Arg3> | 42 | } // namespace SigImpl |
40 | class 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 | */ | ||
47 | template<typename ReturnType, typename Arg1 = SigImpl::EmptyArg, | ||
48 | typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg> | ||
49 | class Slot: public SigImpl::SlotBase { | ||
50 | public: | ||
51 | virtual ReturnType operator()(Arg1, Arg2, Arg3) = 0; | ||
52 | }; | ||
53 | |||
54 | /// Specialization for two arguments | ||
55 | template<typename ReturnType, typename Arg1, typename Arg2> | ||
56 | class Slot<ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SlotBase { | ||
57 | public: | ||
58 | virtual ReturnType operator()(Arg1, Arg2) = 0; | ||
59 | }; | ||
60 | |||
61 | /// Specialization for one argument | ||
62 | template<typename ReturnType, typename Arg1> | ||
63 | class Slot<ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SlotBase { | ||
64 | public: | ||
65 | virtual ReturnType operator()(Arg1) = 0; | ||
66 | }; | ||
67 | |||
68 | /// Specialization for no arguments | ||
69 | template<typename ReturnType> | ||
70 | class Slot<ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SlotBase { | ||
41 | public: | 71 | public: |
42 | virtual void operator()(Arg1, Arg2, Arg3) = 0; | 72 | virtual ReturnType operator()() = 0; |
43 | }; | 73 | }; |
44 | 74 | ||
45 | template<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 |
46 | class Slot: public SlotTemplate<Arg1, Arg2, Arg3> { | 76 | * the function call operator |
77 | */ | ||
78 | template<typename Functor, typename ReturnType, typename Arg1 = SigImpl::EmptyArg, | ||
79 | typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg> | ||
80 | class SlotImpl: public Slot<ReturnType, Arg1, Arg2, Arg3> { | ||
47 | public: | 81 | public: |
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 | ||
53 | private: | 87 | private: |
54 | Functor m_functor; | 88 | Functor m_functor; |
55 | }; | 89 | }; |
56 | 90 | ||
57 | // specialization for two arguments | 91 | /// Specialization for two arguments |
58 | template<typename Arg1, typename Arg2, typename Functor> | 92 | template<typename Functor, typename ReturnType, typename Arg1, typename Arg2> |
59 | class Slot<Arg1, Arg2, EmptyArg, Functor>: public SlotTemplate<Arg1, Arg2, EmptyArg> { | 93 | class SlotImpl<Functor, ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public Slot<ReturnType, Arg1, Arg2> { |
60 | public: | 94 | public: |
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 | ||
66 | private: | 99 | private: |
67 | Functor m_functor; | 100 | Functor m_functor; |
68 | }; | 101 | }; |
69 | 102 | ||
70 | // specialization for one argument | 103 | /// Specialization for one argument |
71 | template<typename Arg1, typename Functor> | 104 | template<typename Functor, typename ReturnType, typename Arg1> |
72 | class Slot<Arg1, EmptyArg, EmptyArg, Functor>: public SlotTemplate<Arg1, EmptyArg, EmptyArg> { | 105 | class SlotImpl<Functor, ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public Slot<ReturnType, Arg1> { |
73 | public: | 106 | public: |
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 | ||
79 | private: | 111 | private: |
80 | Functor m_functor; | 112 | Functor m_functor; |
81 | }; | 113 | }; |
82 | 114 | ||
83 | // specialization for no arguments | 115 | /// Specialization for no arguments |
84 | template<typename Functor> | 116 | template<typename Functor, typename ReturnType> |
85 | class Slot<EmptyArg, EmptyArg, EmptyArg, Functor>: public SlotTemplate<EmptyArg, EmptyArg, EmptyArg> { | 117 | class SlotImpl<Functor, ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public Slot<ReturnType> { |
86 | public: | 118 | public: |
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 | ||
92 | private: | 123 | private: |
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 |