mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 09:49:14 +00:00
Bug 1358476, add support for timeout when doing idle dispatch, p=farre,smaug, r=nfroyd
--HG-- extra : rebase_source : 8561bd1e1aad04be8b9d3efa7b43d4833a4703bf
This commit is contained in:
parent
87f01dcea3
commit
bc787a0ec7
@ -14,6 +14,7 @@
|
||||
{ 0x688be92e, 0x7ade, 0x4fdc, \
|
||||
{ 0x9d, 0x83, 0x74, 0xcb, 0xef, 0xf4, 0xa5, 0x2c } }
|
||||
|
||||
class nsIEventTarget;
|
||||
|
||||
/**
|
||||
* A task interface for tasks that can schedule their work to happen
|
||||
@ -28,8 +29,12 @@ public:
|
||||
* Notify the task of a point in time in the future when the task
|
||||
* should stop executing.
|
||||
*/
|
||||
virtual void SetDeadline(mozilla::TimeStamp aDeadline) = 0;
|
||||
|
||||
virtual void SetDeadline(mozilla::TimeStamp aDeadline) {};
|
||||
virtual void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget)
|
||||
{
|
||||
NS_NOTREACHED("The nsIIdleRunnable instance does not support "
|
||||
"idle dispatch with timeout!");
|
||||
};
|
||||
protected:
|
||||
nsIIdleRunnable() { }
|
||||
virtual ~nsIIdleRunnable() {}
|
||||
|
@ -1164,9 +1164,9 @@ nsThread::GetIdleEvent(nsIRunnable** aEvent, MutexAutoLock& aProofOfLock)
|
||||
mIdleEvents.GetEvent(false, aEvent, aProofOfLock);
|
||||
|
||||
if (*aEvent) {
|
||||
nsCOMPtr<nsIIdleRunnable> incrementalEvent(do_QueryInterface(*aEvent));
|
||||
if (incrementalEvent) {
|
||||
incrementalEvent->SetDeadline(idleDeadline);
|
||||
nsCOMPtr<nsIIdleRunnable> idleEvent(do_QueryInterface(*aEvent));
|
||||
if (idleEvent) {
|
||||
idleEvent->SetDeadline(idleDeadline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,11 +87,15 @@ CancelableRunnable::Cancel()
|
||||
NS_IMPL_ISUPPORTS_INHERITED(IdleRunnable, CancelableRunnable,
|
||||
nsIIdleRunnable)
|
||||
|
||||
void
|
||||
IdleRunnable::SetDeadline(TimeStamp aDeadline)
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
already_AddRefed<nsITimer> CreateTimer()
|
||||
{
|
||||
// Do nothing
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
return timer.forget();
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // XPCOM_GLUE_AVOID_NSPR
|
||||
|
||||
@ -279,6 +283,7 @@ NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIRunnable> event(aEvent);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_INVALID_ARG);
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsIThread* thread = NS_GetCurrentThread();
|
||||
if (!thread) {
|
||||
@ -305,6 +310,80 @@ NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent)
|
||||
return rv;
|
||||
}
|
||||
|
||||
class IdleRunnableWrapper : public IdleRunnable
|
||||
{
|
||||
public:
|
||||
explicit IdleRunnableWrapper(already_AddRefed<nsIRunnable>&& aEvent)
|
||||
: mRunnable(Move(aEvent))
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
if (!mRunnable) {
|
||||
return NS_OK;
|
||||
}
|
||||
CancelTimer();
|
||||
nsCOMPtr<nsIRunnable> runnable = mRunnable.forget();
|
||||
return runnable->Run();
|
||||
}
|
||||
|
||||
static void
|
||||
TimedOut(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
RefPtr<IdleRunnableWrapper> runnable =
|
||||
static_cast<IdleRunnableWrapper*>(aClosure);
|
||||
runnable->Run();
|
||||
}
|
||||
|
||||
void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget) override
|
||||
{
|
||||
MOZ_ASSERT(aTarget);
|
||||
MOZ_ASSERT(!mTimer);
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
if (mTimer) {
|
||||
mTimer->SetTarget(aTarget);
|
||||
mTimer->InitWithFuncCallback(TimedOut, this, aDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
private:
|
||||
~IdleRunnableWrapper()
|
||||
{
|
||||
CancelTimer();
|
||||
}
|
||||
|
||||
void CancelTimer()
|
||||
{
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
};
|
||||
|
||||
extern nsresult
|
||||
NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent,
|
||||
uint32_t aTimeout)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> event(Move(aEvent));
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_INVALID_ARG);
|
||||
nsCOMPtr<nsIIdleRunnable> idleEvent = do_QueryInterface(event);
|
||||
|
||||
if (!idleEvent) {
|
||||
idleEvent = new IdleRunnableWrapper(event.forget());
|
||||
event = do_QueryInterface(idleEvent);
|
||||
MOZ_DIAGNOSTIC_ASSERT(event);
|
||||
}
|
||||
|
||||
//XXX Using current thread for now as the nsIEventTarget.
|
||||
idleEvent->SetTimer(aTimeout, NS_GetCurrentThread());
|
||||
|
||||
return NS_IdleDispatchToCurrentThread(event.forget());
|
||||
}
|
||||
|
||||
#ifndef XPCOM_GLUE_AVOID_NSPR
|
||||
nsresult
|
||||
NS_ProcessPendingEvents(nsIThread* aThread, PRIntervalTime aTimeout)
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "nsINamed.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIThreadManager.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@ -115,9 +116,42 @@ extern nsresult
|
||||
NS_DelayedDispatchToCurrentThread(
|
||||
already_AddRefed<nsIRunnable>&& aEvent, uint32_t aDelayMs);
|
||||
|
||||
/**
|
||||
* Dispatch the given event to the idle queue of the current thread.
|
||||
*
|
||||
* @param aEvent
|
||||
* The event to dispatch.
|
||||
*
|
||||
* @returns NS_ERROR_INVALID_ARG
|
||||
* If event is null.
|
||||
* @returns NS_ERROR_UNEXPECTED
|
||||
* If the thread is shutting down.
|
||||
*/
|
||||
extern nsresult
|
||||
NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent);
|
||||
|
||||
/**
|
||||
* Dispatch the given event to the idle queue of the current thread.
|
||||
*
|
||||
* @param aEvent The event to dispatch. If the event implements
|
||||
* nsIIdleRunnable, it will receive a call on
|
||||
* nsIIdleRunnable::SetTimer when dispatched, with the value of
|
||||
* aTimeout.
|
||||
*
|
||||
* @param aTimeout The time in milliseconds until the event should be
|
||||
* moved from the idle queue to the regular queue, if it hasn't been
|
||||
* executed. If aEvent is also an nsIIdleRunnable, it is expected
|
||||
* that it should handle the timeout itself, after a call to
|
||||
* nsIIdleRunnable::SetTimer.
|
||||
*
|
||||
* @returns NS_ERROR_INVALID_ARG
|
||||
* If event is null.
|
||||
* @returns NS_ERROR_UNEXPECTED
|
||||
* If the thread is shutting down.
|
||||
*/
|
||||
extern nsresult
|
||||
NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aTimeout);
|
||||
|
||||
#ifndef XPCOM_GLUE_AVOID_NSPR
|
||||
/**
|
||||
* Process all pending events for the given thread before returning. This
|
||||
@ -330,6 +364,16 @@ private:
|
||||
IdlePeriod& operator=(const IdlePeriod&&) = delete;
|
||||
};
|
||||
|
||||
// Cancelable runnable methods implement nsICancelableRunnable, and
|
||||
// Idle and IdleWithTimer also nsIIdleRunnable.
|
||||
enum RunnableKind
|
||||
{
|
||||
Standard,
|
||||
Cancelable,
|
||||
Idle,
|
||||
IdleWithTimer
|
||||
};
|
||||
|
||||
// This class is designed to be subclassed.
|
||||
class Runnable : public nsIRunnable, public nsINamed
|
||||
{
|
||||
@ -380,14 +424,13 @@ private:
|
||||
|
||||
// This class is designed to be subclassed.
|
||||
class IdleRunnable : public CancelableRunnable,
|
||||
public nsIIdleRunnable
|
||||
public nsIIdleRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
// nsIIdleRunnable
|
||||
virtual void SetDeadline(TimeStamp aDeadline) override;
|
||||
|
||||
IdleRunnable() {}
|
||||
explicit IdleRunnable(const char* aName) : CancelableRunnable(aName) {}
|
||||
|
||||
protected:
|
||||
virtual ~IdleRunnable() {}
|
||||
@ -543,16 +586,69 @@ NS_NewRunnableFunction(const char* aName, Function&& aFunction)
|
||||
NS_NewRunnableFunction(mozilla::Forward<Function>(aFunction)), aName);
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
already_AddRefed<nsITimer> CreateTimer();
|
||||
|
||||
template <RunnableKind Kind>
|
||||
class TimerBehaviour
|
||||
{
|
||||
public:
|
||||
nsITimer* GetTimer() { return nullptr; }
|
||||
void CancelTimer() {}
|
||||
|
||||
protected:
|
||||
~TimerBehaviour() {}
|
||||
};
|
||||
|
||||
template <>
|
||||
class TimerBehaviour<IdleWithTimer>
|
||||
{
|
||||
public:
|
||||
nsITimer* GetTimer()
|
||||
{
|
||||
if (!mTimer) {
|
||||
mTimer = CreateTimer();
|
||||
}
|
||||
|
||||
return mTimer;
|
||||
}
|
||||
|
||||
void CancelTimer()
|
||||
{
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
~TimerBehaviour()
|
||||
{
|
||||
CancelTimer();
|
||||
}
|
||||
private:
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mozilla
|
||||
|
||||
// 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,
|
||||
bool Owning = true,
|
||||
bool Cancelable = false>
|
||||
class nsRunnableMethod : public mozilla::Conditional<!Cancelable,
|
||||
mozilla::Runnable,
|
||||
mozilla::CancelableRunnable>::Type
|
||||
mozilla::RunnableKind Kind = mozilla::Standard>
|
||||
class nsRunnableMethod
|
||||
: public mozilla::Conditional<Kind == mozilla::Standard,
|
||||
mozilla::Runnable,
|
||||
typename mozilla::Conditional<
|
||||
Kind == mozilla::Cancelable,
|
||||
mozilla::CancelableRunnable,
|
||||
mozilla::IdleRunnable>::Type>::Type,
|
||||
protected mozilla::detail::TimerBehaviour<Kind>
|
||||
{
|
||||
public:
|
||||
virtual void Revoke() = 0;
|
||||
@ -577,7 +673,7 @@ public:
|
||||
typedef typename ReturnTypeEnforcer<ReturnType>::ReturnTypeIsSafe check;
|
||||
};
|
||||
|
||||
template<class ClassType, bool Owning>
|
||||
template<class ClassType, bool Owning, bool Idle>
|
||||
struct nsRunnableMethodReceiver
|
||||
{
|
||||
RefPtr<ClassType> mObj;
|
||||
@ -585,84 +681,114 @@ struct nsRunnableMethodReceiver
|
||||
~nsRunnableMethodReceiver() { Revoke(); }
|
||||
ClassType* Get() const { return mObj.get(); }
|
||||
void Revoke() { mObj = nullptr; }
|
||||
void SetDeadline(mozilla::TimeStamp aDeadline) { if (mObj) mObj->SetDeadline(aDeadline); }
|
||||
};
|
||||
|
||||
template<class ClassType>
|
||||
struct nsRunnableMethodReceiver<ClassType, false>
|
||||
struct nsRunnableMethodReceiver<ClassType, false, false>
|
||||
{
|
||||
ClassType* MOZ_NON_OWNING_REF mObj;
|
||||
explicit nsRunnableMethodReceiver(ClassType* aObj) : mObj(aObj) {}
|
||||
ClassType* Get() const { return mObj; }
|
||||
void Revoke() { mObj = nullptr; }
|
||||
void SetDeadline(mozilla::TimeStamp aDeadline) {}
|
||||
};
|
||||
|
||||
template<typename PtrType, typename Method, bool Owning, bool Cancelable>
|
||||
template<class ClassType>
|
||||
struct nsRunnableMethodReceiver<ClassType, false, true>
|
||||
{
|
||||
ClassType* MOZ_NON_OWNING_REF mObj;
|
||||
explicit nsRunnableMethodReceiver(ClassType* aObj) : mObj(aObj) {}
|
||||
ClassType* Get() const { return mObj; }
|
||||
void Revoke() { mObj = nullptr; }
|
||||
void SetDeadline(mozilla::TimeStamp aDeadline) { if (mObj) mObj->SetDeadline(aDeadline); }
|
||||
};
|
||||
|
||||
static inline constexpr bool
|
||||
IsIdle(mozilla::RunnableKind aKind)
|
||||
{
|
||||
return aKind == mozilla::Idle || aKind == mozilla::IdleWithTimer;
|
||||
}
|
||||
|
||||
template<class ClassType>
|
||||
struct nsRunnableMethodReceiver<ClassType, true, false>
|
||||
{
|
||||
RefPtr<ClassType> mObj;
|
||||
explicit nsRunnableMethodReceiver(ClassType* aObj) : mObj(aObj) {}
|
||||
~nsRunnableMethodReceiver() { Revoke(); }
|
||||
ClassType* Get() const { return mObj.get(); }
|
||||
void Revoke() { mObj = nullptr; }
|
||||
void SetDeadline(mozilla::TimeStamp aDeadline) {}
|
||||
};
|
||||
|
||||
template<typename PtrType, typename Method, bool Owning, mozilla::RunnableKind Kind>
|
||||
struct nsRunnableMethodTraits;
|
||||
|
||||
template<typename PtrType, class C, typename R, bool Owning, bool Cancelable, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R(C::*)(As...), Owning, Cancelable>
|
||||
template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R(C::*)(As...), Owning, Kind>
|
||||
{
|
||||
typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(mozilla::IsBaseOf<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Cancelable> base_type;
|
||||
static const bool can_cancel = Cancelable;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::Cancelable;
|
||||
};
|
||||
|
||||
template<typename PtrType, class C, typename R, bool Owning, bool Cancelable, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R(C::*)(As...) const, Owning, Cancelable>
|
||||
template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R(C::*)(As...) const, Owning, Kind>
|
||||
{
|
||||
typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(mozilla::IsBaseOf<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Cancelable> base_type;
|
||||
static const bool can_cancel = Cancelable;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::Cancelable;
|
||||
};
|
||||
|
||||
#ifdef NS_HAVE_STDCALL
|
||||
template<typename PtrType, class C, typename R, bool Owning, bool Cancelable, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R(__stdcall C::*)(As...), Owning, Cancelable>
|
||||
template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R(__stdcall C::*)(As...), Owning, Kind>
|
||||
{
|
||||
typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(mozilla::IsBaseOf<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Cancelable> base_type;
|
||||
static const bool can_cancel = Cancelable;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::Cancelable;
|
||||
};
|
||||
|
||||
template<typename PtrType, class C, typename R, bool Owning, bool Cancelable>
|
||||
struct nsRunnableMethodTraits<PtrType, R(NS_STDCALL C::*)(), Owning, Cancelable>
|
||||
template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind>
|
||||
struct nsRunnableMethodTraits<PtrType, R(NS_STDCALL C::*)(), Owning, Kind>
|
||||
{
|
||||
typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(mozilla::IsBaseOf<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Cancelable> base_type;
|
||||
static const bool can_cancel = Cancelable;
|
||||
};
|
||||
template<typename PtrType, class C, typename R, bool Owning, bool Cancelable, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R(__stdcall C::*)(As...) const, Owning, Cancelable>
|
||||
{
|
||||
typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(mozilla::IsBaseOf<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Cancelable> base_type;
|
||||
static const bool can_cancel = Cancelable;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::Cancelable;
|
||||
};
|
||||
|
||||
template<typename PtrType, class C, typename R, bool Owning, bool Cancelable>
|
||||
struct nsRunnableMethodTraits<PtrType, R(NS_STDCALL C::*)() const, Owning, Cancelable>
|
||||
template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R(__stdcall C::*)(As...) const, Owning, Kind>
|
||||
{
|
||||
typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(mozilla::IsBaseOf<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Cancelable> base_type;
|
||||
static const bool can_cancel = Cancelable;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::Cancelable;
|
||||
};
|
||||
|
||||
template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind>
|
||||
struct nsRunnableMethodTraits<PtrType, R(NS_STDCALL C::*)() const, Owning, Kind>
|
||||
{
|
||||
typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(mozilla::IsBaseOf<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::Cancelable;
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -966,17 +1092,29 @@ struct RunnableMethodArguments final
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PtrType, typename Method, bool Owning, bool Cancelable, typename... Storages>
|
||||
template<typename PtrType, typename Method, bool Owning, RunnableKind Kind, typename... Storages>
|
||||
class RunnableMethodImpl final
|
||||
: public ::nsRunnableMethodTraits<PtrType, Method, Owning, Cancelable>::base_type
|
||||
: public ::nsRunnableMethodTraits<PtrType, Method, Owning, Kind>::base_type
|
||||
{
|
||||
typedef typename ::nsRunnableMethodTraits<PtrType, Method, Owning, Cancelable>::class_type
|
||||
ClassType;
|
||||
::nsRunnableMethodReceiver<ClassType, Owning> mReceiver;
|
||||
typedef typename ::nsRunnableMethodTraits<PtrType, Method, Owning, Kind> Traits;
|
||||
|
||||
typedef typename Traits::class_type ClassType;
|
||||
typedef typename Traits::base_type BaseType;
|
||||
::nsRunnableMethodReceiver<ClassType, Owning, IsIdle(Kind)> mReceiver;
|
||||
Method mMethod;
|
||||
RunnableMethodArguments<Storages...> mArgs;
|
||||
using BaseType::GetTimer;
|
||||
using BaseType::CancelTimer;
|
||||
private:
|
||||
virtual ~RunnableMethodImpl() { Revoke(); };
|
||||
static void TimedOut(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
static_assert(IsIdle(Kind), "Don't use me!");
|
||||
RefPtr<IdleRunnable> r = static_cast<IdleRunnable*>(aClosure);
|
||||
r->SetDeadline(TimeStamp());
|
||||
r->Run();
|
||||
r->Cancel();
|
||||
}
|
||||
public:
|
||||
template<typename ForwardedPtrType, typename... Args>
|
||||
explicit RunnableMethodImpl(ForwardedPtrType&& aObj, Method aMethod,
|
||||
@ -989,50 +1127,109 @@ public:
|
||||
}
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
CancelTimer();
|
||||
|
||||
if (MOZ_LIKELY(mReceiver.Get())) {
|
||||
mArgs.apply(mReceiver.Get(), mMethod);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult Cancel() {
|
||||
static_assert(Cancelable, "Don't use me!");
|
||||
|
||||
nsresult Cancel()
|
||||
{
|
||||
static_assert(Kind >= Cancelable, "Don't use me!");
|
||||
Revoke();
|
||||
return NS_OK;
|
||||
}
|
||||
void Revoke() { mReceiver.Revoke(); }
|
||||
|
||||
void Revoke()
|
||||
{
|
||||
CancelTimer();
|
||||
mReceiver.Revoke();
|
||||
}
|
||||
|
||||
void SetDeadline(TimeStamp aDeadline)
|
||||
{
|
||||
mReceiver.SetDeadline(aDeadline);
|
||||
}
|
||||
|
||||
void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget)
|
||||
{
|
||||
MOZ_ASSERT(aTarget);
|
||||
|
||||
if (nsCOMPtr<nsITimer> timer = GetTimer()) {
|
||||
timer->Cancel();
|
||||
timer->SetTarget(aTarget);
|
||||
timer->InitWithFuncCallback(TimedOut, this, aDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Type aliases for NewRunnableMethod.
|
||||
template<typename PtrType, typename Method>
|
||||
using OwningRunnableMethod = typename ::nsRunnableMethodTraits<
|
||||
typename RemoveReference<PtrType>::Type, Method, true, false>::base_type;
|
||||
typename RemoveReference<PtrType>::Type, Method, true, Standard>::base_type;
|
||||
template<typename PtrType, typename Method, typename... Storages>
|
||||
using OwningRunnableMethodImpl = RunnableMethodImpl<
|
||||
typename RemoveReference<PtrType>::Type, Method, true, false, Storages...>;
|
||||
typename RemoveReference<PtrType>::Type, Method, true, Standard, Storages...>;
|
||||
|
||||
// Type aliases for NewCancelableRunnableMethod.
|
||||
template<typename PtrType, typename Method>
|
||||
using CancelableRunnableMethod = typename ::nsRunnableMethodTraits<
|
||||
typename RemoveReference<PtrType>::Type, Method, true, true>::base_type;
|
||||
typename RemoveReference<PtrType>::Type, Method, true, Cancelable>::base_type;
|
||||
template<typename PtrType, typename Method, typename... Storages>
|
||||
using CancelableRunnableMethodImpl = RunnableMethodImpl<
|
||||
typename RemoveReference<PtrType>::Type, Method, true, true, Storages...>;
|
||||
typename RemoveReference<PtrType>::Type, Method, true, Cancelable, Storages...>;
|
||||
|
||||
// Type aliases for NewIdleRunnableMethod.
|
||||
template<typename PtrType, typename Method>
|
||||
using IdleRunnableMethod = typename ::nsRunnableMethodTraits<
|
||||
typename RemoveReference<PtrType>::Type, Method, true, Idle>::base_type;
|
||||
template<typename PtrType, typename Method, typename... Storages>
|
||||
using IdleRunnableMethodImpl = RunnableMethodImpl<
|
||||
typename RemoveReference<PtrType>::Type, Method, true, Idle, Storages...>;
|
||||
|
||||
// Type aliases for NewIdleRunnableMethodWithTimer.
|
||||
template<typename PtrType, typename Method>
|
||||
using IdleRunnableMethodWithTimer = typename ::nsRunnableMethodTraits<
|
||||
typename RemoveReference<PtrType>::Type, Method, true, IdleWithTimer>::base_type;
|
||||
template<typename PtrType, typename Method, typename... Storages>
|
||||
using IdleRunnableMethodWithTimerImpl = RunnableMethodImpl<
|
||||
typename RemoveReference<PtrType>::Type, Method, true, IdleWithTimer, Storages...>;
|
||||
|
||||
// Type aliases for NewNonOwningRunnableMethod.
|
||||
template<typename PtrType, typename Method>
|
||||
using NonOwningRunnableMethod = typename ::nsRunnableMethodTraits<
|
||||
typename RemoveReference<PtrType>::Type, Method, false, false>::base_type;
|
||||
typename RemoveReference<PtrType>::Type, Method, false, Standard>::base_type;
|
||||
template<typename PtrType, typename Method, typename... Storages>
|
||||
using NonOwningRunnableMethodImpl = RunnableMethodImpl<
|
||||
typename RemoveReference<PtrType>::Type, Method, false, false, Storages...>;
|
||||
typename RemoveReference<PtrType>::Type, Method, false, Standard, Storages...>;
|
||||
|
||||
// Type aliases for NonOwningCancelableRunnableMethod
|
||||
template<typename PtrType, typename Method>
|
||||
using NonOwningCancelableRunnableMethod = typename ::nsRunnableMethodTraits<
|
||||
typename RemoveReference<PtrType>::Type, Method, false, true>::base_type;
|
||||
typename RemoveReference<PtrType>::Type, Method, false, Cancelable>::base_type;
|
||||
template<typename PtrType, typename Method, typename... Storages>
|
||||
using NonOwningCancelableRunnableMethodImpl = RunnableMethodImpl<
|
||||
typename RemoveReference<PtrType>::Type, Method, false, true, Storages...>;
|
||||
typename RemoveReference<PtrType>::Type, Method, false, Cancelable, Storages...>;
|
||||
|
||||
// Type aliases for NonOwningIdleRunnableMethod
|
||||
template<typename PtrType, typename Method>
|
||||
using NonOwningIdleRunnableMethod = typename ::nsRunnableMethodTraits<
|
||||
typename RemoveReference<PtrType>::Type, Method, false, Idle>::base_type;
|
||||
template<typename PtrType, typename Method, typename... Storages>
|
||||
using NonOwningIdleRunnableMethodImpl = RunnableMethodImpl<
|
||||
typename RemoveReference<PtrType>::Type, Method, false, Idle, Storages...>;
|
||||
|
||||
// Type aliases for NewIdleRunnableMethodWithTimer.
|
||||
template<typename PtrType, typename Method>
|
||||
using NonOwningIdleRunnableMethodWithTimer = typename ::nsRunnableMethodTraits<
|
||||
typename RemoveReference<PtrType>::Type, Method, false, IdleWithTimer>::base_type;
|
||||
template<typename PtrType, typename Method, typename... Storages>
|
||||
using NonOwningIdleRunnableMethodWithTimerImpl = RunnableMethodImpl<
|
||||
typename RemoveReference<PtrType>::Type, Method, false, IdleWithTimer, Storages...>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@ -1156,6 +1353,41 @@ NewCancelableRunnableMethod(const char* aName, PtrType&& aPtr, Method aMethod)
|
||||
NewCancelableRunnableMethod(Forward<PtrType>(aPtr), aMethod), aName);
|
||||
}
|
||||
|
||||
template<typename PtrType, typename Method>
|
||||
already_AddRefed<detail::IdleRunnableMethod<PtrType, Method>>
|
||||
NewIdleRunnableMethod(PtrType&& aPtr, Method aMethod)
|
||||
{
|
||||
return do_AddRef(new detail::IdleRunnableMethodImpl<PtrType, Method>(
|
||||
Forward<PtrType>(aPtr), aMethod));
|
||||
}
|
||||
|
||||
template<typename PtrType, typename Method>
|
||||
already_AddRefed<detail::IdleRunnableMethod<PtrType, Method>>
|
||||
NewIdleRunnableMethod(const char* aName, PtrType&& aPtr, Method aMethod)
|
||||
{
|
||||
return detail::SetRunnableName(
|
||||
NewIdleRunnableMethod(Forward<PtrType>(aPtr), aMethod), aName);
|
||||
}
|
||||
|
||||
template<typename PtrType, typename Method>
|
||||
already_AddRefed<detail::IdleRunnableMethodWithTimer<PtrType, Method>>
|
||||
NewIdleRunnableMethodWithTimer(PtrType&& aPtr, Method aMethod)
|
||||
{
|
||||
return do_AddRef(new detail::IdleRunnableMethodWithTimerImpl<PtrType, Method>(
|
||||
Forward<PtrType>(aPtr), aMethod));
|
||||
}
|
||||
|
||||
template<typename PtrType, typename Method>
|
||||
already_AddRefed<detail::IdleRunnableMethodWithTimer<PtrType, Method>>
|
||||
NewIdleRunnableMethodWithTimer(const char* aName,
|
||||
PtrType&& aPtr,
|
||||
Method aMethod)
|
||||
{
|
||||
return detail::SetRunnableName(
|
||||
NewIdleRunnableMethodWithTimer(Forward<PtrType>(aPtr), aMethod),
|
||||
aName);
|
||||
}
|
||||
|
||||
template<typename PtrType, typename Method>
|
||||
already_AddRefed<detail::NonOwningRunnableMethod<PtrType, Method>>
|
||||
NewNonOwningRunnableMethod(PtrType&& aPtr, Method aMethod)
|
||||
@ -1191,6 +1423,46 @@ NewNonOwningCancelableRunnableMethod(const char* aName, PtrType&& aPtr,
|
||||
NewNonOwningCancelableRunnableMethod(Forward<PtrType>(aPtr), aMethod), aName);
|
||||
}
|
||||
|
||||
template<typename PtrType, typename Method>
|
||||
already_AddRefed<detail::NonOwningIdleRunnableMethod<PtrType, Method>>
|
||||
NewNonOwningIdleRunnableMethod(PtrType&& aPtr, Method aMethod)
|
||||
{
|
||||
return do_AddRef(
|
||||
new detail::NonOwningIdleRunnableMethodImpl<PtrType, Method>(
|
||||
Forward<PtrType>(aPtr), aMethod));
|
||||
}
|
||||
|
||||
template<typename PtrType, typename Method>
|
||||
already_AddRefed<detail::NonOwningIdleRunnableMethod<PtrType, Method>>
|
||||
NewNonOwningIdleRunnableMethod(const char* aName,
|
||||
PtrType&& aPtr,
|
||||
Method aMethod)
|
||||
{
|
||||
return detail::SetRunnableName(
|
||||
NewNonOwningIdleRunnableMethod(Forward<PtrType>(aPtr), aMethod), aName);
|
||||
}
|
||||
|
||||
template<typename PtrType, typename Method>
|
||||
already_AddRefed<detail::NonOwningIdleRunnableMethodWithTimer<PtrType, Method>>
|
||||
NewNonOwningIdleRunnableMethodWithTimer(PtrType&& aPtr,
|
||||
Method aMethod)
|
||||
{
|
||||
return do_AddRef(
|
||||
new detail::NonOwningIdleRunnableMethodWithTimerImpl<PtrType, Method>(
|
||||
Forward<PtrType>(aPtr), aMethod));
|
||||
}
|
||||
|
||||
template<typename PtrType, typename Method>
|
||||
already_AddRefed<detail::NonOwningIdleRunnableMethodWithTimer<PtrType, Method>>
|
||||
NewNonOwningIdleRunnableMethodWithTimer(const char* aName,
|
||||
PtrType&& aPtr,
|
||||
Method aMethod)
|
||||
{
|
||||
return detail::SetRunnableName(NewNonOwningIdleRunnableMethodWithTimer(
|
||||
Forward<PtrType>(aPtr), aMethod),
|
||||
aName);
|
||||
}
|
||||
|
||||
// Similar to NewRunnableMethod. Call like so:
|
||||
// nsCOMPtr<nsIRunnable> event =
|
||||
// NewRunnableMethod<Types,...>(myObject, &MyClass::HandleEvent, myArg1,...);
|
||||
@ -1287,6 +1559,70 @@ NewNonOwningCancelableRunnableMethod(const char* aName, PtrType&& aPtr,
|
||||
(Forward<PtrType>(aPtr), aMethod, mozilla::Forward<Args>(aArgs)...), aName);
|
||||
}
|
||||
|
||||
template<typename... Storages,
|
||||
typename PtrType,
|
||||
typename Method,
|
||||
typename... Args>
|
||||
already_AddRefed<detail::IdleRunnableMethod<PtrType, Method>>
|
||||
NewIdleRunnableMethod(PtrType&& aPtr, Method aMethod, Args&&... aArgs)
|
||||
{
|
||||
static_assert(sizeof...(Storages) == sizeof...(Args),
|
||||
"<Storages...> size should be equal to number of arguments");
|
||||
return do_AddRef(
|
||||
new detail::IdleRunnableMethodImpl<PtrType, Method, Storages...>(
|
||||
Forward<PtrType>(aPtr), aMethod, mozilla::Forward<Args>(aArgs)...));
|
||||
}
|
||||
|
||||
template<typename... Storages,
|
||||
typename PtrType,
|
||||
typename Method,
|
||||
typename... Args>
|
||||
already_AddRefed<detail::IdleRunnableMethod<PtrType, Method>>
|
||||
NewIdleRunnableMethod(const char* aName,
|
||||
PtrType&& aPtr,
|
||||
Method aMethod,
|
||||
Args&&... aArgs)
|
||||
{
|
||||
static_assert(sizeof...(Storages) == sizeof...(Args),
|
||||
"<Storages...> size should be equal to number of arguments");
|
||||
return detail::SetRunnableName(
|
||||
NewIdleRunnableMethod<Storages...>(
|
||||
Forward<PtrType>(aPtr), aMethod, mozilla::Forward<Args>(aArgs)...),
|
||||
aName);
|
||||
}
|
||||
|
||||
template<typename... Storages,
|
||||
typename PtrType,
|
||||
typename Method,
|
||||
typename... Args>
|
||||
already_AddRefed<detail::NonOwningIdleRunnableMethod<PtrType, Method>>
|
||||
NewNonOwningIdleRunnableMethod(PtrType&& aPtr, Method aMethod, Args&&... aArgs)
|
||||
{
|
||||
static_assert(sizeof...(Storages) == sizeof...(Args),
|
||||
"<Storages...> size should be equal to number of arguments");
|
||||
return do_AddRef(
|
||||
new detail::NonOwningIdleRunnableMethodImpl<PtrType, Method, Storages...>(
|
||||
Forward<PtrType>(aPtr), aMethod, mozilla::Forward<Args>(aArgs)...));
|
||||
}
|
||||
|
||||
template<typename... Storages,
|
||||
typename PtrType,
|
||||
typename Method,
|
||||
typename... Args>
|
||||
already_AddRefed<detail::NonOwningIdleRunnableMethod<PtrType, Method>>
|
||||
NewNonOwningIdleRunnableMethod(const char* aName,
|
||||
PtrType&& aPtr,
|
||||
Method aMethod,
|
||||
Args&&... aArgs)
|
||||
{
|
||||
static_assert(sizeof...(Storages) == sizeof...(Args),
|
||||
"<Storages...> size should be equal to number of arguments");
|
||||
return detail::SetRunnableName(
|
||||
NewNonOwningIdleRunnableMethod<Storages...>(
|
||||
Forward<PtrType>(aPtr), aMethod, mozilla::Forward<Args>(aArgs)...),
|
||||
aName);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // XPCOM_GLUE_AVOID_NSPR
|
||||
|
Loading…
x
Reference in New Issue
Block a user