Bug 968016 - Add methods to SharedThreadPools and MediaTaskQueues to report whether we're running on one of their threads. r=kinetik

This commit is contained in:
Chris Pearce 2014-02-18 11:53:52 +13:00
parent fbe22075af
commit 490247e674
4 changed files with 41 additions and 8 deletions

View File

@ -90,6 +90,17 @@ MediaTaskQueue::IsEmpty()
return mTasks.empty();
}
bool
MediaTaskQueue::IsCurrentThreadIn()
{
#ifdef DEBUG
MonitorAutoLock mon(mQueueMonitor);
return NS_GetCurrentThread() == mRunningThread;
#else
return false;
#endif
}
nsresult
MediaTaskQueue::Runner::Run()
{
@ -97,6 +108,7 @@ MediaTaskQueue::Runner::Run()
{
MonitorAutoLock mon(mQueue->mQueueMonitor);
MOZ_ASSERT(mQueue->mIsRunning);
mQueue->mRunningThread = NS_GetCurrentThread();
if (mQueue->mTasks.size() == 0) {
mQueue->mIsRunning = false;
mon.NotifyAll();
@ -120,6 +132,7 @@ MediaTaskQueue::Runner::Run()
// No more events to run. Exit the task runner.
mQueue->mIsRunning = false;
mon.NotifyAll();
mQueue->mRunningThread = nullptr;
return NS_OK;
}
}
@ -129,13 +142,20 @@ MediaTaskQueue::Runner::Run()
// run in a loop here so that we don't hog the thread pool. This means we may
// run on another thread next time, but we rely on the memory fences from
// mQueueMonitor for thread safety of non-threadsafe tasks.
nsresult rv = mQueue->mPool->Dispatch(this, NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
// Failed to dispatch, shutdown!
{
MonitorAutoLock mon(mQueue->mQueueMonitor);
mQueue->mIsRunning = false;
mQueue->mIsShutdown = true;
mon.NotifyAll();
// Note: Hold the monitor *before* we dispatch, in case we context switch
// to another thread pool in the queue immediately and take the lock in the
// other thread; mRunningThread could be set to the new thread's value and
// then incorrectly anulled below in that case.
nsresult rv = mQueue->mPool->Dispatch(this, NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
// Failed to dispatch, shutdown!
mQueue->mIsRunning = false;
mQueue->mIsShutdown = true;
mon.NotifyAll();
}
mQueue->mRunningThread = nullptr;
}
return NS_OK;

View File

@ -43,6 +43,10 @@ public:
bool IsEmpty();
// Returns true if the current thread is currently running a Runnable in
// the task queue. This is for debugging/validation purposes only.
bool IsCurrentThreadIn();
private:
// Blocks until all task finish executing. Called internally by methods
@ -58,6 +62,11 @@ private:
// Queue of tasks to run.
std::queue<RefPtr<nsIRunnable>> mTasks;
// The thread currently running the task queue. We store a reference
// to this so that IsCurrentThreadIn() can tell if the current thread
// is the thread currently running in the task queue.
RefPtr<nsIThread> mRunningThread;
// True if we've dispatched an event to the pool to execute events from
// the queue.
bool mIsRunning;

View File

@ -155,7 +155,7 @@ NS_IMETHODIMP_(nsrefcnt) SharedThreadPool::Release(void)
return 0;
}
NS_IMPL_QUERY_INTERFACE1(SharedThreadPool, nsIThreadPool)
NS_IMPL_QUERY_INTERFACE2(SharedThreadPool, nsIThreadPool, nsIEventTarget)
SharedThreadPool::SharedThreadPool(const nsCString& aName,
nsIThreadPool* aPool)

View File

@ -44,7 +44,11 @@ public:
// Forward behaviour to wrapped thread pool implementation.
NS_FORWARD_SAFE_NSITHREADPOOL(mPool);
NS_FORWARD_SAFE_NSIEVENTTARGET(mEventTarget);
NS_FORWARD_SAFE_NSIEVENTTARGET(GetEventTarget());
nsIEventTarget* GetEventTarget() {
return mEventTarget;
}
private: