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