Eliminate duplicate code by combining nsNonOwningRunnableMethod with nsRunnableMethod (part 1/3 of bug 558498). r=dwitte sr=dbaron

This commit is contained in:
Ben Newman 2010-04-20 10:22:04 -07:00
parent 057ce0b44f
commit 2b2bd4076f
7 changed files with 35 additions and 72 deletions

View File

@ -444,8 +444,8 @@ nsContentSink::ProcessHTTPHeaders(nsIChannel* aChannel)
"Already dispatched an event?");
mProcessLinkHeaderEvent =
new nsNonOwningRunnableMethod<nsContentSink>(this,
&nsContentSink::DoProcessLinkHeader);
new nsRunnableMethod<nsContentSink, void, false>(this,
&nsContentSink::DoProcessLinkHeader);
rv = NS_DispatchToCurrentThread(mProcessLinkHeaderEvent.get());
if (NS_FAILED(rv)) {
mProcessLinkHeaderEvent.Forget();

View File

@ -400,7 +400,7 @@ protected:
PRUint32 mPendingSheetCount;
nsRevocableEventPtr<nsNonOwningRunnableMethod<nsContentSink> >
nsRevocableEventPtr<nsRunnableMethod<nsContentSink, void, false> >
mProcessLinkHeaderEvent;
};

View File

@ -5159,9 +5159,9 @@ nsDocument::NotifyPossibleTitleChange(PRBool aBoundTitleElement)
if (mPendingTitleChangeEvent.IsPending())
return;
nsRefPtr<nsNonOwningRunnableMethod<nsDocument> > event =
new nsNonOwningRunnableMethod<nsDocument>(this,
&nsDocument::DoNotifyPossibleTitleChange);
nsRefPtr<nsRunnableMethod<nsDocument, void, false> > event =
new nsRunnableMethod<nsDocument, void, false>(this,
&nsDocument::DoNotifyPossibleTitleChange);
nsresult rv = NS_DispatchToCurrentThread(event);
if (NS_SUCCEEDED(rv)) {
mPendingTitleChangeEvent = event;

View File

@ -1194,7 +1194,7 @@ private:
nsTArray<nsRefPtr<nsFrameLoader> > mFinalizableFrameLoaders;
nsRefPtr<nsRunnableMethod<nsDocument> > mFrameLoaderRunner;
nsRevocableEventPtr<nsNonOwningRunnableMethod<nsDocument> >
nsRevocableEventPtr<nsRunnableMethod<nsDocument, void, false> >
mPendingTitleChangeEvent;
nsExternalResourceMap mExternalResourceMap;

View File

@ -673,7 +673,7 @@ nsMediaChannelStream::CacheClientNotifyDataReceived()
return;
mDataReceivedEvent =
new nsNonOwningRunnableMethod<nsMediaChannelStream>(this, &nsMediaChannelStream::DoNotifyDataReceived);
new nsRunnableMethod<nsMediaChannelStream, void, false>(this, &nsMediaChannelStream::DoNotifyDataReceived);
NS_DispatchToMainThread(mDataReceivedEvent.get(), NS_DISPATCH_NORMAL);
}

View File

@ -411,7 +411,7 @@ protected:
nsRefPtr<Listener> mListener;
// A data received event for the decoder that has been dispatched but has
// not yet been processed.
nsRevocableEventPtr<nsNonOwningRunnableMethod<nsMediaChannelStream> > mDataReceivedEvent;
nsRevocableEventPtr<nsRunnableMethod<nsMediaChannelStream, void, false> > mDataReceivedEvent;
PRUint32 mSuspendCount;
// When this flag is set, if we get a network error we should silently
// reopen the stream.

View File

@ -262,29 +262,46 @@ 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.
template <class ClassType, typename ReturnType = void>
template <class ClassType,
typename ReturnType = void,
bool Owning = true>
class nsRunnableMethod : public nsRunnable
{
public:
typedef ReturnType (ClassType::*Method)();
nsRunnableMethod(ClassType *obj, Method method)
: mObj(obj), mMethod(method) {
NS_ADDREF(mObj);
}
: mReceiver(obj)
, mMethod(method)
{}
NS_IMETHOD Run() {
if (!mObj)
if (!mReceiver.mObj)
return NS_OK;
(mObj->*mMethod)();
(mReceiver.mObj->*mMethod)();
return NS_OK;
}
void Revoke() {
NS_IF_RELEASE(mObj);
mReceiver.Revoke();
}
// These ReturnTypeEnforcer classes set up a blacklist for return types that
@ -308,11 +325,11 @@ public:
protected:
virtual ~nsRunnableMethod() {
NS_IF_RELEASE(mObj);
Revoke();
}
private:
ClassType* mObj;
RunnableMethodReceiver<ClassType, Owning> mReceiver;
Method mMethod;
};
@ -339,60 +356,6 @@ ns_new_runnable_method(ClassType* obj, ReturnType (ClassType::*method)())
return new nsRunnableMethod<ClassType, ReturnType>(obj, method);
}
// An event that can be used to call a method on a class, but holds only
// a raw pointer to the object on which the method will be called. This
// event supports Revoke for use with nsRevocableEventPtr and should
// almost always be used with it.
template <class ClassType, typename ReturnType = void>
class nsNonOwningRunnableMethod : public nsRunnable
{
public:
typedef ReturnType (ClassType::*Method)();
nsNonOwningRunnableMethod(ClassType *obj, Method method)
: mObj(obj), mMethod(method) {
}
NS_IMETHOD Run() {
if (!mObj)
return NS_OK;
(mObj->*mMethod)();
return NS_OK;
}
void Revoke() {
mObj = nsnull;
}
// These ReturnTypeEnforcer classes set up a blacklist for return types that
// we know are not safe. The default ReturnTypeEnforcer compiles just fine but
// already_AddRefed will not.
template <typename OtherReturnType>
class ReturnTypeEnforcer
{
public:
typedef int ReturnTypeIsSafe;
};
template <class T>
class ReturnTypeEnforcer<already_AddRefed<T> >
{
// No ReturnTypeIsSafe makes this illegal!
};
// Make sure this return type is safe.
typedef typename ReturnTypeEnforcer<ReturnType>::ReturnTypeIsSafe check;
protected:
virtual ~nsNonOwningRunnableMethod() {
}
private:
ClassType* mObj;
Method mMethod;
};
#endif // XPCOM_GLUE_AVOID_NSPR
// This class is designed to be used when you have an event class E that has a