Bug 1361259. P2 - use NewRunnableMethod() to pass event data to the listener function. r=gerald

Note this breaks the MediaEventSource::CopyEvent2 gtest since there is always
one copy or move when storing the event data in the runnable created by
NewRunnableMethod() even when the listener function takes no arguments at all.

We will fix it later.

MozReview-Commit-ID: J9T63yxXko2

--HG--
extra : rebase_source : f15fa78129e562fb3a65027114095b205791d4c7
extra : source : e734b4d950c415be18e2fbc30e26e617758aa556
This commit is contained in:
JW Wang 2017-04-28 16:28:47 +08:00
Родитель 93fb1e26e2
Коммит 56feb1362b
1 изменённых файлов: 46 добавлений и 25 удалений

Просмотреть файл

@ -234,43 +234,64 @@ template <EventPassMode Mode, typename... As>
class Listener : public ListenerBase
{
public:
virtual void Dispatch(const As&... aEvents) = 0;
};
template <typename... Ts>
void Dispatch(Ts&&... aEvents)
{
DispatchTask(NewRunnableMethod<typename Decay<Ts>::Type&&...>(
this, &Listener::Apply, Forward<Ts>(aEvents)...));
}
template <typename... As>
class Listener<EventPassMode::Move, As...> : public ListenerBase
{
public:
virtual void Dispatch(As... aEvents) = 0;
private:
virtual void DispatchTask(already_AddRefed<nsIRunnable> aTask) = 0;
virtual void Apply(As&&... aEvents) = 0;
};
/**
* Store the registered target thread and function so it knows where and to
* whom to send the event data.
*/
template <typename Target, typename Function, EventPassMode, typename... As>
class ListenerImpl : public Listener<EventPassMode::Copy, As...> {
template <typename Target, typename Function, EventPassMode Mode, typename... As>
class ListenerImpl : public Listener<Mode, As...>
{
public:
ListenerImpl(Target* aTarget, const Function& aFunction)
: mHelper(this, aTarget, aFunction) {}
void Dispatch(const As&... aEvents) override {
mHelper.Dispatch(aEvents...);
: mTarget(aTarget)
, mFunction(aFunction)
{
}
private:
ListenerHelper<Target, Function> mHelper;
};
template <typename Target, typename Function, typename... As>
class ListenerImpl<Target, Function, EventPassMode::Move, As...>
: public Listener<EventPassMode::Move, As...> {
public:
ListenerImpl(Target* aTarget, const Function& aFunction)
: mHelper(this, aTarget, aFunction) {}
void Dispatch(As... aEvents) override {
mHelper.Dispatch(Move(aEvents)...);
}
private:
ListenerHelper<Target, Function> mHelper;
void DispatchTask(already_AddRefed<nsIRunnable> aTask) override
{
EventTarget<Target>::Dispatch(mTarget.get(), Move(aTask));
}
// |F| takes one or more arguments.
template <typename F>
typename EnableIf<TakeArgs<F>::value, void>::Type
ApplyImpl(const F& aFunc, As&&... aEvents)
{
aFunc(Move(aEvents)...);
}
// |F| takes no arguments. Don't bother passing aEvent.
template <typename F>
typename EnableIf<!TakeArgs<F>::value, void>::Type
ApplyImpl(const F& aFunc, As&&... aEvents)
{
aFunc();
}
void Apply(As&&... aEvents) override
{
// Don't call the listener if it is disconnected.
if (!RevocableToken::IsRevoked()) {
ApplyImpl(mFunction, Move(aEvents)...);
}
}
const RefPtr<Target> mTarget;
Function mFunction;
};
/**