Support __stdcall nsRunnableMethods (part 2/3 of bug 558498). r=dwitte sr=dbaron

This commit is contained in:
Ben Newman 2010-04-20 16:21:32 -07:00
parent 2b2bd4076f
commit ec00ae01fb
2 changed files with 89 additions and 55 deletions

View File

@ -2842,6 +2842,18 @@ AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_MSG_CHECKING(for __stdcall)
AC_CACHE_VAL(ac_cv___stdcall,
[AC_TRY_COMPILE([],
[void foo(); void __stdcall foo();],
[ac_cv___stdcall=true],
[ac_cv___stdcall=false])])
if test "$ac_cv___stdcall" = true ; then
AC_DEFINE(HAVE_STDCALL)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING(for ssize_t)
AC_CACHE_VAL(ac_cv_type_ssize_t,
[AC_TRY_COMPILE([#include <stdio.h>

View File

@ -262,21 +262,6 @@ protected:
#undef IMETHOD_VISIBILITY
#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
template <class ClassType, bool Owning>
struct RunnableMethodReceiver {
ClassType *mObj;
RunnableMethodReceiver(ClassType *obj) : mObj(obj) { NS_IF_ADDREF(mObj); }
~RunnableMethodReceiver() { Revoke(); }
void Revoke() { NS_IF_RELEASE(mObj); }
};
template <class ClassType>
struct RunnableMethodReceiver<ClassType, false> {
ClassType *mObj;
RunnableMethodReceiver(ClassType *obj) : mObj(obj) {}
void Revoke() { mObj = nsnull; }
};
// An event that can be used to call a method on a class. The class type must
// support reference counting. This event supports Revoke for use
// with nsRevocableEventPtr.
@ -286,23 +271,7 @@ template <class ClassType,
class nsRunnableMethod : public nsRunnable
{
public:
typedef ReturnType (ClassType::*Method)();
nsRunnableMethod(ClassType *obj, Method method)
: mReceiver(obj)
, mMethod(method)
{}
NS_IMETHOD Run() {
if (!mReceiver.mObj)
return NS_OK;
(mReceiver.mObj->*mMethod)();
return NS_OK;
}
void Revoke() {
mReceiver.Revoke();
}
virtual void Revoke() = 0;
// These ReturnTypeEnforcer classes set up a blacklist for return types that
// we know are not safe. The default ReturnTypeEnforcer compiles just fine but
@ -322,38 +291,91 @@ public:
// Make sure this return type is safe.
typedef typename ReturnTypeEnforcer<ReturnType>::ReturnTypeIsSafe check;
protected:
virtual ~nsRunnableMethod() {
Revoke();
}
private:
RunnableMethodReceiver<ClassType, Owning> mReceiver;
Method mMethod;
};
// Use this helper macro like so:
template <class ClassType, bool Owning>
struct nsRunnableMethodReceiver {
ClassType *mObj;
nsRunnableMethodReceiver(ClassType *obj) : mObj(obj) { NS_IF_ADDREF(mObj); }
~nsRunnableMethodReceiver() { Revoke(); }
void Revoke() { NS_IF_RELEASE(mObj); }
};
template <class ClassType>
struct nsRunnableMethodReceiver<ClassType, false> {
ClassType *mObj;
nsRunnableMethodReceiver(ClassType *obj) : mObj(obj) {}
void Revoke() { mObj = nsnull; }
};
template <typename Method, bool Owning> struct nsRunnableMethodTraits;
template <class C, typename R, bool Owning>
struct nsRunnableMethodTraits<R (C::*)(), Owning> {
typedef C class_type;
typedef R return_type;
typedef nsRunnableMethod<C, R, Owning> base_type;
};
#ifdef HAVE_STDCALL
template <class C, typename R, bool Owning>
struct nsRunnableMethodTraits<R (__stdcall C::*)(), Owning> {
typedef C class_type;
typedef R return_type;
typedef nsRunnableMethod<C, R, Owning> base_type;
};
#endif
template <typename Method, bool Owning>
class nsRunnableMethodImpl
: public nsRunnableMethodTraits<Method, Owning>::base_type
{
typedef typename nsRunnableMethodTraits<Method, Owning>::class_type ClassType;
nsRunnableMethodReceiver<ClassType, Owning> mReceiver;
Method mMethod;
public:
nsRunnableMethodImpl(ClassType *obj,
Method method)
: mReceiver(obj)
, mMethod(method)
{}
NS_IMETHOD Run() {
if (NS_LIKELY(mReceiver.mObj))
((*mReceiver.mObj).*mMethod)();
return NS_OK;
}
void Revoke() {
mReceiver.Revoke();
}
};
// Use this template function like so:
//
// nsCOMPtr<nsIRunnable> event =
// NS_NEW_RUNNABLE_METHOD(MyClass, myObject, HandleEvent);
// NS_NewRunnableMethod(myObject, &MyClass::HandleEvent);
// NS_DispatchToCurrentThread(event);
//
// Constraints:
// - myObject must be of type MyClass
// Statically enforced constraints:
// - myObject must be of (or implicitly convertible to) type MyClass
// - MyClass must defined AddRef and Release methods
//
// NOTE: Attempts to make this a template function caused VC6 to barf :-(
//
#define NS_NEW_RUNNABLE_METHOD(class_, obj_, method_) \
ns_new_runnable_method(obj_, &class_::method_)
template<class ClassType, typename ReturnType>
nsRunnableMethod<ClassType, ReturnType>*
ns_new_runnable_method(ClassType* obj, ReturnType (ClassType::*method)())
template<typename PtrType, typename Method>
NS_COM_GLUE
typename nsRunnableMethodTraits<Method, true>::base_type*
NS_NewRunnableMethod(PtrType ptr, Method method)
{
return new nsRunnableMethod<ClassType, ReturnType>(obj, method);
return new nsRunnableMethodImpl<Method, true>(ptr, method);
}
template<typename PtrType, typename Method>
NS_COM_GLUE
typename nsRunnableMethodTraits<Method, false>::base_type*
NS_NewNonOwningRunnableMethod(PtrType ptr, Method method)
{
return new nsRunnableMethodImpl<Method, false>(ptr, method);
}
#endif // XPCOM_GLUE_AVOID_NSPR