OLD | NEW |
| (Empty) |
1 // Copyright 2003-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // sta_call.h generics for cross apartment calling. | |
17 // | |
18 // The code is using compile-time and run-time polymorphism to create | |
19 // type-safe call wrappers that can be used to cross call from a | |
20 // worker thread to an STA thread. The current implementation only | |
21 // supports calling the main STA. | |
22 // | |
23 // Functions as well as object methods can be called. | |
24 // | |
25 // Examples: | |
26 // class X { | |
27 // public: | |
28 // int Add(int i, int j) { return i + j; } | |
29 // }; | |
30 // | |
31 // | |
32 // namespace { | |
33 // int Add(long i, long j) { return i + j; } | |
34 // } | |
35 // | |
36 // X x; | |
37 // int sum = CallMethod(&x, X::Add, 10, 20); | |
38 // int j = CallFunction(Add, -10, 10); | |
39 // | |
40 // The central piece of machinery is a hierarchy of functors. A functor is | |
41 // instantiated by a function template (CallFunction or CallMethod) and its | |
42 // 'Invoke' method gets called. | |
43 // Calling 'Invoke' will send the functor using 'SendMessage' | |
44 // to a window. The window message handler picks up the functor and | |
45 // calls the functor virtual operator(). | |
46 // This virtual call is what actually calls the specified function or the | |
47 // method, the only difference being that the call is now made in a thread | |
48 // different than the thread that called 'Invoke'. There is a partial | |
49 // specialization of the templates for void, so that void type is supported | |
50 // as a return type. | |
51 // | |
52 // | |
53 // !!! Limitations !!! | |
54 // | |
55 // There are a few important design and implementation limitations. They are | |
56 // mostly related to template parameters ambiguities (T or T&) especially | |
57 // for overloaded names or const types. The limitations are significant although | |
58 // the code is useful enough as it is in most of the cases. | |
59 // However, when using the code it is frustrating to discover that it does not | |
60 // compile for obvious and useful cases, a constant reminder that a better | |
61 // solution is to be seeked. | |
62 // | |
63 // | |
64 // The implementation does not support calling all 'stdcall' calling convention. | |
65 // | |
66 // The design does not support calling functions or methods that use pass by | |
67 // reference arguments: f(std::string&) . | |
68 // | |
69 // The design does not support well calling functions or methods that take | |
70 // pointer to const types parameters : f(const std::string*) . | |
71 // | |
72 // The implementation does not support calling methods of const objects. | |
73 // | |
74 // To reduce the number of templates that get instantiated, the types of the | |
75 // arguments of the call must match exactly the types of parameters of the | |
76 // function or method . In some cases static_casts mey be required | |
77 // at the point of the call. Example: CallMethod(f, static_cast<long>(10)); | |
78 | |
79 #ifndef OMAHA_COMMON_STA_CALL_H__ | |
80 #define OMAHA_COMMON_STA_CALL_H__ | |
81 | |
82 #include "base/scoped_ptr.h" | |
83 #include "omaha/base/debug.h" | |
84 #include "omaha/base/logging.h" | |
85 | |
86 namespace omaha { | |
87 | |
88 // C4347: 'function template' is called instead of 'function' | |
89 #pragma warning(disable : 4347) | |
90 | |
91 // The Base Functor is the base of the functor hierarchy. | |
92 class BaseFunctor { | |
93 public: | |
94 explicit BaseFunctor(bool is_async) : | |
95 thread_id_(::GetCurrentThreadId()), | |
96 is_async_(is_async) { | |
97 CORE_LOG(L6, (_T("[BaseFunctor::BaseFunctor]"))); | |
98 } | |
99 | |
100 // Functors are polymorphic objects. | |
101 virtual ~BaseFunctor() { | |
102 CORE_LOG(L6, (_T("[BaseFunctor::~BaseFunctor]"))); | |
103 } | |
104 | |
105 // Abstract virtual function call operator. This is always called | |
106 // in the callee thread by the dispatcher of the apartment. | |
107 virtual void operator()(void* presult) = 0; | |
108 | |
109 // The thread id of the calling thread. | |
110 DWORD thread_id() const { return thread_id_; } | |
111 | |
112 bool is_async() const { return is_async_; } | |
113 | |
114 protected: | |
115 | |
116 // Invoke is called by each of the derived functors. This is how | |
117 // the cross thread invocation is made and the result of the invocation | |
118 // is retrieved. Invoke is always called in the caller thread. | |
119 template <typename R> | |
120 R Invoke() { | |
121 R r = R(); // ensure r is initialized even for primitive types. | |
122 if (!is_async_) { | |
123 DoInvoke(&r); | |
124 } else { | |
125 // We handle the async calls as if the call returns void. | |
126 DoInvoke(0); | |
127 } | |
128 return r; | |
129 } | |
130 | |
131 // non-template method to be called by the derived functors | |
132 // specialized for void. | |
133 void Invoke() { | |
134 // When the argument of the invocation is 0, we are not | |
135 // interested in the result. | |
136 DoInvoke(0); | |
137 } | |
138 | |
139 private: | |
140 void DoInvoke(void* presult); // Does the actual invocation. | |
141 DWORD thread_id_; // The thread id of the calling thread. | |
142 bool is_async_; // True for async calls. | |
143 | |
144 DISALLOW_EVIL_CONSTRUCTORS(BaseFunctor); | |
145 }; | |
146 | |
147 // | |
148 // 0-ary method functor. | |
149 // | |
150 template <class T, typename R> | |
151 class MethodFunctor0 : public BaseFunctor { | |
152 public: | |
153 MethodFunctor0(bool is_async, T* pt, R (T::*pm)()) : | |
154 BaseFunctor(is_async), pobj_(pt), pm_(pm) {} | |
155 | |
156 virtual void operator()(void* presult) { | |
157 ASSERT(pobj_, (_T("Null object."))); | |
158 if (presult) { | |
159 *static_cast<R*>(presult) = (pobj_->*pm_)(); | |
160 } else { | |
161 (pobj_->*pm_)(); | |
162 } | |
163 } | |
164 | |
165 R Invoke() { | |
166 // Don't forget to call the base implementation. | |
167 return BaseFunctor::Invoke<R>(); | |
168 } | |
169 | |
170 private: | |
171 T* pobj_; | |
172 R (T::*pm_)(); | |
173 }; | |
174 | |
175 // | |
176 // 0-ary partial specialization for void return types. | |
177 // | |
178 template <class T> | |
179 class MethodFunctor0<T, void> : public BaseFunctor { | |
180 public: | |
181 MethodFunctor0(bool is_async, T* pt, void (T::*pm)()) : | |
182 BaseFunctor(is_async), pobj_(pt), pm_(pm) {} | |
183 | |
184 virtual void operator()(void* presult) { | |
185 ASSERT(pobj_, (_T("Null object."))); | |
186 ASSERT1(!presult); | |
187 presult; // unreferenced formal parameter | |
188 | |
189 // the actual call. There is no return value when the return type is void. | |
190 (pobj_->*pm_)(); | |
191 } | |
192 | |
193 // Bring in the name from the Base | |
194 using BaseFunctor::Invoke; | |
195 | |
196 private: | |
197 T* pobj_; | |
198 void (T::*pm_)(); | |
199 }; | |
200 | |
201 // | |
202 // 0-ary functor and specialization for void. | |
203 // | |
204 template <typename R> | |
205 class Functor0 : public BaseFunctor { | |
206 public: | |
207 Functor0(bool is_async, R (*pf)()) : | |
208 BaseFunctor(is_async), pf_(pf) {} | |
209 | |
210 virtual void operator()(void* presult) { | |
211 if (presult) { | |
212 *static_cast<R*>(presult) = (*pf_)(); | |
213 } else { | |
214 (*pf_)(); | |
215 } | |
216 } | |
217 | |
218 R Invoke() { | |
219 return BaseFunctor::Invoke<R>(); | |
220 } | |
221 | |
222 private: | |
223 R (*pf_)(); | |
224 }; | |
225 | |
226 template <> | |
227 class Functor0<void> : public BaseFunctor { | |
228 public: | |
229 Functor0(bool is_async, void (*pf)()) : | |
230 BaseFunctor(is_async), pf_(pf) {} | |
231 | |
232 virtual void operator()(void* presult) { | |
233 ASSERT1(!presult); | |
234 presult; // unreferenced formal parameter | |
235 | |
236 (*pf_)(); | |
237 } | |
238 | |
239 using BaseFunctor::Invoke; | |
240 | |
241 private: | |
242 void (*pf_)(); | |
243 }; | |
244 | |
245 | |
246 // | |
247 // 1-ary | |
248 // | |
249 template <class T, typename R, typename P> | |
250 class MethodFunctor1 : public BaseFunctor { | |
251 public: | |
252 MethodFunctor1(bool is_async, T* pt, R (T::*pm)(P), P p) : | |
253 BaseFunctor(is_async), pobj_(pt), pm_(pm), p_(p) {} | |
254 | |
255 virtual void operator()(void* presult) { | |
256 ASSERT(pobj_, (_T("Null object."))); | |
257 if (presult) { | |
258 *static_cast<R*>(presult) = (pobj_->*pm_)(p_); | |
259 } else { | |
260 (pobj_->*pm_)(p_); | |
261 } | |
262 } | |
263 | |
264 R Invoke() { | |
265 return BaseFunctor::Invoke<R>(); | |
266 } | |
267 | |
268 private: | |
269 T* pobj_; | |
270 R (T::*pm_)(P); | |
271 P p_; | |
272 }; | |
273 | |
274 template <class T, typename P> | |
275 class MethodFunctor1<T, void, P> : public BaseFunctor { | |
276 public: | |
277 MethodFunctor1(bool is_async, T* pt, void (T::*pm)(P), P p) : | |
278 BaseFunctor(is_async), pobj_(pt), pm_(pm), p_(p) {} | |
279 | |
280 virtual void operator()(void* presult) { | |
281 ASSERT(pobj_, (_T("Null object."))); | |
282 ASSERT1(!presult); | |
283 presult; // unreferenced formal parameter | |
284 | |
285 (pobj_->*pm_)(p_); | |
286 } | |
287 | |
288 using BaseFunctor::Invoke; | |
289 | |
290 private: | |
291 T* pobj_; | |
292 void (T::*pm_)(P); | |
293 P p_; | |
294 }; | |
295 | |
296 template <typename R, typename P1> | |
297 class Functor1 : public BaseFunctor { | |
298 public: | |
299 Functor1(bool is_async, R (*pf)(P1), P1 p1) : | |
300 BaseFunctor(is_async), pf_(pf), p1_(p1) {} | |
301 | |
302 virtual void operator()(void* presult) { | |
303 if (presult) { | |
304 *static_cast<R*>(presult) = (*pf_)(p1_); | |
305 } else { | |
306 (*pf_)(p1_); | |
307 } | |
308 } | |
309 | |
310 R Invoke() { | |
311 return BaseFunctor::Invoke<R>(); | |
312 } | |
313 | |
314 private: | |
315 R (*pf_)(P1); | |
316 P1 p1_; | |
317 }; | |
318 | |
319 template <typename P1> | |
320 class Functor1<void, P1> : public BaseFunctor { | |
321 public: | |
322 Functor1(bool is_async, void (*pf)(P1), P1 p1) : | |
323 BaseFunctor(is_async), pf_(pf), p1_(p1) {} | |
324 | |
325 virtual void operator()(void* presult) { | |
326 ASSERT1(!presult); | |
327 presult; // unreferenced formal parameter | |
328 | |
329 (*pf_)(p1_); | |
330 } | |
331 | |
332 using BaseFunctor::Invoke; | |
333 | |
334 private: | |
335 void (*pf_)(P1); | |
336 P1 p1_; | |
337 }; | |
338 | |
339 | |
340 // | |
341 // 2-ary | |
342 // | |
343 template <class T, typename R, typename P1, typename P2> | |
344 class MethodFunctor2 : public BaseFunctor { | |
345 public: | |
346 MethodFunctor2(bool is_async, T* pt, R (T::*pm)(P1, P2), P1 p1, P2 p2) : | |
347 BaseFunctor(is_async), pobj_(pt), pm_(pm), p1_(p1), p2_(p2) {} | |
348 | |
349 virtual void operator()(void* presult) { | |
350 ASSERT(pobj_, (_T("Null object."))); | |
351 if (presult) { | |
352 *static_cast<R*>(presult) = (pobj_->*pm_)(p1_, p2_); | |
353 } else { | |
354 (pobj_->*pm_)(p1_, p2_); | |
355 } | |
356 } | |
357 | |
358 R Invoke() { | |
359 return BaseFunctor::Invoke<R>(); | |
360 } | |
361 | |
362 private: | |
363 T* pobj_; | |
364 R (T::*pm_)(P1, P2); | |
365 P1 p1_; | |
366 P2 p2_; | |
367 }; | |
368 | |
369 template <class T, typename P1, typename P2> | |
370 class MethodFunctor2<T, void, P1, P2> : public BaseFunctor { | |
371 public: | |
372 MethodFunctor2(bool is_async, T* pt, void (T::*pm)(P1, P2), P1 p1, P2 p2) : | |
373 BaseFunctor(is_async), pobj_(pt), pm_(pm), p1_(p1), p2_(p2) {} | |
374 | |
375 virtual void operator()(void* presult) { | |
376 ASSERT(pobj_, (_T("Null object."))); | |
377 ASSERT1(!presult); | |
378 presult; // unreferenced formal parameter | |
379 | |
380 (pobj_->*pm_)(p1_, p2_); | |
381 } | |
382 | |
383 using BaseFunctor::Invoke; | |
384 | |
385 private: | |
386 T* pobj_; | |
387 void (T::*pm_)(P1, P2); | |
388 P1 p1_; | |
389 P2 p2_; | |
390 }; | |
391 | |
392 template <typename R, typename P1, typename P2> | |
393 class Functor2 : public BaseFunctor { | |
394 public: | |
395 Functor2(bool is_async, R (*pf)(P1, P2), P1 p1, P2 p2) : | |
396 BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2) {} | |
397 | |
398 virtual void operator()(void* presult) { | |
399 if (presult) { | |
400 *static_cast<R*>(presult) = pf_(p1_, p2_); | |
401 } else { | |
402 pf_(p1_, p2_); | |
403 } | |
404 } | |
405 | |
406 R Invoke() { | |
407 return BaseFunctor::Invoke<R>(); | |
408 } | |
409 | |
410 private: | |
411 R (*pf_)(P1, P2); | |
412 P1 p1_; | |
413 P2 p2_; | |
414 }; | |
415 | |
416 template <typename P1, typename P2> | |
417 class Functor2<void, P1, P2> : public BaseFunctor { | |
418 public: | |
419 Functor2(bool is_async, void (*pf)(P1, P2), P1 p1, P2 p2) : | |
420 BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2) {} | |
421 | |
422 virtual void operator()(void* presult) { | |
423 ASSERT1(!presult); | |
424 presult; // unreferenced formal parameter | |
425 | |
426 (*pf_)(p1_, p2_); | |
427 } | |
428 | |
429 using BaseFunctor::Invoke; | |
430 | |
431 private: | |
432 void (*pf_)(P1, P2); | |
433 P1 p1_; | |
434 P2 p2_; | |
435 }; | |
436 | |
437 // | |
438 // 3-ary | |
439 // | |
440 template <class T, typename R, typename P1, typename P2, typename P3> | |
441 class MethodFunctor3 : public BaseFunctor { | |
442 public: | |
443 MethodFunctor3(bool is_async, | |
444 T* pt, | |
445 R (T::*pm)(P1, P2, P3), | |
446 P1 p1, | |
447 P2 p2, | |
448 P3 p3) : | |
449 BaseFunctor(is_async), pobj_(pt), pm_(pm), p1_(p1), p2_(p2), p3_(p3) {} | |
450 | |
451 virtual void operator()(void* presult) { | |
452 ASSERT(pobj_, (_T("Null object."))); | |
453 if (presult) { | |
454 *static_cast<R*>(presult) = (pobj_->*pm_)(p1_, p2_, p3_); | |
455 } else { | |
456 (pobj_->*pm_)(p1_, p2_, p3_); | |
457 } | |
458 } | |
459 | |
460 R Invoke() { | |
461 return BaseFunctor::Invoke<R>(); | |
462 } | |
463 | |
464 private: | |
465 T* pobj_; | |
466 R (T::*pm_)(P1, P2, P3); | |
467 P1 p1_; | |
468 P2 p2_; | |
469 P3 p3_; | |
470 }; | |
471 | |
472 template <class T, typename P1, typename P2, typename P3> | |
473 class MethodFunctor3<T, void, P1, P2, P3> : public BaseFunctor { | |
474 public: | |
475 MethodFunctor3(bool is_async, | |
476 T* pt, | |
477 void (T::*pm)(P1, P2, P3), | |
478 P1 p1, | |
479 P2 p2, | |
480 P3 p3) : | |
481 BaseFunctor(is_async), pobj_(pt), pm_(pm), p1_(p1), p2_(p2), p3_(p3) {} | |
482 | |
483 virtual void operator()(void* presult) { | |
484 ASSERT(pobj_, (_T("Null object."))); | |
485 ASSERT1(!presult); | |
486 presult; // unreferenced formal parameter | |
487 | |
488 (pobj_->*pm_)(p1_, p2_, p3_); | |
489 } | |
490 | |
491 using BaseFunctor::Invoke; | |
492 | |
493 private: | |
494 T* pobj_; | |
495 void (T::*pm_)(P1, P2, P3); | |
496 P1 p1_; | |
497 P2 p2_; | |
498 P3 p3_; | |
499 }; | |
500 | |
501 | |
502 template <typename R, typename P1, typename P2, typename P3> | |
503 class Functor3 : public BaseFunctor { | |
504 public: | |
505 Functor3(bool is_async, R (*pf)(P1, P2, P3), P1 p1, P2 p2, P3 p3) : | |
506 BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2), p3_(p3) {} | |
507 virtual void operator()(void* presult) { | |
508 if (presult) { | |
509 *static_cast<R*>(presult) = (*pf_)(p1_, p2_, p3_); | |
510 } else { | |
511 (*pf_)(p1_, p2_, p3_); | |
512 } | |
513 } | |
514 | |
515 R Invoke() { | |
516 return BaseFunctor::Invoke<R>(); | |
517 } | |
518 | |
519 private: | |
520 R (*pf_)(P1, P2, P3); | |
521 P1 p1_; | |
522 P2 p2_; | |
523 P3 p3_; | |
524 }; | |
525 | |
526 template <typename P1, typename P2, typename P3> | |
527 class Functor3<void, P1, P2, P3> : public BaseFunctor { | |
528 public: | |
529 Functor3(bool is_async, void (*pf)(P1, P2, P3), P1 p1, P2 p2, P3 p3) : | |
530 BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2), p3_(p3) {} | |
531 | |
532 virtual void operator()(void* presult) { | |
533 ASSERT1(!presult); | |
534 presult; // unreferenced formal parameter | |
535 | |
536 (*pf_)(p1_, p2_, p3_); | |
537 } | |
538 | |
539 using BaseFunctor::Invoke; | |
540 | |
541 private: | |
542 void (*pf_)(P1, P2, P3); | |
543 P1 p1_; | |
544 P2 p2_; | |
545 P3 p3_; | |
546 }; | |
547 | |
548 // | |
549 // 4-ary | |
550 // | |
551 template <class T, | |
552 typename R, | |
553 typename P1, | |
554 typename P2, | |
555 typename P3, | |
556 typename P4> | |
557 class MethodFunctor4 : public BaseFunctor { | |
558 public: | |
559 MethodFunctor4(bool is_async, | |
560 T* pt, | |
561 R (T::*pm)(P1, P2, P3, P4), | |
562 P1 p1, | |
563 P2 p2, | |
564 P3 p3, | |
565 P4 p4) : | |
566 BaseFunctor(is_async), | |
567 pobj_(pt), | |
568 pm_(pm), | |
569 p1_(p1), | |
570 p2_(p2), | |
571 p3_(p3), | |
572 p4_(p4) {} | |
573 | |
574 virtual void operator()(void* presult) { | |
575 ASSERT(pobj_, (_T("Null object."))); | |
576 if (presult) { | |
577 *static_cast<R*>(presult) = (pobj_->*pm_)(p1_, p2_, p3_, p4_); | |
578 } else { | |
579 (pobj_->*pm_)(p1_, p2_, p3_, p4_); | |
580 } | |
581 } | |
582 | |
583 R Invoke() { | |
584 return BaseFunctor::Invoke<R>(); | |
585 } | |
586 | |
587 private: | |
588 T* pobj_; | |
589 R (T::*pm_)(P1, P2, P3, P4); | |
590 P1 p1_; | |
591 P2 p2_; | |
592 P3 p3_; | |
593 P4 p4_; | |
594 }; | |
595 | |
596 template <class T, typename P1, typename P2, typename P3, typename P4> | |
597 class MethodFunctor4<T, void, P1, P2, P3, P4> : public BaseFunctor { | |
598 public: | |
599 MethodFunctor4(bool is_async, | |
600 T* pt, | |
601 void (T::*pm)(P1, P2, P3, P4), | |
602 P1 p1, | |
603 P2 p2, | |
604 P3 p3, | |
605 P4 p4) : | |
606 BaseFunctor(is_async), | |
607 pobj_(pt), | |
608 pm_(pm), | |
609 p1_(p1), | |
610 p2_(p2), | |
611 p3_(p3), | |
612 p4_(p4) {} | |
613 | |
614 virtual void operator()(void* presult) { | |
615 ASSERT(pobj_, (_T("Null object."))); | |
616 ASSERT1(!presult); | |
617 presult; // unreferenced formal parameter | |
618 | |
619 (pobj_->*pm_)(p1_, p2_, p3_, p4_); | |
620 } | |
621 | |
622 using BaseFunctor::Invoke; | |
623 | |
624 private: | |
625 T* pobj_; | |
626 void (T::*pm_)(P1, P2, P3, P4); | |
627 P1 p1_; | |
628 P2 p2_; | |
629 P3 p3_; | |
630 P4 p4_; | |
631 }; | |
632 | |
633 | |
634 template <typename R, typename P1, typename P2, typename P3, typename P4> | |
635 class Functor4 : public BaseFunctor { | |
636 public: | |
637 Functor4(bool is_async, R (*pf)(P1, P2, P3, P4), P1 p1, P2 p2, P3 p3, P4 p4) : | |
638 BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2), p3_(p3), p4_(p4) {} | |
639 | |
640 virtual void operator()(void* presult) { | |
641 if (presult) { | |
642 *static_cast<R*>(presult) = (*pf_)(p1_, p2_, p3_, p4_); | |
643 } else { | |
644 (*pf_)(p1_, p2_, p3_, p4_); | |
645 } | |
646 } | |
647 | |
648 R Invoke() { | |
649 return BaseFunctor::Invoke<R>(); | |
650 } | |
651 | |
652 private: | |
653 R (*pf_)(P1, P2, P3, P4); | |
654 P1 p1_; | |
655 P2 p2_; | |
656 P3 p3_; | |
657 P4 p4_; | |
658 }; | |
659 | |
660 template <typename P1, typename P2, typename P3, typename P4> | |
661 class Functor4<void, P1, P2, P3, P4> : public BaseFunctor { | |
662 public: | |
663 Functor4(bool is_async, | |
664 void (*pf)(P1, P2, P3, P4), | |
665 P1 p1, | |
666 P2 p2, | |
667 P3 p3, | |
668 P4 p4) : | |
669 BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2), p3_(p3), p4_(p4) {} | |
670 | |
671 virtual void operator()(void* presult) { | |
672 ASSERT1(!presult); | |
673 presult; // unreferenced formal parameter | |
674 | |
675 (*pf_)(p1_, p2_, p3_, p4_); | |
676 } | |
677 | |
678 using BaseFunctor::Invoke; | |
679 | |
680 private: | |
681 void (*pf_)(P1, P2, P3, P4); | |
682 P1 p1_; | |
683 P2 p2_; | |
684 P3 p3_; | |
685 P4 p4_; | |
686 }; | |
687 | |
688 // | |
689 // 5-ary | |
690 // | |
691 template <class T, | |
692 typename R, | |
693 typename P1, | |
694 typename P2, | |
695 typename P3, | |
696 typename P4, | |
697 typename P5> | |
698 class MethodFunctor5 : public BaseFunctor { | |
699 public: | |
700 MethodFunctor5(bool is_async, | |
701 T* pt, | |
702 R (T::*pm)(P1, P2, P3, P4, P5), | |
703 P1 p1, | |
704 P2 p2, | |
705 P3 p3, | |
706 P4 p4, | |
707 P5 p5) : | |
708 BaseFunctor(is_async), | |
709 pobj_(pt), | |
710 pm_(pm), | |
711 p1_(p1), | |
712 p2_(p2), | |
713 p3_(p3), | |
714 p4_(p4), | |
715 p5_(p5) {} | |
716 | |
717 virtual void operator()(void* presult) { | |
718 ASSERT(pobj_, (_T("Null object."))); | |
719 if (presult) { | |
720 *static_cast<R*>(presult) = (pobj_->*pm_)(p1_, p2_, p3_, p4_, p5_); | |
721 } else { | |
722 (pobj_->*pm_)(p1_, p2_, p3_, p4_, p5_); | |
723 } | |
724 } | |
725 | |
726 R Invoke() { | |
727 return BaseFunctor::Invoke<R>(); | |
728 } | |
729 | |
730 private: | |
731 T* pobj_; | |
732 R (T::*pm_)(P1, P2, P3, P4, P5); | |
733 P1 p1_; | |
734 P2 p2_; | |
735 P3 p3_; | |
736 P4 p4_; | |
737 P5 p5_; | |
738 }; | |
739 | |
740 template <class T, | |
741 typename P1, | |
742 typename P2, | |
743 typename P3, | |
744 typename P4, | |
745 typename P5> | |
746 class MethodFunctor5<T, void, P1, P2, P3, P4, P5> : public BaseFunctor { | |
747 public: | |
748 MethodFunctor5(bool is_async, | |
749 T* pt, | |
750 void (T::*pm)(P1, P2, P3, P4, P5), | |
751 P1 p1, | |
752 P2 p2, | |
753 P3 p3, | |
754 P4 p4, | |
755 P5 p5) : | |
756 BaseFunctor(is_async), | |
757 pobj_(pt), | |
758 pm_(pm), | |
759 p1_(p1), | |
760 p2_(p2), | |
761 p3_(p3), | |
762 p4_(p4), | |
763 p5_(p5) {} | |
764 | |
765 virtual void operator()(void* presult) { | |
766 ASSERT(pobj_, (_T("Null object."))); | |
767 ASSERT1(!presult); | |
768 presult; // unreferenced formal parameter | |
769 | |
770 (pobj_->*pm_)(p1_, p2_, p3_, p4_, p5_); | |
771 } | |
772 | |
773 using BaseFunctor::Invoke; | |
774 | |
775 private: | |
776 T* pobj_; | |
777 void (T::*pm_)(P1, P2, P3, P4, P5); | |
778 P1 p1_; | |
779 P2 p2_; | |
780 P3 p3_; | |
781 P4 p4_; | |
782 P5 p5_; | |
783 }; | |
784 | |
785 template <typename R, | |
786 typename P1, | |
787 typename P2, | |
788 typename P3, | |
789 typename P4, | |
790 typename P5> | |
791 class Functor5 : public BaseFunctor { | |
792 public: | |
793 Functor5(bool is_async, | |
794 R (*pf)(P1, P2, P3, P4, P5), | |
795 P1 p1, | |
796 P2 p2, | |
797 P3 p3, | |
798 P4 p4, | |
799 P5 p5) : | |
800 BaseFunctor(is_async), | |
801 pf_(pf), | |
802 p1_(p1), | |
803 p2_(p2), | |
804 p3_(p3), | |
805 p4_(p4), | |
806 p5_(p5) {} | |
807 virtual void operator()(void* presult) { | |
808 if (presult) { | |
809 *static_cast<R*>(presult) = (*pf_)(p1_, p2_, p3_, p4_, p5_); | |
810 } else { | |
811 (*pf_)(p1_, p2_, p3_, p4_, p5_); | |
812 } | |
813 } | |
814 | |
815 R Invoke() { | |
816 return BaseFunctor::Invoke<R>(); | |
817 } | |
818 | |
819 private: | |
820 R (*pf_)(P1, P2, P3, P4, P5); | |
821 P1 p1_; | |
822 P2 p2_; | |
823 P3 p3_; | |
824 P4 p4_; | |
825 P5 p5_; | |
826 }; | |
827 | |
828 template <typename P1, typename P2, typename P3, typename P4, typename P5> | |
829 class Functor5<void, P1, P2, P3, P4, P5> : public BaseFunctor { | |
830 public: | |
831 Functor5(bool is_async, | |
832 void (*pf)(P1, P2, P3, P4, P5), | |
833 P1 p1, | |
834 P2 p2, | |
835 P3 p3, | |
836 P4 p4, | |
837 P5 p5) : | |
838 BaseFunctor(is_async), | |
839 pf_(pf), | |
840 p1_(p1), | |
841 p2_(p2), | |
842 p3_(p3), | |
843 p4_(p4), | |
844 p5_(p5) {} | |
845 | |
846 virtual void operator()(void* presult) { | |
847 ASSERT1(!presult); | |
848 presult; // unreferenced formal parameter | |
849 | |
850 (*pf_)(p1_, p2_, p3_, p4_, p5_); | |
851 } | |
852 | |
853 using BaseFunctor::Invoke; | |
854 | |
855 private: | |
856 void (*pf_)(P1, P2, P3, P4, P5); | |
857 P1 p1_; | |
858 P2 p2_; | |
859 P3 p3_; | |
860 P4 p4_; | |
861 P5 p5_; | |
862 }; | |
863 | |
864 | |
865 // This is what the clients of the STA code instantiate and call. | |
866 // | |
867 // Synchronous Callers. | |
868 // | |
869 template <class T, typename R> | |
870 R CallMethod(T* object, R (T::*pm)()) { | |
871 return MethodFunctor0<T, R>(false, object, pm).Invoke(); | |
872 } | |
873 | |
874 template <typename R> | |
875 R CallFunction(R (*pf)()) { | |
876 return Functor0<R>(false, pf).Invoke(); | |
877 } | |
878 | |
879 template <class T, typename R, typename P> | |
880 R CallMethod(T* object, R (T::*pm)(P), P p) { | |
881 return MethodFunctor1<T, R, P>(false, object, pm, p).Invoke(); | |
882 } | |
883 | |
884 template <typename R, typename P> | |
885 R CallFunction(R (*pf)(P), P p) { | |
886 return Functor1<R, P>(false, pf, p).Invoke(); | |
887 } | |
888 | |
889 template <class T, typename R, typename P1, typename P2> | |
890 R CallMethod(T* object, R (T::*pm)(P1, P2), P1 p1, P2 p2) { | |
891 return MethodFunctor2<T, R, P1, P2>(false, object, pm, p1, p2).Invoke(); | |
892 } | |
893 | |
894 template <typename R, typename P1, typename P2> | |
895 R CallFunction(R (*pf)(P1, P2), P1 p1, P2 p2) { | |
896 return Functor2<R, P1, P2>(false, pf, p1, p2).Invoke(); | |
897 } | |
898 | |
899 template <class T, typename R, typename P1, typename P2, typename P3> | |
900 R CallMethod(T* object, R (T::*pm)(P1, P2, P3), P1 p1, P2 p2, P3 p3) { | |
901 return MethodFunctor3<T, R, P1, P2, P3>(false, | |
902 object, pm, p1, p2, p3).Invoke(); | |
903 } | |
904 | |
905 template <typename R, typename P1, typename P2, typename P3> | |
906 R CallFunction(R (*pf)(P1, P2, P3), P1 p1, P2 p2, P3 p3) { | |
907 return Functor3<R, P1, P2, P3>(false, pf, p1, p2, p3).Invoke(); | |
908 } | |
909 | |
910 template <class T, | |
911 typename R, | |
912 typename P1, | |
913 typename P2, | |
914 typename P3, | |
915 typename P4> | |
916 R CallMethod(T* object, | |
917 R (T::*pm)(P1, P2, P3, P4), | |
918 P1 p1, | |
919 P2 p2, | |
920 P3 p3, | |
921 P4 p4) { | |
922 return MethodFunctor4<T, R, P1, P2, P3, P4>(false, | |
923 object, | |
924 pm, | |
925 p1, | |
926 p2, | |
927 p3, | |
928 p4).Invoke(); | |
929 } | |
930 | |
931 template <typename R, typename P1, typename P2, typename P3, typename P4> | |
932 R CallFunction(R (*pf)(P1, P2, P3, P4), P1 p1, P2 p2, P3 p3, P4 p4) { | |
933 return Functor4<R, P1, P2, P3, P4>(false, pf, p1, p2, p3, p4).Invoke(); | |
934 } | |
935 | |
936 template <class T, | |
937 typename R, | |
938 typename P1, | |
939 typename P2, | |
940 typename P3, | |
941 typename P4, | |
942 typename P5> | |
943 R CallMethod(T* object, | |
944 R (T::*pm)(P1, P2, P3, P4, P5), | |
945 P1 p1, | |
946 P2 p2, | |
947 P3 p3, | |
948 P4 p4, | |
949 P5 p5) { | |
950 return MethodFunctor5<T, R, P1, P2, P3, P4, P5>(false, | |
951 object, | |
952 pm, | |
953 p1, | |
954 p2, | |
955 p3, | |
956 p4, | |
957 p5).Invoke(); | |
958 } | |
959 | |
960 template <typename R, | |
961 typename P1, | |
962 typename P2, | |
963 typename P3, | |
964 typename P4, | |
965 typename P5> | |
966 R CallFunction(R (*pf)(P1, P2, P3, P4, P5), P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { | |
967 return Functor5<R, P1, P2, P3, P4, P5>(false, | |
968 pf, | |
969 p1, | |
970 p2, | |
971 p3, | |
972 p4, | |
973 p5).Invoke(); | |
974 } | |
975 | |
976 // | |
977 // Asynchronous Callers. | |
978 // | |
979 template <class T, typename R> | |
980 void CallMethodAsync(T* object, R (T::*pm)()) { | |
981 scoped_ptr<MethodFunctor0<T, R> > fun( | |
982 new MethodFunctor0<T, R>(true, object, pm)); | |
983 fun->Invoke(); | |
984 fun.release(); | |
985 } | |
986 | |
987 template <typename R> | |
988 void CallFunctionAsync(R (*pf)()) { | |
989 scoped_ptr<Functor0<R> > fun(new Functor0<R>(true, pf)); | |
990 fun->Invoke(); | |
991 fun.release(); | |
992 } | |
993 | |
994 template <class T, typename R, typename P> | |
995 void CallMethodAsync(T* object, R (T::*pm)(P), P p) { | |
996 scoped_ptr<MethodFunctor1<T, R, P> > fun( | |
997 new MethodFunctor1<T, R, P>(true, object, pm, p)); | |
998 fun->Invoke(); | |
999 fun.release(); | |
1000 } | |
1001 | |
1002 template <typename R, typename P> | |
1003 void CallFunctionAsync(R (*pf)(P), P p) { | |
1004 scoped_ptr<Functor1<R, P> > fun(new Functor1<R, P>(true, pf, p)); | |
1005 fun->Invoke(); | |
1006 fun.release(); | |
1007 } | |
1008 | |
1009 template <class T, typename R, typename P1, typename P2> | |
1010 void CallMethodAsync(T* object, R (T::*pm)(P1, P2), P1 p1, P2 p2) { | |
1011 scoped_ptr<MethodFunctor2<T, R, P1, P2> > fun( | |
1012 new MethodFunctor2<T, R, P1, P2>(true, object, pm, p1, p2)); | |
1013 fun->Invoke(); | |
1014 fun.release(); | |
1015 } | |
1016 | |
1017 template <typename R, typename P1, typename P2> | |
1018 void CallFunctionAsync(R (*pf)(P1, P2), P1 p1, P2 p2) { | |
1019 scoped_ptr<Functor2<R, P1, P2> > fun( | |
1020 new Functor2<R, P1, P2>(true, pf, p1, p2)); | |
1021 fun->Invoke(); | |
1022 fun.release(); | |
1023 } | |
1024 | |
1025 template <class T, typename R, typename P1, typename P2, typename P3> | |
1026 void CallMethodAsync(T* object, R (T::*pm)(P1, P2, P3), P1 p1, P2 p2, P3 p3) { | |
1027 scoped_ptr<MethodFunctor3<T, R, P1, P2, P3> > fun( | |
1028 new MethodFunctor3<T, R, P1, P2, P3>(true, object, pm, p1, p2, p3)); | |
1029 fun->Invoke(); | |
1030 fun.release(); | |
1031 } | |
1032 | |
1033 template <typename R, typename P1, typename P2, typename P3> | |
1034 void CallFunctionAsync(R (*pf)(P1, P2, P3), P1 p1, P2 p2, P3 p3) { | |
1035 scoped_ptr<Functor3<R, P1, P2, P3> > fun( | |
1036 new Functor3<R, P1, P2, P3>(true, pf, p1, p2, p3)); | |
1037 fun->Invoke(); | |
1038 fun.release(); | |
1039 } | |
1040 | |
1041 template <class T, | |
1042 typename R, | |
1043 typename P1, | |
1044 typename P2, | |
1045 typename P3, | |
1046 typename P4> | |
1047 void CallMethodAsync(T* obj, | |
1048 R (T::*pm)(P1, P2, P3, P4), | |
1049 P1 p1, | |
1050 P2 p2, | |
1051 P3 p3, | |
1052 P4 p4) { | |
1053 scoped_ptr<MethodFunctor4<T, R, P1, P2, P3, P4> > fun( | |
1054 new MethodFunctor4<T, R, P1, P2, P3, P4>(true, obj, pm, p1, p2, p3, p4)); | |
1055 fun->Invoke(); | |
1056 fun.release(); | |
1057 } | |
1058 | |
1059 template <typename R, typename P1, typename P2, typename P3, typename P4> | |
1060 void CallFunctionAsync(R (*pf)(P1, P2, P3, P4), P1 p1, P2 p2, P3 p3, P4 p4) { | |
1061 scoped_ptr<Functor4<R, P1, P2, P3, P4> > fun( | |
1062 new Functor4<R, P1, P2, P3, P4>(true, pf, p1, p2, p3, p4)); | |
1063 fun->Invoke(); | |
1064 fun.release(); | |
1065 } | |
1066 | |
1067 template <class T, | |
1068 typename R, | |
1069 typename P1, | |
1070 typename P2, | |
1071 typename P3, | |
1072 typename P4, | |
1073 typename P5> | |
1074 void CallMethodAsync(T* object, | |
1075 R (T::*pm)(P1, P2, P3, P4, P5), | |
1076 P1 p1, | |
1077 P2 p2, | |
1078 P3 p3, | |
1079 P4 p4, | |
1080 P5 p5) { | |
1081 scoped_ptr<MethodFunctor5<T, R, P1, P2, P3, P4, P5> > fun( | |
1082 new MethodFunctor5<T, R, P1, P2, P3, P4, P5>(true, | |
1083 object, | |
1084 pm, | |
1085 p1, | |
1086 p2, | |
1087 p3, | |
1088 p4, | |
1089 p5)); | |
1090 fun->Invoke(); | |
1091 fun.release(); | |
1092 } | |
1093 | |
1094 template <typename R, | |
1095 typename P1, | |
1096 typename P2, | |
1097 typename P3, | |
1098 typename P4, | |
1099 typename P5> | |
1100 void CallFunctionAsync(R (*pf)(P1, P2, P3, P4, P5), | |
1101 P1 p1, | |
1102 P2 p2, | |
1103 P3 p3, | |
1104 P4 p4, | |
1105 P5 p5) { | |
1106 scoped_ptr<Functor5<R, P1, P2, P3, P4, P5> > fun( | |
1107 new Functor5<R, P1, P2, P3, P4, P5>(true, pf, p1, p2, p3, p4, p5)); | |
1108 fun->Invoke(); | |
1109 fun.release(); | |
1110 } | |
1111 | |
1112 #pragma warning(default : 4347) | |
1113 | |
1114 } // namespace omaha | |
1115 | |
1116 #endif // OMAHA_COMMON_STA_CALL_H__ | |
1117 | |
OLD | NEW |