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 |
11 #include "webrtc/base/platform_thread.h" | 11 #include "webrtc/base/platform_thread.h" |
12 | 12 |
| 13 #include "webrtc/base/atomicops.h" |
13 #include "webrtc/base/checks.h" | 14 #include "webrtc/base/checks.h" |
14 | 15 |
15 #if defined(WEBRTC_LINUX) | 16 #if defined(WEBRTC_LINUX) |
16 #include <sys/prctl.h> | 17 #include <sys/prctl.h> |
17 #include <sys/syscall.h> | 18 #include <sys/syscall.h> |
18 #endif | 19 #endif |
19 | 20 |
20 namespace rtc { | 21 namespace rtc { |
21 | 22 |
22 PlatformThreadId CurrentThreadId() { | 23 PlatformThreadId CurrentThreadId() { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 pthread_attr_t attr; | 90 pthread_attr_t attr; |
90 }; | 91 }; |
91 #endif // defined(WEBRTC_WIN) | 92 #endif // defined(WEBRTC_WIN) |
92 } | 93 } |
93 | 94 |
94 PlatformThread::PlatformThread(ThreadRunFunction func, | 95 PlatformThread::PlatformThread(ThreadRunFunction func, |
95 void* obj, | 96 void* obj, |
96 const char* thread_name) | 97 const char* thread_name) |
97 : run_function_(func), | 98 : run_function_(func), |
98 obj_(obj), | 99 obj_(obj), |
99 name_(thread_name ? thread_name : "webrtc"), | 100 name_(thread_name ? thread_name : "webrtc") { |
100 #if defined(WEBRTC_WIN) | |
101 stop_(false), | |
102 thread_(NULL), | |
103 thread_id_(0) { | |
104 #else | |
105 stop_event_(false, false), | |
106 thread_(0) { | |
107 #endif // defined(WEBRTC_WIN) | |
108 RTC_DCHECK(func); | 101 RTC_DCHECK(func); |
109 RTC_DCHECK(name_.length() < 64); | 102 RTC_DCHECK(name_.length() < 64); |
110 } | 103 } |
111 | 104 |
112 PlatformThread::~PlatformThread() { | 105 PlatformThread::~PlatformThread() { |
113 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 106 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
114 #if defined(WEBRTC_WIN) | 107 #if defined(WEBRTC_WIN) |
115 RTC_DCHECK(!thread_); | 108 RTC_DCHECK(!thread_); |
116 RTC_DCHECK(!thread_id_); | 109 RTC_DCHECK(!thread_id_); |
117 #endif // defined(WEBRTC_WIN) | 110 #endif // defined(WEBRTC_WIN) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 #if defined(WEBRTC_WIN) | 173 #if defined(WEBRTC_WIN) |
181 // Set stop_ to |true| on the worker thread. | 174 // Set stop_ to |true| on the worker thread. |
182 bool queued = QueueAPC(&RaiseFlag, reinterpret_cast<ULONG_PTR>(&stop_)); | 175 bool queued = QueueAPC(&RaiseFlag, reinterpret_cast<ULONG_PTR>(&stop_)); |
183 // Queuing the APC can fail if the thread is being terminated. | 176 // Queuing the APC can fail if the thread is being terminated. |
184 RTC_CHECK(queued || GetLastError() == ERROR_GEN_FAILURE); | 177 RTC_CHECK(queued || GetLastError() == ERROR_GEN_FAILURE); |
185 WaitForSingleObject(thread_, INFINITE); | 178 WaitForSingleObject(thread_, INFINITE); |
186 CloseHandle(thread_); | 179 CloseHandle(thread_); |
187 thread_ = nullptr; | 180 thread_ = nullptr; |
188 thread_id_ = 0; | 181 thread_id_ = 0; |
189 #else | 182 #else |
190 stop_event_.Set(); | 183 RTC_CHECK_EQ(1, AtomicOps::Increment(&stop_flag_)); |
191 RTC_CHECK_EQ(0, pthread_join(thread_, nullptr)); | 184 RTC_CHECK_EQ(0, pthread_join(thread_, nullptr)); |
| 185 AtomicOps::ReleaseStore(&stop_flag_, 0); |
192 thread_ = 0; | 186 thread_ = 0; |
193 #endif // defined(WEBRTC_WIN) | 187 #endif // defined(WEBRTC_WIN) |
194 } | 188 } |
195 | 189 |
| 190 // TODO(tommi): Deprecate the loop behavior in PlatformThread. |
| 191 // * Introduce a new callback type that returns void. |
| 192 // * Remove potential for a busy loop in PlatformThread. |
| 193 // * Delegate the responsibility for how to stop the thread, to the |
| 194 // implementation that actually uses the thread. |
| 195 // 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. |
196 void PlatformThread::Run() { | 197 void PlatformThread::Run() { |
197 if (!name_.empty()) | 198 if (!name_.empty()) |
198 rtc::SetCurrentThreadName(name_.c_str()); | 199 rtc::SetCurrentThreadName(name_.c_str()); |
| 200 #if !defined(WEBRTC_MAC) && !defined(WEBRTC_WIN) |
| 201 const struct timespec ts_null = {0}; |
| 202 #endif |
199 do { | 203 do { |
200 // The interface contract of Start/Stop is that for a successful call to | 204 // The interface contract of Start/Stop is that for a successful call to |
201 // Start, there should be at least one call to the run function. So we | 205 // Start, there should be at least one call to the run function. So we |
202 // call the function before checking |stop_|. | 206 // call the function before checking |stop_|. |
203 if (!run_function_(obj_)) | 207 if (!run_function_(obj_)) |
204 break; | 208 break; |
205 #if defined(WEBRTC_WIN) | 209 #if defined(WEBRTC_WIN) |
206 // Alertable sleep to permit RaiseFlag to run and update |stop_|. | 210 // Alertable sleep to permit RaiseFlag to run and update |stop_|. |
207 SleepEx(0, true); | 211 SleepEx(0, true); |
208 } while (!stop_); | 212 } while (!stop_); |
209 #else | 213 #else |
210 } while (!stop_event_.Wait(0)); | 214 #if defined(WEBRTC_MAC) |
| 215 sched_yield(); |
| 216 #else |
| 217 nanosleep(&ts_null, nullptr); |
| 218 #endif |
| 219 } while (!AtomicOps::AcquireLoad(&stop_flag_)); |
211 #endif // defined(WEBRTC_WIN) | 220 #endif // defined(WEBRTC_WIN) |
212 } | 221 } |
213 | 222 |
214 bool PlatformThread::SetPriority(ThreadPriority priority) { | 223 bool PlatformThread::SetPriority(ThreadPriority priority) { |
215 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 224 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
216 RTC_DCHECK(IsRunning()); | 225 RTC_DCHECK(IsRunning()); |
217 #if defined(WEBRTC_WIN) | 226 #if defined(WEBRTC_WIN) |
218 return SetThreadPriority(thread_, priority) != FALSE; | 227 return SetThreadPriority(thread_, priority) != FALSE; |
219 #elif defined(__native_client__) | 228 #elif defined(__native_client__) |
220 // Setting thread priorities is not supported in NaCl. | 229 // Setting thread priorities is not supported in NaCl. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 #if defined(WEBRTC_WIN) | 277 #if defined(WEBRTC_WIN) |
269 bool PlatformThread::QueueAPC(PAPCFUNC function, ULONG_PTR data) { | 278 bool PlatformThread::QueueAPC(PAPCFUNC function, ULONG_PTR data) { |
270 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 279 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
271 RTC_DCHECK(IsRunning()); | 280 RTC_DCHECK(IsRunning()); |
272 | 281 |
273 return QueueUserAPC(function, thread_, data) != FALSE; | 282 return QueueUserAPC(function, thread_, data) != FALSE; |
274 } | 283 } |
275 #endif | 284 #endif |
276 | 285 |
277 } // namespace rtc | 286 } // namespace rtc |
OLD | NEW |