Bug 1425904 - Make the monitor refcounted. r=gerald

To prevent another heap allocation, we re-use the TaskQueue internal monitor.
As a TaskQueue is refcounted, and the MozPromise::Then() holds a reference to the taskqueue, it ensures that the monitor isn't immediately destroyed when Await() execution unwinds.
Instead it will live until either the lambda or Await() completes, whichever comes last.

MozReview-Commit-ID: EeG6LLAiiyp

--HG--
extra : rebase_source : c5872733c0444737682632dd10d8844c44c4d429
This commit is contained in:
Jean-Yves Avenard 2017-12-19 11:11:23 +01:00
parent fd655b880c
commit b8cd152890
2 changed files with 19 additions and 8 deletions

View File

@ -21,16 +21,20 @@ class AutoTaskQueue : public AbstractThread
public:
explicit AutoTaskQueue(already_AddRefed<nsIEventTarget> aPool,
bool aSupportsTailDispatch = false)
: AbstractThread(aSupportsTailDispatch)
, mTaskQueue(new TaskQueue(Move(aPool), aSupportsTailDispatch))
{}
: AbstractThread(aSupportsTailDispatch)
, mTaskQueue(new TaskQueue(Move(aPool), aSupportsTailDispatch))
, mMonitor("AutoTaskQueue")
{
}
AutoTaskQueue(already_AddRefed<nsIEventTarget> aPool,
const char* aName,
bool aSupportsTailDispatch = false)
: AbstractThread(aSupportsTailDispatch)
, mTaskQueue(new TaskQueue(Move(aPool), aName, aSupportsTailDispatch))
{}
: AbstractThread(aSupportsTailDispatch)
, mTaskQueue(new TaskQueue(Move(aPool), aName, aSupportsTailDispatch))
, mMonitor("AutoTaskQueue")
{
}
TaskDispatcher& TailDispatcher() override
{
@ -56,9 +60,12 @@ public:
// the task queue.
bool IsCurrentThreadIn() override { return mTaskQueue->IsCurrentThreadIn(); }
mozilla::Monitor& Monitor() { return mMonitor; }
private:
~AutoTaskQueue() { mTaskQueue->BeginShutdown(); }
RefPtr<TaskQueue> mTaskQueue;
mozilla::Monitor mMonitor;
};
} // namespace mozilla

View File

@ -424,6 +424,8 @@ private:
* provided by the monitor.
* For now Await can only be used with an exclusive MozPromise if passed a
* Resolve/Reject function.
* Await() can *NOT* be called from a task queue/nsISerialEventTarget used for
* resolving/rejecting aPromise, otherwise things will deadlock.
*/
template<typename ResolveValueType,
typename RejectValueType,
@ -436,9 +438,10 @@ Await(
ResolveFunction&& aResolveFunction,
RejectFunction&& aRejectFunction)
{
Monitor mon(__func__);
RefPtr<AutoTaskQueue> taskQueue =
new AutoTaskQueue(Move(aPool), "MozPromiseAwait");
// We can't use a Monitor allocated on the stack (see bug 1426067)
Monitor& mon = taskQueue->Monitor();
bool done = false;
aPromise->Then(taskQueue,
@ -468,9 +471,10 @@ typename MozPromise<ResolveValueType, RejectValueType, Excl>::
Await(already_AddRefed<nsIEventTarget> aPool,
RefPtr<MozPromise<ResolveValueType, RejectValueType, Excl>> aPromise)
{
Monitor mon(__func__);
RefPtr<AutoTaskQueue> taskQueue =
new AutoTaskQueue(Move(aPool), "MozPromiseAwait");
// We can't use a Monitor allocated on the stack (see bug 1426067)
Monitor& mon = taskQueue->Monitor();
bool done = false;
typename MozPromise<ResolveValueType, RejectValueType, Excl>::ResolveOrRejectValue val;