1 | // |
2 | // Delegate.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Events |
6 | // Module: Delegate |
7 | // |
8 | // Implementation of the Delegate template. |
9 | // |
10 | // Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_Delegate_INCLUDED |
18 | #define Foundation_Delegate_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/AbstractDelegate.h" |
23 | #include "Poco/FunctionDelegate.h" |
24 | #include "Poco/Expire.h" |
25 | #include "Poco/Mutex.h" |
26 | |
27 | |
28 | namespace Poco { |
29 | |
30 | |
31 | template <class TObj, class TArgs, bool withSender = true> |
32 | class Delegate: public AbstractDelegate<TArgs> |
33 | { |
34 | public: |
35 | typedef void (TObj::*NotifyMethod)(const void*, TArgs&); |
36 | |
37 | Delegate(TObj* obj, NotifyMethod method): |
38 | _receiverObject(obj), |
39 | _receiverMethod(method) |
40 | { |
41 | } |
42 | |
43 | Delegate(const Delegate& delegate): |
44 | AbstractDelegate<TArgs>(delegate), |
45 | _receiverObject(delegate._receiverObject), |
46 | _receiverMethod(delegate._receiverMethod) |
47 | { |
48 | } |
49 | |
50 | ~Delegate() |
51 | { |
52 | } |
53 | |
54 | Delegate& operator = (const Delegate& delegate) |
55 | { |
56 | if (&delegate != this) |
57 | { |
58 | this->_receiverObject = delegate._receiverObject; |
59 | this->_receiverMethod = delegate._receiverMethod; |
60 | } |
61 | return *this; |
62 | } |
63 | |
64 | bool notify(const void* sender, TArgs& arguments) |
65 | { |
66 | Mutex::ScopedLock lock(_mutex); |
67 | if (_receiverObject) |
68 | { |
69 | (_receiverObject->*_receiverMethod)(sender, arguments); |
70 | return true; |
71 | } |
72 | else return false; |
73 | } |
74 | |
75 | bool equals(const AbstractDelegate<TArgs>& other) const |
76 | { |
77 | const Delegate* pOtherDelegate = dynamic_cast<const Delegate*>(other.unwrap()); |
78 | return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod; |
79 | } |
80 | |
81 | AbstractDelegate<TArgs>* clone() const |
82 | { |
83 | return new Delegate(*this); |
84 | } |
85 | |
86 | void disable() |
87 | { |
88 | Mutex::ScopedLock lock(_mutex); |
89 | _receiverObject = 0; |
90 | } |
91 | |
92 | protected: |
93 | TObj* _receiverObject; |
94 | NotifyMethod _receiverMethod; |
95 | Mutex _mutex; |
96 | |
97 | private: |
98 | Delegate(); |
99 | }; |
100 | |
101 | |
102 | template <class TObj, class TArgs> |
103 | class Delegate<TObj, TArgs, false>: public AbstractDelegate<TArgs> |
104 | { |
105 | public: |
106 | typedef void (TObj::*NotifyMethod)(TArgs&); |
107 | |
108 | Delegate(TObj* obj, NotifyMethod method): |
109 | _receiverObject(obj), |
110 | _receiverMethod(method) |
111 | { |
112 | } |
113 | |
114 | Delegate(const Delegate& delegate): |
115 | AbstractDelegate<TArgs>(delegate), |
116 | _receiverObject(delegate._receiverObject), |
117 | _receiverMethod(delegate._receiverMethod) |
118 | { |
119 | } |
120 | |
121 | ~Delegate() |
122 | { |
123 | } |
124 | |
125 | Delegate& operator = (const Delegate& delegate) |
126 | { |
127 | if (&delegate != this) |
128 | { |
129 | this->_receiverObject = delegate._receiverObject; |
130 | this->_receiverMethod = delegate._receiverMethod; |
131 | } |
132 | return *this; |
133 | } |
134 | |
135 | bool notify(const void*, TArgs& arguments) |
136 | { |
137 | Mutex::ScopedLock lock(_mutex); |
138 | if (_receiverObject) |
139 | { |
140 | (_receiverObject->*_receiverMethod)(arguments); |
141 | return true; |
142 | } |
143 | else return false; |
144 | } |
145 | |
146 | bool equals(const AbstractDelegate<TArgs>& other) const |
147 | { |
148 | const Delegate* pOtherDelegate = dynamic_cast<const Delegate*>(other.unwrap()); |
149 | return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod; |
150 | } |
151 | |
152 | AbstractDelegate<TArgs>* clone() const |
153 | { |
154 | return new Delegate(*this); |
155 | } |
156 | |
157 | void disable() |
158 | { |
159 | Mutex::ScopedLock lock(_mutex); |
160 | _receiverObject = 0; |
161 | } |
162 | |
163 | protected: |
164 | TObj* _receiverObject; |
165 | NotifyMethod _receiverMethod; |
166 | Mutex _mutex; |
167 | |
168 | private: |
169 | Delegate(); |
170 | }; |
171 | |
172 | |
173 | template <class TObj, class TArgs> |
174 | inline Delegate<TObj, TArgs, true> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&)) |
175 | { |
176 | return Delegate<TObj, TArgs, true>(pObj, NotifyMethod); |
177 | } |
178 | |
179 | |
180 | template <class TObj, class TArgs> |
181 | inline Delegate<TObj, TArgs, false> delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&)) |
182 | { |
183 | return Delegate<TObj, TArgs, false>(pObj, NotifyMethod); |
184 | } |
185 | |
186 | |
187 | template <class TObj, class TArgs> |
188 | inline Expire<TArgs> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&), Timestamp::TimeDiff expireMillisecs) |
189 | { |
190 | return Expire<TArgs>(Delegate<TObj, TArgs, true>(pObj, NotifyMethod), expireMillisecs); |
191 | } |
192 | |
193 | |
194 | template <class TObj, class TArgs> |
195 | inline Expire<TArgs> delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&), Timestamp::TimeDiff expireMillisecs) |
196 | { |
197 | return Expire<TArgs>(Delegate<TObj, TArgs, false>(pObj, NotifyMethod), expireMillisecs); |
198 | } |
199 | |
200 | |
201 | template <class TArgs> |
202 | inline Expire<TArgs> delegate(void (*NotifyMethod)(const void*, TArgs&), Timestamp::TimeDiff expireMillisecs) |
203 | { |
204 | return Expire<TArgs>(FunctionDelegate<TArgs, true, true>(NotifyMethod), expireMillisecs); |
205 | } |
206 | |
207 | |
208 | template <class TArgs> |
209 | inline Expire<TArgs> delegate(void (*NotifyMethod)(void*, TArgs&), Timestamp::TimeDiff expireMillisecs) |
210 | { |
211 | return Expire<TArgs>(FunctionDelegate<TArgs, true, false>(NotifyMethod), expireMillisecs); |
212 | } |
213 | |
214 | |
215 | template <class TArgs> |
216 | inline Expire<TArgs> delegate(void (*NotifyMethod)(TArgs&), Timestamp::TimeDiff expireMillisecs) |
217 | { |
218 | return Expire<TArgs>(FunctionDelegate<TArgs, false>(NotifyMethod), expireMillisecs); |
219 | } |
220 | |
221 | |
222 | template <class TArgs> |
223 | inline FunctionDelegate<TArgs, true, true> delegate(void (*NotifyMethod)(const void*, TArgs&)) |
224 | { |
225 | return FunctionDelegate<TArgs, true, true>(NotifyMethod); |
226 | } |
227 | |
228 | |
229 | template <class TArgs> |
230 | inline FunctionDelegate<TArgs, true, false> delegate(void (*NotifyMethod)(void*, TArgs&)) |
231 | { |
232 | return FunctionDelegate<TArgs, true, false>(NotifyMethod); |
233 | } |
234 | |
235 | |
236 | template <class TArgs> |
237 | inline FunctionDelegate<TArgs, false> delegate(void (*NotifyMethod)(TArgs&)) |
238 | { |
239 | return FunctionDelegate<TArgs, false>(NotifyMethod); |
240 | } |
241 | |
242 | |
243 | template <class TObj> |
244 | class Delegate<TObj,void,true>: public AbstractDelegate<void> |
245 | { |
246 | public: |
247 | typedef void (TObj::*NotifyMethod)(const void*); |
248 | |
249 | Delegate(TObj* obj, NotifyMethod method): |
250 | _receiverObject(obj), |
251 | _receiverMethod(method) |
252 | { |
253 | } |
254 | |
255 | Delegate(const Delegate& delegate): |
256 | AbstractDelegate<void>(delegate), |
257 | _receiverObject(delegate._receiverObject), |
258 | _receiverMethod(delegate._receiverMethod) |
259 | { |
260 | } |
261 | |
262 | ~Delegate() |
263 | { |
264 | } |
265 | |
266 | Delegate& operator = (const Delegate& delegate) |
267 | { |
268 | if (&delegate != this) |
269 | { |
270 | this->_receiverObject = delegate._receiverObject; |
271 | this->_receiverMethod = delegate._receiverMethod; |
272 | } |
273 | return *this; |
274 | } |
275 | |
276 | bool notify(const void* sender) |
277 | { |
278 | Mutex::ScopedLock lock(_mutex); |
279 | if (_receiverObject) |
280 | { |
281 | (_receiverObject->*_receiverMethod)(sender); |
282 | return true; |
283 | } |
284 | else return false; |
285 | } |
286 | |
287 | bool equals(const AbstractDelegate<void>& other) const |
288 | { |
289 | const Delegate* pOtherDelegate = dynamic_cast<const Delegate*>(other.unwrap()); |
290 | return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod; |
291 | } |
292 | |
293 | AbstractDelegate<void>* clone() const |
294 | { |
295 | return new Delegate(*this); |
296 | } |
297 | |
298 | void disable() |
299 | { |
300 | Mutex::ScopedLock lock(_mutex); |
301 | _receiverObject = 0; |
302 | } |
303 | |
304 | protected: |
305 | TObj* _receiverObject; |
306 | NotifyMethod _receiverMethod; |
307 | Mutex _mutex; |
308 | |
309 | private: |
310 | Delegate(); |
311 | }; |
312 | |
313 | |
314 | template <class TObj> |
315 | class Delegate<TObj, void, false>: public AbstractDelegate<void> |
316 | { |
317 | public: |
318 | typedef void (TObj::*NotifyMethod)(); |
319 | |
320 | Delegate(TObj* obj, NotifyMethod method): |
321 | _receiverObject(obj), |
322 | _receiverMethod(method) |
323 | { |
324 | } |
325 | |
326 | Delegate(const Delegate& delegate): |
327 | AbstractDelegate<void>(delegate), |
328 | _receiverObject(delegate._receiverObject), |
329 | _receiverMethod(delegate._receiverMethod) |
330 | { |
331 | } |
332 | |
333 | ~Delegate() |
334 | { |
335 | } |
336 | |
337 | Delegate& operator = (const Delegate& delegate) |
338 | { |
339 | if (&delegate != this) |
340 | { |
341 | this->_receiverObject = delegate._receiverObject; |
342 | this->_receiverMethod = delegate._receiverMethod; |
343 | } |
344 | return *this; |
345 | } |
346 | |
347 | bool notify(const void*) |
348 | { |
349 | Mutex::ScopedLock lock(_mutex); |
350 | if (_receiverObject) |
351 | { |
352 | (_receiverObject->*_receiverMethod)(); |
353 | return true; |
354 | } |
355 | else return false; |
356 | } |
357 | |
358 | bool equals(const AbstractDelegate<void>& other) const |
359 | { |
360 | const Delegate* pOtherDelegate = dynamic_cast<const Delegate*>(other.unwrap()); |
361 | return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod; |
362 | } |
363 | |
364 | AbstractDelegate<void>* clone() const |
365 | { |
366 | return new Delegate(*this); |
367 | } |
368 | |
369 | void disable() |
370 | { |
371 | Mutex::ScopedLock lock(_mutex); |
372 | _receiverObject = 0; |
373 | } |
374 | |
375 | protected: |
376 | TObj* _receiverObject; |
377 | NotifyMethod _receiverMethod; |
378 | Mutex _mutex; |
379 | |
380 | private: |
381 | Delegate(); |
382 | }; |
383 | |
384 | |
385 | template <class TObj> |
386 | inline Delegate<TObj, void, true> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*)) |
387 | { |
388 | return Delegate<TObj, void, true>(pObj, NotifyMethod); |
389 | } |
390 | |
391 | |
392 | template <class TObj> |
393 | inline Delegate<TObj, void, false> delegate(TObj* pObj, void (TObj::*NotifyMethod)()) |
394 | { |
395 | return Delegate<TObj, void, false>(pObj, NotifyMethod); |
396 | } |
397 | |
398 | |
399 | template <class TObj> |
400 | inline Expire<void> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*), Timestamp::TimeDiff expireMillisecs) |
401 | { |
402 | return Expire<void>(Delegate<TObj, void, true>(pObj, NotifyMethod), expireMillisecs); |
403 | } |
404 | |
405 | |
406 | template <class TObj> |
407 | inline Expire<void> delegate(TObj* pObj, void (TObj::*NotifyMethod)(), Timestamp::TimeDiff expireMillisecs) |
408 | { |
409 | return Expire<void>(Delegate<TObj, void, false>(pObj, NotifyMethod), expireMillisecs); |
410 | } |
411 | |
412 | |
413 | inline Expire<void> delegate(void (*NotifyMethod)(const void*), Timestamp::TimeDiff expireMillisecs) |
414 | { |
415 | return Expire<void>(FunctionDelegate<void, true, true>(NotifyMethod), expireMillisecs); |
416 | } |
417 | |
418 | |
419 | inline Expire<void> delegate(void (*NotifyMethod)(void*), Timestamp::TimeDiff expireMillisecs) |
420 | { |
421 | return Expire<void>(FunctionDelegate<void, true, false>(NotifyMethod), expireMillisecs); |
422 | } |
423 | |
424 | |
425 | inline Expire<void> delegate(void (*NotifyMethod)(), Timestamp::TimeDiff expireMillisecs) |
426 | { |
427 | return Expire<void>(FunctionDelegate<void, false>(NotifyMethod), expireMillisecs); |
428 | } |
429 | |
430 | |
431 | inline FunctionDelegate<void, true, true> delegate(void (*NotifyMethod)(const void*)) |
432 | { |
433 | return FunctionDelegate<void, true, true>(NotifyMethod); |
434 | } |
435 | |
436 | |
437 | inline FunctionDelegate<void, true, false> delegate(void (*NotifyMethod)(void*)) |
438 | { |
439 | return FunctionDelegate<void, true, false>(NotifyMethod); |
440 | } |
441 | |
442 | |
443 | inline FunctionDelegate<void, false> delegate(void (*NotifyMethod)()) |
444 | { |
445 | return FunctionDelegate<void, false>(NotifyMethod); |
446 | } |
447 | |
448 | |
449 | } // namespace Poco |
450 | |
451 | |
452 | #endif // Foundation_Delegate_INCLUDED |
453 | |