|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "nsPSMBackgroundThread.h" |
|
6 #include "nsThreadUtils.h" |
|
7 |
|
8 using namespace mozilla; |
|
9 |
|
10 void nsPSMBackgroundThread::nsThreadRunner(void *arg) |
|
11 { |
|
12 nsPSMBackgroundThread *self = static_cast<nsPSMBackgroundThread *>(arg); |
|
13 PR_SetCurrentThreadName(self->mName.BeginReading()); |
|
14 self->Run(); |
|
15 } |
|
16 |
|
17 nsPSMBackgroundThread::nsPSMBackgroundThread() |
|
18 : mThreadHandle(nullptr), |
|
19 mMutex("nsPSMBackgroundThread.mMutex"), |
|
20 mCond(mMutex, "nsPSMBackgroundThread.mCond"), |
|
21 mExitState(ePSMThreadRunning) |
|
22 { |
|
23 } |
|
24 |
|
25 nsresult nsPSMBackgroundThread::startThread(const nsCSubstring & name) |
|
26 { |
|
27 mName = name; |
|
28 |
|
29 mThreadHandle = PR_CreateThread(PR_USER_THREAD, nsThreadRunner, static_cast<void*>(this), |
|
30 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); |
|
31 |
|
32 NS_ASSERTION(mThreadHandle, "Could not create nsPSMBackgroundThread\n"); |
|
33 |
|
34 if (!mThreadHandle) |
|
35 return NS_ERROR_OUT_OF_MEMORY; |
|
36 |
|
37 return NS_OK; |
|
38 } |
|
39 |
|
40 nsPSMBackgroundThread::~nsPSMBackgroundThread() |
|
41 { |
|
42 } |
|
43 |
|
44 bool |
|
45 nsPSMBackgroundThread::exitRequested(const MutexAutoLock & /*proofOfLock*/) const |
|
46 { |
|
47 return exitRequestedNoLock(); |
|
48 } |
|
49 |
|
50 nsresult |
|
51 nsPSMBackgroundThread::postStoppedEventToMainThread( |
|
52 MutexAutoLock const & /*proofOfLock*/) |
|
53 { |
|
54 NS_ASSERTION(PR_GetCurrentThread() == mThreadHandle, |
|
55 "Background thread stopped from another thread"); |
|
56 |
|
57 mExitState = ePSMThreadStopped; |
|
58 // requestExit is waiting for an event, so give it one. |
|
59 return NS_DispatchToMainThread(new nsRunnable()); |
|
60 } |
|
61 |
|
62 void nsPSMBackgroundThread::requestExit() |
|
63 { |
|
64 NS_ASSERTION(NS_IsMainThread(), |
|
65 "nsPSMBackgroundThread::requestExit called off main thread."); |
|
66 |
|
67 if (!mThreadHandle) |
|
68 return; |
|
69 |
|
70 { |
|
71 MutexAutoLock threadLock(mMutex); |
|
72 if (mExitState < ePSMThreadStopRequested) { |
|
73 mExitState = ePSMThreadStopRequested; |
|
74 mCond.NotifyAll(); |
|
75 } |
|
76 } |
|
77 |
|
78 nsCOMPtr<nsIThread> mainThread = do_GetCurrentThread(); |
|
79 for (;;) { |
|
80 { |
|
81 MutexAutoLock threadLock(mMutex); |
|
82 if (mExitState == ePSMThreadStopped) |
|
83 break; |
|
84 } |
|
85 NS_ProcessPendingEvents(mainThread, PR_MillisecondsToInterval(50)); |
|
86 } |
|
87 |
|
88 PR_JoinThread(mThreadHandle); |
|
89 mThreadHandle = nullptr; |
|
90 } |