OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 #else | 85 #else |
86 struct ThreadAttributes { | 86 struct ThreadAttributes { |
87 ThreadAttributes() { pthread_attr_init(&attr); } | 87 ThreadAttributes() { pthread_attr_init(&attr); } |
88 ~ThreadAttributes() { pthread_attr_destroy(&attr); } | 88 ~ThreadAttributes() { pthread_attr_destroy(&attr); } |
89 pthread_attr_t* operator&() { return &attr; } | 89 pthread_attr_t* operator&() { return &attr; } |
90 pthread_attr_t attr; | 90 pthread_attr_t attr; |
91 }; | 91 }; |
92 #endif // defined(WEBRTC_WIN) | 92 #endif // defined(WEBRTC_WIN) |
93 } | 93 } |
94 | 94 |
| 95 PlatformThread::PlatformThread(ThreadRunFunctionDeprecated func, |
| 96 void* obj, |
| 97 const char* thread_name) |
| 98 : run_function_deprecated_(func), |
| 99 obj_(obj), |
| 100 name_(thread_name ? thread_name : "webrtc") { |
| 101 RTC_DCHECK(func); |
| 102 RTC_DCHECK(name_.length() < 64); |
| 103 spawned_thread_checker_.DetachFromThread(); |
| 104 } |
| 105 |
95 PlatformThread::PlatformThread(ThreadRunFunction func, | 106 PlatformThread::PlatformThread(ThreadRunFunction func, |
96 void* obj, | 107 void* obj, |
97 const char* thread_name) | 108 const char* thread_name, |
98 : run_function_(func), | 109 ThreadPriority priority /*= kNormalPriority*/) |
99 obj_(obj), | 110 : run_function_(func), priority_(priority), obj_(obj), name_(thread_name) { |
100 name_(thread_name ? thread_name : "webrtc") { | |
101 RTC_DCHECK(func); | 111 RTC_DCHECK(func); |
| 112 RTC_DCHECK(!name_.empty()); |
| 113 // TODO(tommi): Consider lowering the limit to 15 (limit on Linux). |
102 RTC_DCHECK(name_.length() < 64); | 114 RTC_DCHECK(name_.length() < 64); |
| 115 spawned_thread_checker_.DetachFromThread(); |
103 } | 116 } |
104 | 117 |
105 PlatformThread::~PlatformThread() { | 118 PlatformThread::~PlatformThread() { |
106 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 119 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
107 #if defined(WEBRTC_WIN) | 120 #if defined(WEBRTC_WIN) |
108 RTC_DCHECK(!thread_); | 121 RTC_DCHECK(!thread_); |
109 RTC_DCHECK(!thread_id_); | 122 RTC_DCHECK(!thread_id_); |
110 #endif // defined(WEBRTC_WIN) | 123 #endif // defined(WEBRTC_WIN) |
111 } | 124 } |
112 | 125 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 #if defined(WEBRTC_WIN) | 186 #if defined(WEBRTC_WIN) |
174 // Set stop_ to |true| on the worker thread. | 187 // Set stop_ to |true| on the worker thread. |
175 bool queued = QueueAPC(&RaiseFlag, reinterpret_cast<ULONG_PTR>(&stop_)); | 188 bool queued = QueueAPC(&RaiseFlag, reinterpret_cast<ULONG_PTR>(&stop_)); |
176 // Queuing the APC can fail if the thread is being terminated. | 189 // Queuing the APC can fail if the thread is being terminated. |
177 RTC_CHECK(queued || GetLastError() == ERROR_GEN_FAILURE); | 190 RTC_CHECK(queued || GetLastError() == ERROR_GEN_FAILURE); |
178 WaitForSingleObject(thread_, INFINITE); | 191 WaitForSingleObject(thread_, INFINITE); |
179 CloseHandle(thread_); | 192 CloseHandle(thread_); |
180 thread_ = nullptr; | 193 thread_ = nullptr; |
181 thread_id_ = 0; | 194 thread_id_ = 0; |
182 #else | 195 #else |
183 RTC_CHECK_EQ(1, AtomicOps::Increment(&stop_flag_)); | 196 if (!run_function_) |
| 197 RTC_CHECK_EQ(1, AtomicOps::Increment(&stop_flag_)); |
184 RTC_CHECK_EQ(0, pthread_join(thread_, nullptr)); | 198 RTC_CHECK_EQ(0, pthread_join(thread_, nullptr)); |
185 AtomicOps::ReleaseStore(&stop_flag_, 0); | 199 if (!run_function_) |
| 200 AtomicOps::ReleaseStore(&stop_flag_, 0); |
186 thread_ = 0; | 201 thread_ = 0; |
187 #endif // defined(WEBRTC_WIN) | 202 #endif // defined(WEBRTC_WIN) |
| 203 spawned_thread_checker_.DetachFromThread(); |
188 } | 204 } |
189 | 205 |
190 // TODO(tommi): Deprecate the loop behavior in PlatformThread. | 206 // TODO(tommi): Deprecate the loop behavior in PlatformThread. |
191 // * Introduce a new callback type that returns void. | 207 // * Introduce a new callback type that returns void. |
192 // * Remove potential for a busy loop in PlatformThread. | 208 // * Remove potential for a busy loop in PlatformThread. |
193 // * Delegate the responsibility for how to stop the thread, to the | 209 // * Delegate the responsibility for how to stop the thread, to the |
194 // implementation that actually uses the thread. | 210 // implementation that actually uses the thread. |
195 // All implementations will need to be aware of how the thread should be stopped | 211 // All implementations will need to be aware of how the thread should be stopped |
196 // and encouraging a busy polling loop, can be costly in terms of power and cpu. | 212 // and encouraging a busy polling loop, can be costly in terms of power and cpu. |
197 void PlatformThread::Run() { | 213 void PlatformThread::Run() { |
198 if (!name_.empty()) | 214 // Attach the worker thread checker to this thread. |
199 rtc::SetCurrentThreadName(name_.c_str()); | 215 RTC_DCHECK(spawned_thread_checker_.CalledOnValidThread()); |
| 216 rtc::SetCurrentThreadName(name_.c_str()); |
| 217 |
| 218 if (run_function_) { |
| 219 SetPriority(priority_); |
| 220 run_function_(obj_); |
| 221 return; |
| 222 } |
| 223 // TODO(tommi): Delete the below. |
200 #if !defined(WEBRTC_MAC) && !defined(WEBRTC_WIN) | 224 #if !defined(WEBRTC_MAC) && !defined(WEBRTC_WIN) |
201 const struct timespec ts_null = {0}; | 225 const struct timespec ts_null = {0}; |
202 #endif | 226 #endif |
203 do { | 227 do { |
204 // The interface contract of Start/Stop is that for a successful call to | 228 // The interface contract of Start/Stop is that for a successful call to |
205 // Start, there should be at least one call to the run function. So we | 229 // Start, there should be at least one call to the run function. So we |
206 // call the function before checking |stop_|. | 230 // call the function before checking |stop_|. |
207 if (!run_function_(obj_)) | 231 if (!run_function_deprecated_(obj_)) |
208 break; | 232 break; |
209 #if defined(WEBRTC_WIN) | 233 #if defined(WEBRTC_WIN) |
210 // Alertable sleep to permit RaiseFlag to run and update |stop_|. | 234 // Alertable sleep to permit RaiseFlag to run and update |stop_|. |
211 SleepEx(0, true); | 235 SleepEx(0, true); |
212 } while (!stop_); | 236 } while (!stop_); |
213 #else | 237 #else |
214 #if defined(WEBRTC_MAC) | 238 #if defined(WEBRTC_MAC) |
215 sched_yield(); | 239 sched_yield(); |
216 #else | 240 #else |
217 nanosleep(&ts_null, nullptr); | 241 nanosleep(&ts_null, nullptr); |
218 #endif | 242 #endif |
219 } while (!AtomicOps::AcquireLoad(&stop_flag_)); | 243 } while (!AtomicOps::AcquireLoad(&stop_flag_)); |
220 #endif // defined(WEBRTC_WIN) | 244 #endif // defined(WEBRTC_WIN) |
221 } | 245 } |
222 | 246 |
223 bool PlatformThread::SetPriority(ThreadPriority priority) { | 247 bool PlatformThread::SetPriority(ThreadPriority priority) { |
224 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 248 #if RTC_DCHECK_IS_ON |
225 RTC_DCHECK(IsRunning()); | 249 if (run_function_) { |
| 250 // The non-deprecated way of how this function gets called, is that it must |
| 251 // be called on the worker thread itself. |
| 252 RTC_DCHECK(spawned_thread_checker_.CalledOnValidThread()); |
| 253 } else { |
| 254 // In the case of deprecated use of this method, it must be called on the |
| 255 // same thread as the PlatformThread object is constructed on. |
| 256 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 257 RTC_DCHECK(IsRunning()); |
| 258 } |
| 259 #endif |
| 260 |
226 #if defined(WEBRTC_WIN) | 261 #if defined(WEBRTC_WIN) |
227 return SetThreadPriority(thread_, priority) != FALSE; | 262 return SetThreadPriority(thread_, priority) != FALSE; |
228 #elif defined(__native_client__) | 263 #elif defined(__native_client__) |
229 // Setting thread priorities is not supported in NaCl. | 264 // Setting thread priorities is not supported in NaCl. |
230 return true; | 265 return true; |
231 #elif defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX) | 266 #elif defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX) |
232 // TODO(tommi): Switch to the same mechanism as Chromium uses for changing | 267 // TODO(tommi): Switch to the same mechanism as Chromium uses for changing |
233 // thread priorities. | 268 // thread priorities. |
234 return true; | 269 return true; |
235 #else | 270 #else |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 #if defined(WEBRTC_WIN) | 312 #if defined(WEBRTC_WIN) |
278 bool PlatformThread::QueueAPC(PAPCFUNC function, ULONG_PTR data) { | 313 bool PlatformThread::QueueAPC(PAPCFUNC function, ULONG_PTR data) { |
279 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 314 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
280 RTC_DCHECK(IsRunning()); | 315 RTC_DCHECK(IsRunning()); |
281 | 316 |
282 return QueueUserAPC(function, thread_, data) != FALSE; | 317 return QueueUserAPC(function, thread_, data) != FALSE; |
283 } | 318 } |
284 #endif | 319 #endif |
285 | 320 |
286 } // namespace rtc | 321 } // namespace rtc |
OLD | NEW |