Bug 1195767 - part 3 - modify nsThreadPool to use a non-reentrant monitor; r=gerald

There's no reason nsThreadPool needs to use a reentrant monitor for
locking its event queue.  Having it use a non-reentrant one should be
slightly more efficient, both in the general operation of the monitor,
and that we're not performing redundant locking in methods like
nsThreadPool::Run.  This change also eliminates the only usage of
nsEventQueue::GetReentrantMonitor.
This commit is contained in:
Nathan Froyd 2015-09-03 15:38:28 -04:00
parent 92e6eccda2
commit aafe5d489a
2 changed files with 30 additions and 23 deletions

View File

@ -48,13 +48,15 @@ NS_IMPL_QUERY_INTERFACE_CI(nsThreadPool, nsIThreadPool, nsIEventTarget,
NS_IMPL_CI_INTERFACE_GETTER(nsThreadPool, nsIThreadPool, nsIEventTarget)
nsThreadPool::nsThreadPool()
: mThreadLimit(DEFAULT_THREAD_LIMIT)
: mMonitor("[nsThreadPool.mMonitor]")
, mThreadLimit(DEFAULT_THREAD_LIMIT)
, mIdleThreadLimit(DEFAULT_IDLE_THREAD_LIMIT)
, mIdleThreadTimeout(DEFAULT_IDLE_THREAD_TIMEOUT)
, mIdleCount(0)
, mStackSize(nsIThreadManager::DEFAULT_STACK_SIZE)
, mShutdown(false)
{
LOG(("THRD-P(%p) constructor!!!\n", this));
}
nsThreadPool::~nsThreadPool()
@ -79,7 +81,7 @@ nsThreadPool::PutEvent(already_AddRefed<nsIRunnable>&& aEvent)
bool spawnThread = false;
uint32_t stackSize = 0;
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
if (NS_WARN_IF(mShutdown)) {
return NS_ERROR_NOT_AVAILABLE;
@ -92,11 +94,11 @@ nsThreadPool::PutEvent(already_AddRefed<nsIRunnable>&& aEvent)
if (mThreads.Count() < (int32_t)mThreadLimit &&
// Spawn a new thread if we don't have enough idle threads to serve
// pending events immediately.
mEvents.Count() >= mIdleCount) {
mEvents.Count(mon) >= mIdleCount) {
spawnThread = true;
}
mEvents.PutEvent(Move(aEvent));
mEvents.PutEvent(Move(aEvent), mon);
stackSize = mStackSize;
}
@ -115,7 +117,7 @@ nsThreadPool::PutEvent(already_AddRefed<nsIRunnable>&& aEvent)
bool killThread = false;
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
if (mThreads.Count() < (int32_t)mThreadLimit) {
mThreads.AppendObject(thread);
} else {
@ -157,10 +159,10 @@ nsThreadPool::ShutdownThread(nsIThread* aThread)
NS_IMETHODIMP
nsThreadPool::Run()
{
LOG(("THRD-P(%p) enter\n", this));
mThreadNaming.SetThreadPoolName(mName);
LOG(("THRD-P(%p) enter %s\n", this, mName.BeginReading()));
nsCOMPtr<nsIThread> current;
nsThreadManager::get()->GetCurrentThread(getter_AddRefs(current));
@ -171,7 +173,7 @@ nsThreadPool::Run()
nsCOMPtr<nsIThreadPoolListener> listener;
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
listener = mListener;
}
@ -182,8 +184,8 @@ nsThreadPool::Run()
do {
nsCOMPtr<nsIRunnable> event;
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
if (!mEvents.GetPendingEvent(getter_AddRefs(event))) {
MonitorAutoLock mon(mMonitor);
if (!mEvents.GetPendingEvent(getter_AddRefs(event), mon)) {
PRIntervalTime now = PR_IntervalNow();
PRIntervalTime timeout = PR_MillisecondsToInterval(mIdleThreadTimeout);
@ -215,8 +217,9 @@ nsThreadPool::Run()
shutdownThreadOnExit = mThreads.RemoveObject(current);
} else {
PRIntervalTime delta = timeout - (now - idleSince);
LOG(("THRD-P(%p) waiting [%d]\n", this, delta));
LOG(("THRD-P(%p) %s waiting [%d]\n", this, mName.BeginReading(), delta));
mon.Wait(delta);
LOG(("THRD-P(%p) done waiting\n", this));
}
} else if (wasIdle) {
wasIdle = false;
@ -224,7 +227,7 @@ nsThreadPool::Run()
}
}
if (event) {
LOG(("THRD-P(%p) running [%p]\n", this, event.get()));
LOG(("THRD-P(%p) %s running [%p]\n", this, mName.BeginReading(), event.get()));
event->Run();
}
} while (!exitThread);
@ -281,7 +284,7 @@ nsThreadPool::Dispatch(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFlags)
NS_IMETHODIMP
nsThreadPool::IsOnCurrentThread(bool* aResult)
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
if (NS_WARN_IF(mShutdown)) {
return NS_ERROR_NOT_AVAILABLE;
}
@ -303,7 +306,7 @@ nsThreadPool::Shutdown()
nsCOMArray<nsIThread> threads;
nsCOMPtr<nsIThreadPoolListener> listener;
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
mShutdown = true;
mon.NotifyAll();
@ -336,7 +339,8 @@ nsThreadPool::GetThreadLimit(uint32_t* aValue)
NS_IMETHODIMP
nsThreadPool::SetThreadLimit(uint32_t aValue)
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
LOG(("THRD-P(%p) thread limit [%u]\n", this, aValue));
mThreadLimit = aValue;
if (mIdleThreadLimit > mThreadLimit) {
mIdleThreadLimit = mThreadLimit;
@ -358,7 +362,8 @@ nsThreadPool::GetIdleThreadLimit(uint32_t* aValue)
NS_IMETHODIMP
nsThreadPool::SetIdleThreadLimit(uint32_t aValue)
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
LOG(("THRD-P(%p) idle thread limit [%u]\n", this, aValue));
mIdleThreadLimit = aValue;
if (mIdleThreadLimit > mThreadLimit) {
mIdleThreadLimit = mThreadLimit;
@ -381,7 +386,7 @@ nsThreadPool::GetIdleThreadTimeout(uint32_t* aValue)
NS_IMETHODIMP
nsThreadPool::SetIdleThreadTimeout(uint32_t aValue)
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
uint32_t oldTimeout = mIdleThreadTimeout;
mIdleThreadTimeout = aValue;
@ -395,7 +400,7 @@ nsThreadPool::SetIdleThreadTimeout(uint32_t aValue)
NS_IMETHODIMP
nsThreadPool::GetThreadStackSize(uint32_t* aValue)
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
*aValue = mStackSize;
return NS_OK;
}
@ -403,7 +408,7 @@ nsThreadPool::GetThreadStackSize(uint32_t* aValue)
NS_IMETHODIMP
nsThreadPool::SetThreadStackSize(uint32_t aValue)
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
mStackSize = aValue;
return NS_OK;
}
@ -411,7 +416,7 @@ nsThreadPool::SetThreadStackSize(uint32_t aValue)
NS_IMETHODIMP
nsThreadPool::GetListener(nsIThreadPoolListener** aListener)
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
NS_IF_ADDREF(*aListener = mListener);
return NS_OK;
}
@ -421,7 +426,7 @@ nsThreadPool::SetListener(nsIThreadPoolListener* aListener)
{
nsCOMPtr<nsIThreadPoolListener> swappedListener(aListener);
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
mListener.swap(swappedListener);
}
return NS_OK;
@ -431,7 +436,7 @@ NS_IMETHODIMP
nsThreadPool::SetName(const nsACString& aName)
{
{
ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
MonitorAutoLock mon(mMonitor);
if (mThreads.Count()) {
return NS_ERROR_NOT_AVAILABLE;
}

View File

@ -16,6 +16,7 @@
#include "nsThreadUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Monitor.h"
class nsThreadPool final
: public nsIThreadPool
@ -41,7 +42,8 @@ private:
nsresult PutEvent(already_AddRefed<nsIRunnable>&& aEvent);
nsCOMArray<nsIThread> mThreads;
nsEventQueue mEvents;
mozilla::Monitor mMonitor;
nsEventQueueBase<mozilla::Monitor> mEvents;
uint32_t mThreadLimit;
uint32_t mIdleThreadLimit;
uint32_t mIdleThreadTimeout;