// Copyright 2003-2009 Google Inc. | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// ======================================================================== | |
// | |
// sta_call.h generics for cross apartment calling. | |
// | |
// The code is using compile-time and run-time polymorphism to create | |
// type-safe call wrappers that can be used to cross call from a | |
// worker thread to an STA thread. The current implementation only | |
// supports calling the main STA. | |
// | |
// Functions as well as object methods can be called. | |
// | |
// Examples: | |
// class X { | |
// public: | |
// int Add(int i, int j) { return i + j; } | |
// }; | |
// | |
// | |
// namespace { | |
// int Add(long i, long j) { return i + j; } | |
// } | |
// | |
// X x; | |
// int sum = CallMethod(&x, X::Add, 10, 20); | |
// int j = CallFunction(Add, -10, 10); | |
// | |
// The central piece of machinery is a hierarchy of functors. A functor is | |
// instantiated by a function template (CallFunction or CallMethod) and its | |
// 'Invoke' method gets called. | |
// Calling 'Invoke' will send the functor using 'SendMessage' | |
// to a window. The window message handler picks up the functor and | |
// calls the functor virtual operator(). | |
// This virtual call is what actually calls the specified function or the | |
// method, the only difference being that the call is now made in a thread | |
// different than the thread that called 'Invoke'. There is a partial | |
// specialization of the templates for void, so that void type is supported | |
// as a return type. | |
// | |
// | |
// !!! Limitations !!! | |
// | |
// There are a few important design and implementation limitations. They are | |
// mostly related to template parameters ambiguities (T or T&) especially | |
// for overloaded names or const types. The limitations are significant although | |
// the code is useful enough as it is in most of the cases. | |
// However, when using the code it is frustrating to discover that it does not | |
// compile for obvious and useful cases, a constant reminder that a better | |
// solution is to be seeked. | |
// | |
// | |
// The implementation does not support calling all 'stdcall' calling convention. | |
// | |
// The design does not support calling functions or methods that use pass by | |
// reference arguments: f(std::string&) . | |
// | |
// The design does not support well calling functions or methods that take | |
// pointer to const types parameters : f(const std::string*) . | |
// | |
// The implementation does not support calling methods of const objects. | |
// | |
// To reduce the number of templates that get instantiated, the types of the | |
// arguments of the call must match exactly the types of parameters of the | |
// function or method . In some cases static_casts mey be required | |
// at the point of the call. Example: CallMethod(f, static_cast<long>(10)); | |
#ifndef OMAHA_COMMON_STA_CALL_H__ | |
#define OMAHA_COMMON_STA_CALL_H__ | |
#include "base/scoped_ptr.h" | |
#include "omaha/common/debug.h" | |
#include "omaha/common/logging.h" | |
namespace omaha { | |
// C4347: 'function template' is called instead of 'function' | |
#pragma warning(disable : 4347) | |
// The Base Functor is the base of the functor hierarchy. | |
class BaseFunctor { | |
public: | |
explicit BaseFunctor(bool is_async) : | |
thread_id_(::GetCurrentThreadId()), | |
is_async_(is_async) { | |
CORE_LOG(L6, (_T("[BaseFunctor::BaseFunctor]"))); | |
} | |
// Functors are polymorphic objects. | |
virtual ~BaseFunctor() { | |
CORE_LOG(L6, (_T("[BaseFunctor::~BaseFunctor]"))); | |
} | |
// Abstract virtual function call operator. This is always called | |
// in the callee thread by the dispatcher of the apartment. | |
virtual void operator()(void* presult) = 0; | |
// The thread id of the calling thread. | |
DWORD thread_id() const { return thread_id_; } | |
bool is_async() const { return is_async_; } | |
protected: | |
// Invoke is called by each of the derived functors. This is how | |
// the cross thread invocation is made and the result of the invocation | |
// is retrieved. Invoke is always called in the caller thread. | |
template <typename R> | |
R Invoke() { | |
R r = R(); // ensure r is initialized even for primitive types. | |
if (!is_async_) { | |
DoInvoke(&r); | |
} else { | |
// We handle the async calls as if the call returns void. | |
DoInvoke(0); | |
} | |
return r; | |
} | |
// non-template method to be called by the derived functors | |
// specialized for void. | |
void Invoke() { | |
// When the argument of the invocation is 0, we are not | |
// interested in the result. | |
DoInvoke(0); | |
} | |
private: | |
void DoInvoke(void* presult); // Does the actual invocation. | |
DWORD thread_id_; // The thread id of the calling thread. | |
bool is_async_; // True for async calls. | |
DISALLOW_EVIL_CONSTRUCTORS(BaseFunctor); | |
}; | |
// | |
// 0-ary method functor. | |
// | |
template <class T, typename R> | |
class MethodFunctor0 : public BaseFunctor { | |
public: | |
MethodFunctor0(bool is_async, T* pt, R (T::*pm)()) : | |
BaseFunctor(is_async), pobj_(pt), pm_(pm) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
if (presult) { | |
*static_cast<R*>(presult) = (pobj_->*pm_)(); | |
} else { | |
(pobj_->*pm_)(); | |
} | |
} | |
R Invoke() { | |
// Don't forget to call the base implementation. | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
T* pobj_; | |
R (T::*pm_)(); | |
}; | |
// | |
// 0-ary partial specialization for void return types. | |
// | |
template <class T> | |
class MethodFunctor0<T, void> : public BaseFunctor { | |
public: | |
MethodFunctor0(bool is_async, T* pt, void (T::*pm)()) : | |
BaseFunctor(is_async), pobj_(pt), pm_(pm) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
// the actual call. There is no return value when the return type is void. | |
(pobj_->*pm_)(); | |
} | |
// Bring in the name from the Base | |
using BaseFunctor::Invoke; | |
private: | |
T* pobj_; | |
void (T::*pm_)(); | |
}; | |
// | |
// 0-ary functor and specialization for void. | |
// | |
template <typename R> | |
class Functor0 : public BaseFunctor { | |
public: | |
Functor0(bool is_async, R (*pf)()) : | |
BaseFunctor(is_async), pf_(pf) {} | |
virtual void operator()(void* presult) { | |
if (presult) { | |
*static_cast<R*>(presult) = (*pf_)(); | |
} else { | |
(*pf_)(); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
R (*pf_)(); | |
}; | |
template <> | |
class Functor0<void> : public BaseFunctor { | |
public: | |
Functor0(bool is_async, void (*pf)()) : | |
BaseFunctor(is_async), pf_(pf) {} | |
virtual void operator()(void* presult) { | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(*pf_)(); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
void (*pf_)(); | |
}; | |
// | |
// 1-ary | |
// | |
template <class T, typename R, typename P> | |
class MethodFunctor1 : public BaseFunctor { | |
public: | |
MethodFunctor1(bool is_async, T* pt, R (T::*pm)(P), P p) : | |
BaseFunctor(is_async), pobj_(pt), pm_(pm), p_(p) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
if (presult) { | |
*static_cast<R*>(presult) = (pobj_->*pm_)(p_); | |
} else { | |
(pobj_->*pm_)(p_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
T* pobj_; | |
R (T::*pm_)(P); | |
P p_; | |
}; | |
template <class T, typename P> | |
class MethodFunctor1<T, void, P> : public BaseFunctor { | |
public: | |
MethodFunctor1(bool is_async, T* pt, void (T::*pm)(P), P p) : | |
BaseFunctor(is_async), pobj_(pt), pm_(pm), p_(p) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(pobj_->*pm_)(p_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
T* pobj_; | |
void (T::*pm_)(P); | |
P p_; | |
}; | |
template <typename R, typename P1> | |
class Functor1 : public BaseFunctor { | |
public: | |
Functor1(bool is_async, R (*pf)(P1), P1 p1) : | |
BaseFunctor(is_async), pf_(pf), p1_(p1) {} | |
virtual void operator()(void* presult) { | |
if (presult) { | |
*static_cast<R*>(presult) = (*pf_)(p1_); | |
} else { | |
(*pf_)(p1_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
R (*pf_)(P1); | |
P1 p1_; | |
}; | |
template <typename P1> | |
class Functor1<void, P1> : public BaseFunctor { | |
public: | |
Functor1(bool is_async, void (*pf)(P1), P1 p1) : | |
BaseFunctor(is_async), pf_(pf), p1_(p1) {} | |
virtual void operator()(void* presult) { | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(*pf_)(p1_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
void (*pf_)(P1); | |
P1 p1_; | |
}; | |
// | |
// 2-ary | |
// | |
template <class T, typename R, typename P1, typename P2> | |
class MethodFunctor2 : public BaseFunctor { | |
public: | |
MethodFunctor2(bool is_async, T* pt, R (T::*pm)(P1, P2), P1 p1, P2 p2) : | |
BaseFunctor(is_async), pobj_(pt), pm_(pm), p1_(p1), p2_(p2) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
if (presult) { | |
*static_cast<R*>(presult) = (pobj_->*pm_)(p1_, p2_); | |
} else { | |
(pobj_->*pm_)(p1_, p2_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
T* pobj_; | |
R (T::*pm_)(P1, P2); | |
P1 p1_; | |
P2 p2_; | |
}; | |
template <class T, typename P1, typename P2> | |
class MethodFunctor2<T, void, P1, P2> : public BaseFunctor { | |
public: | |
MethodFunctor2(bool is_async, T* pt, void (T::*pm)(P1, P2), P1 p1, P2 p2) : | |
BaseFunctor(is_async), pobj_(pt), pm_(pm), p1_(p1), p2_(p2) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(pobj_->*pm_)(p1_, p2_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
T* pobj_; | |
void (T::*pm_)(P1, P2); | |
P1 p1_; | |
P2 p2_; | |
}; | |
template <typename R, typename P1, typename P2> | |
class Functor2 : public BaseFunctor { | |
public: | |
Functor2(bool is_async, R (*pf)(P1, P2), P1 p1, P2 p2) : | |
BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2) {} | |
virtual void operator()(void* presult) { | |
if (presult) { | |
*static_cast<R*>(presult) = pf_(p1_, p2_); | |
} else { | |
pf_(p1_, p2_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
R (*pf_)(P1, P2); | |
P1 p1_; | |
P2 p2_; | |
}; | |
template <typename P1, typename P2> | |
class Functor2<void, P1, P2> : public BaseFunctor { | |
public: | |
Functor2(bool is_async, void (*pf)(P1, P2), P1 p1, P2 p2) : | |
BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2) {} | |
virtual void operator()(void* presult) { | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(*pf_)(p1_, p2_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
void (*pf_)(P1, P2); | |
P1 p1_; | |
P2 p2_; | |
}; | |
// | |
// 3-ary | |
// | |
template <class T, typename R, typename P1, typename P2, typename P3> | |
class MethodFunctor3 : public BaseFunctor { | |
public: | |
MethodFunctor3(bool is_async, | |
T* pt, | |
R (T::*pm)(P1, P2, P3), | |
P1 p1, | |
P2 p2, | |
P3 p3) : | |
BaseFunctor(is_async), pobj_(pt), pm_(pm), p1_(p1), p2_(p2), p3_(p3) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
if (presult) { | |
*static_cast<R*>(presult) = (pobj_->*pm_)(p1_, p2_, p3_); | |
} else { | |
(pobj_->*pm_)(p1_, p2_, p3_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
T* pobj_; | |
R (T::*pm_)(P1, P2, P3); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
}; | |
template <class T, typename P1, typename P2, typename P3> | |
class MethodFunctor3<T, void, P1, P2, P3> : public BaseFunctor { | |
public: | |
MethodFunctor3(bool is_async, | |
T* pt, | |
void (T::*pm)(P1, P2, P3), | |
P1 p1, | |
P2 p2, | |
P3 p3) : | |
BaseFunctor(is_async), pobj_(pt), pm_(pm), p1_(p1), p2_(p2), p3_(p3) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(pobj_->*pm_)(p1_, p2_, p3_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
T* pobj_; | |
void (T::*pm_)(P1, P2, P3); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
}; | |
template <typename R, typename P1, typename P2, typename P3> | |
class Functor3 : public BaseFunctor { | |
public: | |
Functor3(bool is_async, R (*pf)(P1, P2, P3), P1 p1, P2 p2, P3 p3) : | |
BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2), p3_(p3) {} | |
virtual void operator()(void* presult) { | |
if (presult) { | |
*static_cast<R*>(presult) = (*pf_)(p1_, p2_, p3_); | |
} else { | |
(*pf_)(p1_, p2_, p3_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
R (*pf_)(P1, P2, P3); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
}; | |
template <typename P1, typename P2, typename P3> | |
class Functor3<void, P1, P2, P3> : public BaseFunctor { | |
public: | |
Functor3(bool is_async, void (*pf)(P1, P2, P3), P1 p1, P2 p2, P3 p3) : | |
BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2), p3_(p3) {} | |
virtual void operator()(void* presult) { | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(*pf_)(p1_, p2_, p3_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
void (*pf_)(P1, P2, P3); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
}; | |
// | |
// 4-ary | |
// | |
template <class T, | |
typename R, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4> | |
class MethodFunctor4 : public BaseFunctor { | |
public: | |
MethodFunctor4(bool is_async, | |
T* pt, | |
R (T::*pm)(P1, P2, P3, P4), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4) : | |
BaseFunctor(is_async), | |
pobj_(pt), | |
pm_(pm), | |
p1_(p1), | |
p2_(p2), | |
p3_(p3), | |
p4_(p4) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
if (presult) { | |
*static_cast<R*>(presult) = (pobj_->*pm_)(p1_, p2_, p3_, p4_); | |
} else { | |
(pobj_->*pm_)(p1_, p2_, p3_, p4_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
T* pobj_; | |
R (T::*pm_)(P1, P2, P3, P4); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
P4 p4_; | |
}; | |
template <class T, typename P1, typename P2, typename P3, typename P4> | |
class MethodFunctor4<T, void, P1, P2, P3, P4> : public BaseFunctor { | |
public: | |
MethodFunctor4(bool is_async, | |
T* pt, | |
void (T::*pm)(P1, P2, P3, P4), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4) : | |
BaseFunctor(is_async), | |
pobj_(pt), | |
pm_(pm), | |
p1_(p1), | |
p2_(p2), | |
p3_(p3), | |
p4_(p4) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(pobj_->*pm_)(p1_, p2_, p3_, p4_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
T* pobj_; | |
void (T::*pm_)(P1, P2, P3, P4); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
P4 p4_; | |
}; | |
template <typename R, typename P1, typename P2, typename P3, typename P4> | |
class Functor4 : public BaseFunctor { | |
public: | |
Functor4(bool is_async, R (*pf)(P1, P2, P3, P4), P1 p1, P2 p2, P3 p3, P4 p4) : | |
BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2), p3_(p3), p4_(p4) {} | |
virtual void operator()(void* presult) { | |
if (presult) { | |
*static_cast<R*>(presult) = (*pf_)(p1_, p2_, p3_, p4_); | |
} else { | |
(*pf_)(p1_, p2_, p3_, p4_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
R (*pf_)(P1, P2, P3, P4); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
P4 p4_; | |
}; | |
template <typename P1, typename P2, typename P3, typename P4> | |
class Functor4<void, P1, P2, P3, P4> : public BaseFunctor { | |
public: | |
Functor4(bool is_async, | |
void (*pf)(P1, P2, P3, P4), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4) : | |
BaseFunctor(is_async), pf_(pf), p1_(p1), p2_(p2), p3_(p3), p4_(p4) {} | |
virtual void operator()(void* presult) { | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(*pf_)(p1_, p2_, p3_, p4_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
void (*pf_)(P1, P2, P3, P4); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
P4 p4_; | |
}; | |
// | |
// 5-ary | |
// | |
template <class T, | |
typename R, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4, | |
typename P5> | |
class MethodFunctor5 : public BaseFunctor { | |
public: | |
MethodFunctor5(bool is_async, | |
T* pt, | |
R (T::*pm)(P1, P2, P3, P4, P5), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4, | |
P5 p5) : | |
BaseFunctor(is_async), | |
pobj_(pt), | |
pm_(pm), | |
p1_(p1), | |
p2_(p2), | |
p3_(p3), | |
p4_(p4), | |
p5_(p5) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
if (presult) { | |
*static_cast<R*>(presult) = (pobj_->*pm_)(p1_, p2_, p3_, p4_, p5_); | |
} else { | |
(pobj_->*pm_)(p1_, p2_, p3_, p4_, p5_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
T* pobj_; | |
R (T::*pm_)(P1, P2, P3, P4, P5); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
P4 p4_; | |
P5 p5_; | |
}; | |
template <class T, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4, | |
typename P5> | |
class MethodFunctor5<T, void, P1, P2, P3, P4, P5> : public BaseFunctor { | |
public: | |
MethodFunctor5(bool is_async, | |
T* pt, | |
void (T::*pm)(P1, P2, P3, P4, P5), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4, | |
P5 p5) : | |
BaseFunctor(is_async), | |
pobj_(pt), | |
pm_(pm), | |
p1_(p1), | |
p2_(p2), | |
p3_(p3), | |
p4_(p4), | |
p5_(p5) {} | |
virtual void operator()(void* presult) { | |
ASSERT(pobj_, (_T("Null object."))); | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(pobj_->*pm_)(p1_, p2_, p3_, p4_, p5_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
T* pobj_; | |
void (T::*pm_)(P1, P2, P3, P4, P5); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
P4 p4_; | |
P5 p5_; | |
}; | |
template <typename R, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4, | |
typename P5> | |
class Functor5 : public BaseFunctor { | |
public: | |
Functor5(bool is_async, | |
R (*pf)(P1, P2, P3, P4, P5), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4, | |
P5 p5) : | |
BaseFunctor(is_async), | |
pf_(pf), | |
p1_(p1), | |
p2_(p2), | |
p3_(p3), | |
p4_(p4), | |
p5_(p5) {} | |
virtual void operator()(void* presult) { | |
if (presult) { | |
*static_cast<R*>(presult) = (*pf_)(p1_, p2_, p3_, p4_, p5_); | |
} else { | |
(*pf_)(p1_, p2_, p3_, p4_, p5_); | |
} | |
} | |
R Invoke() { | |
return BaseFunctor::Invoke<R>(); | |
} | |
private: | |
R (*pf_)(P1, P2, P3, P4, P5); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
P4 p4_; | |
P5 p5_; | |
}; | |
template <typename P1, typename P2, typename P3, typename P4, typename P5> | |
class Functor5<void, P1, P2, P3, P4, P5> : public BaseFunctor { | |
public: | |
Functor5(bool is_async, | |
void (*pf)(P1, P2, P3, P4, P5), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4, | |
P5 p5) : | |
BaseFunctor(is_async), | |
pf_(pf), | |
p1_(p1), | |
p2_(p2), | |
p3_(p3), | |
p4_(p4), | |
p5_(p5) {} | |
virtual void operator()(void* presult) { | |
ASSERT1(!presult); | |
presult; // unreferenced formal parameter | |
(*pf_)(p1_, p2_, p3_, p4_, p5_); | |
} | |
using BaseFunctor::Invoke; | |
private: | |
void (*pf_)(P1, P2, P3, P4, P5); | |
P1 p1_; | |
P2 p2_; | |
P3 p3_; | |
P4 p4_; | |
P5 p5_; | |
}; | |
// This is what the clients of the STA code instantiate and call. | |
// | |
// Synchronous Callers. | |
// | |
template <class T, typename R> | |
R CallMethod(T* object, R (T::*pm)()) { | |
return MethodFunctor0<T, R>(false, object, pm).Invoke(); | |
} | |
template <typename R> | |
R CallFunction(R (*pf)()) { | |
return Functor0<R>(false, pf).Invoke(); | |
} | |
template <class T, typename R, typename P> | |
R CallMethod(T* object, R (T::*pm)(P), P p) { | |
return MethodFunctor1<T, R, P>(false, object, pm, p).Invoke(); | |
} | |
template <typename R, typename P> | |
R CallFunction(R (*pf)(P), P p) { | |
return Functor1<R, P>(false, pf, p).Invoke(); | |
} | |
template <class T, typename R, typename P1, typename P2> | |
R CallMethod(T* object, R (T::*pm)(P1, P2), P1 p1, P2 p2) { | |
return MethodFunctor2<T, R, P1, P2>(false, object, pm, p1, p2).Invoke(); | |
} | |
template <typename R, typename P1, typename P2> | |
R CallFunction(R (*pf)(P1, P2), P1 p1, P2 p2) { | |
return Functor2<R, P1, P2>(false, pf, p1, p2).Invoke(); | |
} | |
template <class T, typename R, typename P1, typename P2, typename P3> | |
R CallMethod(T* object, R (T::*pm)(P1, P2, P3), P1 p1, P2 p2, P3 p3) { | |
return MethodFunctor3<T, R, P1, P2, P3>(false, | |
object, pm, p1, p2, p3).Invoke(); | |
} | |
template <typename R, typename P1, typename P2, typename P3> | |
R CallFunction(R (*pf)(P1, P2, P3), P1 p1, P2 p2, P3 p3) { | |
return Functor3<R, P1, P2, P3>(false, pf, p1, p2, p3).Invoke(); | |
} | |
template <class T, | |
typename R, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4> | |
R CallMethod(T* object, | |
R (T::*pm)(P1, P2, P3, P4), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4) { | |
return MethodFunctor4<T, R, P1, P2, P3, P4>(false, | |
object, | |
pm, | |
p1, | |
p2, | |
p3, | |
p4).Invoke(); | |
} | |
template <typename R, typename P1, typename P2, typename P3, typename P4> | |
R CallFunction(R (*pf)(P1, P2, P3, P4), P1 p1, P2 p2, P3 p3, P4 p4) { | |
return Functor4<R, P1, P2, P3, P4>(false, pf, p1, p2, p3, p4).Invoke(); | |
} | |
template <class T, | |
typename R, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4, | |
typename P5> | |
R CallMethod(T* object, | |
R (T::*pm)(P1, P2, P3, P4, P5), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4, | |
P5 p5) { | |
return MethodFunctor5<T, R, P1, P2, P3, P4, P5>(false, | |
object, | |
pm, | |
p1, | |
p2, | |
p3, | |
p4, | |
p5).Invoke(); | |
} | |
template <typename R, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4, | |
typename P5> | |
R CallFunction(R (*pf)(P1, P2, P3, P4, P5), P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { | |
return Functor5<R, P1, P2, P3, P4, P5>(false, | |
pf, | |
p1, | |
p2, | |
p3, | |
p4, | |
p5).Invoke(); | |
} | |
// | |
// Asynchronous Callers. | |
// | |
template <class T, typename R> | |
void CallMethodAsync(T* object, R (T::*pm)()) { | |
scoped_ptr<MethodFunctor0<T, R> > fun( | |
new MethodFunctor0<T, R>(true, object, pm)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <typename R> | |
void CallFunctionAsync(R (*pf)()) { | |
scoped_ptr<Functor0<R> > fun(new Functor0<R>(true, pf)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <class T, typename R, typename P> | |
void CallMethodAsync(T* object, R (T::*pm)(P), P p) { | |
scoped_ptr<MethodFunctor1<T, R, P> > fun( | |
new MethodFunctor1<T, R, P>(true, object, pm, p)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <typename R, typename P> | |
void CallFunctionAsync(R (*pf)(P), P p) { | |
scoped_ptr<Functor1<R, P> > fun(new Functor1<R, P>(true, pf, p)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <class T, typename R, typename P1, typename P2> | |
void CallMethodAsync(T* object, R (T::*pm)(P1, P2), P1 p1, P2 p2) { | |
scoped_ptr<MethodFunctor2<T, R, P1, P2> > fun( | |
new MethodFunctor2<T, R, P1, P2>(true, object, pm, p1, p2)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <typename R, typename P1, typename P2> | |
void CallFunctionAsync(R (*pf)(P1, P2), P1 p1, P2 p2) { | |
scoped_ptr<Functor2<R, P1, P2> > fun( | |
new Functor2<R, P1, P2>(true, pf, p1, p2)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <class T, typename R, typename P1, typename P2, typename P3> | |
void CallMethodAsync(T* object, R (T::*pm)(P1, P2, P3), P1 p1, P2 p2, P3 p3) { | |
scoped_ptr<MethodFunctor3<T, R, P1, P2, P3> > fun( | |
new MethodFunctor3<T, R, P1, P2, P3>(true, object, pm, p1, p2, p3)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <typename R, typename P1, typename P2, typename P3> | |
void CallFunctionAsync(R (*pf)(P1, P2, P3), P1 p1, P2 p2, P3 p3) { | |
scoped_ptr<Functor3<R, P1, P2, P3> > fun( | |
new Functor3<R, P1, P2, P3>(true, pf, p1, p2, p3)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <class T, | |
typename R, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4> | |
void CallMethodAsync(T* obj, | |
R (T::*pm)(P1, P2, P3, P4), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4) { | |
scoped_ptr<MethodFunctor4<T, R, P1, P2, P3, P4> > fun( | |
new MethodFunctor4<T, R, P1, P2, P3, P4>(true, obj, pm, p1, p2, p3, p4)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <typename R, typename P1, typename P2, typename P3, typename P4> | |
void CallFunctionAsync(R (*pf)(P1, P2, P3, P4), P1 p1, P2 p2, P3 p3, P4 p4) { | |
scoped_ptr<Functor4<R, P1, P2, P3, P4> > fun( | |
new Functor4<R, P1, P2, P3, P4>(true, pf, p1, p2, p3, p4)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <class T, | |
typename R, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4, | |
typename P5> | |
void CallMethodAsync(T* object, | |
R (T::*pm)(P1, P2, P3, P4, P5), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4, | |
P5 p5) { | |
scoped_ptr<MethodFunctor5<T, R, P1, P2, P3, P4, P5> > fun( | |
new MethodFunctor5<T, R, P1, P2, P3, P4, P5>(true, | |
object, | |
pm, | |
p1, | |
p2, | |
p3, | |
p4, | |
p5)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
template <typename R, | |
typename P1, | |
typename P2, | |
typename P3, | |
typename P4, | |
typename P5> | |
void CallFunctionAsync(R (*pf)(P1, P2, P3, P4, P5), | |
P1 p1, | |
P2 p2, | |
P3 p3, | |
P4 p4, | |
P5 p5) { | |
scoped_ptr<Functor5<R, P1, P2, P3, P4, P5> > fun( | |
new Functor5<R, P1, P2, P3, P4, P5>(true, pf, p1, p2, p3, p4, p5)); | |
fun->Invoke(); | |
fun.release(); | |
} | |
#pragma warning(default : 4347) | |
} // namespace omaha | |
#endif // OMAHA_COMMON_STA_CALL_H__ | |