blob: 9a02a42983658aa656ea2f17cb59c8c48bccdc84 [file] [log] [blame]
// 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__