Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "JobScheduler.h"
7 : #include "mozilla/gfx/Logging.h"
8 :
9 : using namespace std;
10 :
11 : namespace mozilla {
12 : namespace gfx {
13 :
14 : void* ThreadCallback(void* threadData);
15 :
16 : class WorkerThreadPosix : public WorkerThread {
17 : public:
18 0 : explicit WorkerThreadPosix(MultiThreadedJobQueue* aJobQueue)
19 0 : : WorkerThread(aJobQueue)
20 : {
21 0 : pthread_create(&mThread, nullptr, ThreadCallback, static_cast<WorkerThread*>(this));
22 0 : }
23 :
24 0 : ~WorkerThreadPosix() override
25 0 : {
26 0 : pthread_join(mThread, nullptr);
27 0 : }
28 :
29 0 : void SetName(const char*) override
30 : {
31 : // XXX - temporarily disabled, see bug 1209039
32 : //
33 : // // Call this from the thread itself because of Mac.
34 : //#ifdef XP_MACOSX
35 : // pthread_setname_np(aName);
36 : //#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
37 : // pthread_set_name_np(mThread, aName);
38 : //#elif defined(__NetBSD__)
39 : // pthread_setname_np(mThread, "%s", (void*)aName);
40 : //#else
41 : // pthread_setname_np(mThread, aName);
42 : //#endif
43 0 : }
44 :
45 : protected:
46 : pthread_t mThread;
47 : };
48 :
49 0 : void* ThreadCallback(void* threadData)
50 : {
51 0 : WorkerThread* thread = static_cast<WorkerThread*>(threadData);
52 0 : thread->Run();
53 0 : return nullptr;
54 : }
55 :
56 : WorkerThread*
57 0 : WorkerThread::Create(MultiThreadedJobQueue* aJobQueue)
58 : {
59 0 : return new WorkerThreadPosix(aJobQueue);
60 : }
61 :
62 0 : MultiThreadedJobQueue::MultiThreadedJobQueue()
63 : : mThreadsCount(0)
64 0 : , mShuttingDown(false)
65 0 : {}
66 :
67 0 : MultiThreadedJobQueue::~MultiThreadedJobQueue()
68 : {
69 0 : MOZ_ASSERT(mJobs.empty());
70 0 : }
71 :
72 : bool
73 0 : MultiThreadedJobQueue::WaitForJob(Job*& aOutJob)
74 : {
75 0 : return PopJob(aOutJob, BLOCKING);
76 : }
77 :
78 : bool
79 0 : MultiThreadedJobQueue::PopJob(Job*& aOutJobs, AccessType aAccess)
80 : {
81 : for (;;) {
82 0 : CriticalSectionAutoEnter lock(&mMutex);
83 :
84 0 : while (aAccess == BLOCKING && !mShuttingDown && mJobs.empty()) {
85 0 : mAvailableCondvar.Wait(&mMutex);
86 : }
87 :
88 0 : if (mShuttingDown) {
89 0 : return false;
90 : }
91 :
92 0 : if (mJobs.empty()) {
93 0 : if (aAccess == NON_BLOCKING) {
94 0 : return false;
95 : }
96 0 : continue;
97 : }
98 :
99 0 : Job* task = mJobs.front();
100 0 : MOZ_ASSERT(task);
101 :
102 0 : mJobs.pop_front();
103 :
104 0 : aOutJobs = task;
105 0 : return true;
106 0 : }
107 : }
108 :
109 : void
110 0 : MultiThreadedJobQueue::SubmitJob(Job* aJobs)
111 : {
112 0 : MOZ_ASSERT(aJobs);
113 0 : CriticalSectionAutoEnter lock(&mMutex);
114 0 : mJobs.push_back(aJobs);
115 0 : mAvailableCondvar.Broadcast();
116 0 : }
117 :
118 : size_t
119 0 : MultiThreadedJobQueue::NumJobs()
120 : {
121 0 : CriticalSectionAutoEnter lock(&mMutex);
122 0 : return mJobs.size();
123 : }
124 :
125 : bool
126 0 : MultiThreadedJobQueue::IsEmpty()
127 : {
128 0 : CriticalSectionAutoEnter lock(&mMutex);
129 0 : return mJobs.empty();
130 : }
131 :
132 : void
133 0 : MultiThreadedJobQueue::ShutDown()
134 : {
135 0 : CriticalSectionAutoEnter lock(&mMutex);
136 0 : mShuttingDown = true;
137 0 : while (mThreadsCount) {
138 0 : mAvailableCondvar.Broadcast();
139 0 : mShutdownCondvar.Wait(&mMutex);
140 : }
141 0 : }
142 :
143 : void
144 0 : MultiThreadedJobQueue::RegisterThread()
145 : {
146 0 : mThreadsCount += 1;
147 0 : }
148 :
149 : void
150 0 : MultiThreadedJobQueue::UnregisterThread()
151 : {
152 0 : CriticalSectionAutoEnter lock(&mMutex);
153 0 : mThreadsCount -= 1;
154 0 : if (mThreadsCount == 0) {
155 0 : mShutdownCondvar.Broadcast();
156 : }
157 0 : }
158 :
159 0 : EventObject::EventObject()
160 0 : : mIsSet(false)
161 0 : {}
162 :
163 : EventObject::~EventObject() = default;
164 :
165 : bool
166 0 : EventObject::Peak()
167 : {
168 0 : CriticalSectionAutoEnter lock(&mMutex);
169 0 : return mIsSet;
170 : }
171 :
172 : void
173 0 : EventObject::Set()
174 : {
175 0 : CriticalSectionAutoEnter lock(&mMutex);
176 0 : if (!mIsSet) {
177 0 : mIsSet = true;
178 0 : mCond.Broadcast();
179 : }
180 0 : }
181 :
182 : void
183 0 : EventObject::Wait()
184 : {
185 0 : CriticalSectionAutoEnter lock(&mMutex);
186 0 : if (mIsSet) {
187 0 : return;
188 : }
189 0 : mCond.Wait(&mMutex);
190 : }
191 :
192 : } // namespce
193 : } // namespce
|