michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsPSMBackgroundThread.h" michael@0: #include "nsThreadUtils.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: void nsPSMBackgroundThread::nsThreadRunner(void *arg) michael@0: { michael@0: nsPSMBackgroundThread *self = static_cast(arg); michael@0: PR_SetCurrentThreadName(self->mName.BeginReading()); michael@0: self->Run(); michael@0: } michael@0: michael@0: nsPSMBackgroundThread::nsPSMBackgroundThread() michael@0: : mThreadHandle(nullptr), michael@0: mMutex("nsPSMBackgroundThread.mMutex"), michael@0: mCond(mMutex, "nsPSMBackgroundThread.mCond"), michael@0: mExitState(ePSMThreadRunning) michael@0: { michael@0: } michael@0: michael@0: nsresult nsPSMBackgroundThread::startThread(const nsCSubstring & name) michael@0: { michael@0: mName = name; michael@0: michael@0: mThreadHandle = PR_CreateThread(PR_USER_THREAD, nsThreadRunner, static_cast(this), michael@0: PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); michael@0: michael@0: NS_ASSERTION(mThreadHandle, "Could not create nsPSMBackgroundThread\n"); michael@0: michael@0: if (!mThreadHandle) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsPSMBackgroundThread::~nsPSMBackgroundThread() michael@0: { michael@0: } michael@0: michael@0: bool michael@0: nsPSMBackgroundThread::exitRequested(const MutexAutoLock & /*proofOfLock*/) const michael@0: { michael@0: return exitRequestedNoLock(); michael@0: } michael@0: michael@0: nsresult michael@0: nsPSMBackgroundThread::postStoppedEventToMainThread( michael@0: MutexAutoLock const & /*proofOfLock*/) michael@0: { michael@0: NS_ASSERTION(PR_GetCurrentThread() == mThreadHandle, michael@0: "Background thread stopped from another thread"); michael@0: michael@0: mExitState = ePSMThreadStopped; michael@0: // requestExit is waiting for an event, so give it one. michael@0: return NS_DispatchToMainThread(new nsRunnable()); michael@0: } michael@0: michael@0: void nsPSMBackgroundThread::requestExit() michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), michael@0: "nsPSMBackgroundThread::requestExit called off main thread."); michael@0: michael@0: if (!mThreadHandle) michael@0: return; michael@0: michael@0: { michael@0: MutexAutoLock threadLock(mMutex); michael@0: if (mExitState < ePSMThreadStopRequested) { michael@0: mExitState = ePSMThreadStopRequested; michael@0: mCond.NotifyAll(); michael@0: } michael@0: } michael@0: michael@0: nsCOMPtr mainThread = do_GetCurrentThread(); michael@0: for (;;) { michael@0: { michael@0: MutexAutoLock threadLock(mMutex); michael@0: if (mExitState == ePSMThreadStopped) michael@0: break; michael@0: } michael@0: NS_ProcessPendingEvents(mainThread, PR_MillisecondsToInterval(50)); michael@0: } michael@0: michael@0: PR_JoinThread(mThreadHandle); michael@0: mThreadHandle = nullptr; michael@0: }