OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 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 29 matching lines...) Expand all Loading... |
40 return &thread_manager; | 40 return &thread_manager; |
41 } | 41 } |
42 | 42 |
43 // static | 43 // static |
44 Thread* Thread::Current() { | 44 Thread* Thread::Current() { |
45 return ThreadManager::Instance()->CurrentThread(); | 45 return ThreadManager::Instance()->CurrentThread(); |
46 } | 46 } |
47 | 47 |
48 #if defined(WEBRTC_POSIX) | 48 #if defined(WEBRTC_POSIX) |
49 ThreadManager::ThreadManager() { | 49 ThreadManager::ThreadManager() { |
50 pthread_key_create(&key_, NULL); | 50 pthread_key_create(&key_, nullptr); |
51 #ifndef NO_MAIN_THREAD_WRAPPING | 51 #ifndef NO_MAIN_THREAD_WRAPPING |
52 WrapCurrentThread(); | 52 WrapCurrentThread(); |
53 #endif | 53 #endif |
54 #if !__has_feature(objc_arc) && (defined(WEBRTC_MAC)) | 54 #if !__has_feature(objc_arc) && (defined(WEBRTC_MAC)) |
55 // Under Automatic Reference Counting (ARC), you cannot use autorelease pools | 55 // Under Automatic Reference Counting (ARC), you cannot use autorelease pools |
56 // directly. Instead, you use @autoreleasepool blocks instead. Also, we are | 56 // directly. Instead, you use @autoreleasepool blocks instead. Also, we are |
57 // maintaining thread safety using immutability within context of GCD dispatch | 57 // maintaining thread safety using immutability within context of GCD dispatch |
58 // queues in this case. | 58 // queues in this case. |
59 InitCocoaMultiThreading(); | 59 InitCocoaMultiThreading(); |
60 #endif | 60 #endif |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 return static_cast<Thread *>(TlsGetValue(key_)); | 101 return static_cast<Thread *>(TlsGetValue(key_)); |
102 } | 102 } |
103 | 103 |
104 void ThreadManager::SetCurrentThread(Thread *thread) { | 104 void ThreadManager::SetCurrentThread(Thread *thread) { |
105 TlsSetValue(key_, thread); | 105 TlsSetValue(key_, thread); |
106 } | 106 } |
107 #endif | 107 #endif |
108 | 108 |
109 Thread *ThreadManager::WrapCurrentThread() { | 109 Thread *ThreadManager::WrapCurrentThread() { |
110 Thread* result = CurrentThread(); | 110 Thread* result = CurrentThread(); |
111 if (NULL == result) { | 111 if (nullptr == result) { |
112 result = new Thread(); | 112 result = new Thread(); |
113 result->WrapCurrentWithThreadManager(this, true); | 113 result->WrapCurrentWithThreadManager(this, true); |
114 } | 114 } |
115 return result; | 115 return result; |
116 } | 116 } |
117 | 117 |
118 void ThreadManager::UnwrapCurrentThread() { | 118 void ThreadManager::UnwrapCurrentThread() { |
119 Thread* t = CurrentThread(); | 119 Thread* t = CurrentThread(); |
120 if (t && !(t->IsOwned())) { | 120 if (t && !(t->IsOwned())) { |
121 t->UnwrapCurrent(); | 121 t->UnwrapCurrent(); |
(...skipping 15 matching lines...) Expand all Loading... |
137 RTC_DCHECK(thread_->IsCurrent()); | 137 RTC_DCHECK(thread_->IsCurrent()); |
138 thread_->SetAllowBlockingCalls(previous_state_); | 138 thread_->SetAllowBlockingCalls(previous_state_); |
139 } | 139 } |
140 | 140 |
141 Thread::Thread() : Thread(SocketServer::CreateDefault()) {} | 141 Thread::Thread() : Thread(SocketServer::CreateDefault()) {} |
142 | 142 |
143 Thread::Thread(SocketServer* ss) | 143 Thread::Thread(SocketServer* ss) |
144 : MessageQueue(ss, false), | 144 : MessageQueue(ss, false), |
145 running_(true, false), | 145 running_(true, false), |
146 #if defined(WEBRTC_WIN) | 146 #if defined(WEBRTC_WIN) |
147 thread_(NULL), | 147 thread_(nullptr), |
148 thread_id_(0), | 148 thread_id_(0), |
149 #endif | 149 #endif |
150 owned_(true), | 150 owned_(true), |
151 blocking_calls_allowed_(true) { | 151 blocking_calls_allowed_(true) { |
152 SetName("Thread", this); // default name | 152 SetName("Thread", this); // default name |
153 DoInit(); | 153 DoInit(); |
154 } | 154 } |
155 | 155 |
156 Thread::Thread(std::unique_ptr<SocketServer> ss) | 156 Thread::Thread(std::unique_ptr<SocketServer> ss) |
157 : MessageQueue(std::move(ss), false), | 157 : MessageQueue(std::move(ss), false), |
158 running_(true, false), | 158 running_(true, false), |
159 #if defined(WEBRTC_WIN) | 159 #if defined(WEBRTC_WIN) |
160 thread_(NULL), | 160 thread_(nullptr), |
161 thread_id_(0), | 161 thread_id_(0), |
162 #endif | 162 #endif |
163 owned_(true), | 163 owned_(true), |
164 blocking_calls_allowed_(true) { | 164 blocking_calls_allowed_(true) { |
165 SetName("Thread", this); // default name | 165 SetName("Thread", this); // default name |
166 DoInit(); | 166 DoInit(); |
167 } | 167 } |
168 | 168 |
169 Thread::~Thread() { | 169 Thread::~Thread() { |
170 Stop(); | 170 Stop(); |
(...skipping 14 matching lines...) Expand all Loading... |
185 | 185 |
186 #if defined(WEBRTC_WIN) | 186 #if defined(WEBRTC_WIN) |
187 ::Sleep(milliseconds); | 187 ::Sleep(milliseconds); |
188 return true; | 188 return true; |
189 #else | 189 #else |
190 // POSIX has both a usleep() and a nanosleep(), but the former is deprecated, | 190 // POSIX has both a usleep() and a nanosleep(), but the former is deprecated, |
191 // so we use nanosleep() even though it has greater precision than necessary. | 191 // so we use nanosleep() even though it has greater precision than necessary. |
192 struct timespec ts; | 192 struct timespec ts; |
193 ts.tv_sec = milliseconds / 1000; | 193 ts.tv_sec = milliseconds / 1000; |
194 ts.tv_nsec = (milliseconds % 1000) * 1000000; | 194 ts.tv_nsec = (milliseconds % 1000) * 1000000; |
195 int ret = nanosleep(&ts, NULL); | 195 int ret = nanosleep(&ts, nullptr); |
196 if (ret != 0) { | 196 if (ret != 0) { |
197 LOG_ERR(LS_WARNING) << "nanosleep() returning early"; | 197 LOG_ERR(LS_WARNING) << "nanosleep() returning early"; |
198 return false; | 198 return false; |
199 } | 199 } |
200 return true; | 200 return true; |
201 #endif | 201 #endif |
202 } | 202 } |
203 | 203 |
204 bool Thread::SetName(const std::string& name, const void* obj) { | 204 bool Thread::SetName(const std::string& name, const void* obj) { |
205 if (running()) return false; | 205 if (running()) return false; |
(...skipping 15 matching lines...) Expand all Loading... |
221 Restart(); // reset IsQuitting() if the thread is being restarted | 221 Restart(); // reset IsQuitting() if the thread is being restarted |
222 | 222 |
223 // Make sure that ThreadManager is created on the main thread before | 223 // Make sure that ThreadManager is created on the main thread before |
224 // we start a new thread. | 224 // we start a new thread. |
225 ThreadManager::Instance(); | 225 ThreadManager::Instance(); |
226 | 226 |
227 ThreadInit* init = new ThreadInit; | 227 ThreadInit* init = new ThreadInit; |
228 init->thread = this; | 228 init->thread = this; |
229 init->runnable = runnable; | 229 init->runnable = runnable; |
230 #if defined(WEBRTC_WIN) | 230 #if defined(WEBRTC_WIN) |
231 thread_ = CreateThread(NULL, 0, PreRun, init, 0, &thread_id_); | 231 thread_ = CreateThread(nullptr, 0, PreRun, init, 0, &thread_id_); |
232 if (thread_) { | 232 if (thread_) { |
233 running_.Set(); | 233 running_.Set(); |
234 } else { | 234 } else { |
235 return false; | 235 return false; |
236 } | 236 } |
237 #elif defined(WEBRTC_POSIX) | 237 #elif defined(WEBRTC_POSIX) |
238 pthread_attr_t attr; | 238 pthread_attr_t attr; |
239 pthread_attr_init(&attr); | 239 pthread_attr_init(&attr); |
240 | 240 |
241 int error_code = pthread_create(&thread_, &attr, PreRun, init); | 241 int error_code = pthread_create(&thread_, &attr, PreRun, init); |
242 if (0 != error_code) { | 242 if (0 != error_code) { |
243 LOG(LS_ERROR) << "Unable to create pthread, error " << error_code; | 243 LOG(LS_ERROR) << "Unable to create pthread, error " << error_code; |
244 return false; | 244 return false; |
245 } | 245 } |
246 running_.Set(); | 246 running_.Set(); |
247 #endif | 247 #endif |
248 return true; | 248 return true; |
249 } | 249 } |
250 | 250 |
251 bool Thread::WrapCurrent() { | 251 bool Thread::WrapCurrent() { |
252 return WrapCurrentWithThreadManager(ThreadManager::Instance(), true); | 252 return WrapCurrentWithThreadManager(ThreadManager::Instance(), true); |
253 } | 253 } |
254 | 254 |
255 void Thread::UnwrapCurrent() { | 255 void Thread::UnwrapCurrent() { |
256 // Clears the platform-specific thread-specific storage. | 256 // Clears the platform-specific thread-specific storage. |
257 ThreadManager::Instance()->SetCurrentThread(NULL); | 257 ThreadManager::Instance()->SetCurrentThread(nullptr); |
258 #if defined(WEBRTC_WIN) | 258 #if defined(WEBRTC_WIN) |
259 if (thread_ != NULL) { | 259 if (thread_ != nullptr) { |
260 if (!CloseHandle(thread_)) { | 260 if (!CloseHandle(thread_)) { |
261 LOG_GLE(LS_ERROR) << "When unwrapping thread, failed to close handle."; | 261 LOG_GLE(LS_ERROR) << "When unwrapping thread, failed to close handle."; |
262 } | 262 } |
263 thread_ = NULL; | 263 thread_ = nullptr; |
264 } | 264 } |
265 #endif | 265 #endif |
266 running_.Reset(); | 266 running_.Reset(); |
267 } | 267 } |
268 | 268 |
269 void Thread::SafeWrapCurrent() { | 269 void Thread::SafeWrapCurrent() { |
270 WrapCurrentWithThreadManager(ThreadManager::Instance(), false); | 270 WrapCurrentWithThreadManager(ThreadManager::Instance(), false); |
271 } | 271 } |
272 | 272 |
273 void Thread::Join() { | 273 void Thread::Join() { |
274 if (running()) { | 274 if (running()) { |
275 RTC_DCHECK(!IsCurrent()); | 275 RTC_DCHECK(!IsCurrent()); |
276 if (Current() && !Current()->blocking_calls_allowed_) { | 276 if (Current() && !Current()->blocking_calls_allowed_) { |
277 LOG(LS_WARNING) << "Waiting for the thread to join, " | 277 LOG(LS_WARNING) << "Waiting for the thread to join, " |
278 << "but blocking calls have been disallowed"; | 278 << "but blocking calls have been disallowed"; |
279 } | 279 } |
280 | 280 |
281 #if defined(WEBRTC_WIN) | 281 #if defined(WEBRTC_WIN) |
282 RTC_DCHECK(thread_ != NULL); | 282 RTC_DCHECK(thread_ != nullptr); |
283 WaitForSingleObject(thread_, INFINITE); | 283 WaitForSingleObject(thread_, INFINITE); |
284 CloseHandle(thread_); | 284 CloseHandle(thread_); |
285 thread_ = NULL; | 285 thread_ = nullptr; |
286 thread_id_ = 0; | 286 thread_id_ = 0; |
287 #elif defined(WEBRTC_POSIX) | 287 #elif defined(WEBRTC_POSIX) |
288 void *pv; | 288 void *pv; |
289 pthread_join(thread_, &pv); | 289 pthread_join(thread_, &pv); |
290 #endif | 290 #endif |
291 running_.Reset(); | 291 running_.Reset(); |
292 } | 292 } |
293 } | 293 } |
294 | 294 |
295 bool Thread::SetAllowBlockingCalls(bool allow) { | 295 bool Thread::SetAllowBlockingCalls(bool allow) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 msg.pdata = pdata; | 367 msg.pdata = pdata; |
368 if (IsCurrent()) { | 368 if (IsCurrent()) { |
369 phandler->OnMessage(&msg); | 369 phandler->OnMessage(&msg); |
370 return; | 370 return; |
371 } | 371 } |
372 | 372 |
373 AssertBlockingIsAllowedOnCurrentThread(); | 373 AssertBlockingIsAllowedOnCurrentThread(); |
374 | 374 |
375 AutoThread thread; | 375 AutoThread thread; |
376 Thread *current_thread = Thread::Current(); | 376 Thread *current_thread = Thread::Current(); |
377 RTC_DCHECK(current_thread != NULL); // AutoThread ensures this | 377 RTC_DCHECK(current_thread != nullptr); // AutoThread ensures this |
378 | 378 |
379 bool ready = false; | 379 bool ready = false; |
380 { | 380 { |
381 CritScope cs(&crit_); | 381 CritScope cs(&crit_); |
382 _SendMessage smsg; | 382 _SendMessage smsg; |
383 smsg.thread = current_thread; | 383 smsg.thread = current_thread; |
384 smsg.msg = msg; | 384 smsg.msg = msg; |
385 smsg.ready = &ready; | 385 smsg.ready = &ready; |
386 sendlist_.push_back(smsg); | 386 sendlist_.push_back(smsg); |
387 } | 387 } |
(...skipping 24 matching lines...) Expand all Loading... |
412 // Post while waiting for the Send to complete, which means that when we exit | 412 // Post while waiting for the Send to complete, which means that when we exit |
413 // this loop, we need to issue another WakeUp, or else the Posted message | 413 // this loop, we need to issue another WakeUp, or else the Posted message |
414 // won't be processed in a timely manner. | 414 // won't be processed in a timely manner. |
415 | 415 |
416 if (waited) { | 416 if (waited) { |
417 current_thread->socketserver()->WakeUp(); | 417 current_thread->socketserver()->WakeUp(); |
418 } | 418 } |
419 } | 419 } |
420 | 420 |
421 void Thread::ReceiveSends() { | 421 void Thread::ReceiveSends() { |
422 ReceiveSendsFromThread(NULL); | 422 ReceiveSendsFromThread(nullptr); |
423 } | 423 } |
424 | 424 |
425 void Thread::ReceiveSendsFromThread(const Thread* source) { | 425 void Thread::ReceiveSendsFromThread(const Thread* source) { |
426 // Receive a sent message. Cleanup scenarios: | 426 // Receive a sent message. Cleanup scenarios: |
427 // - thread sending exits: We don't allow this, since thread can exit | 427 // - thread sending exits: We don't allow this, since thread can exit |
428 // only via Join, so Send must complete. | 428 // only via Join, so Send must complete. |
429 // - thread receiving exits: Wakeup/set ready in Thread::Clear() | 429 // - thread receiving exits: Wakeup/set ready in Thread::Clear() |
430 // - object target cleared: Wakeup/set ready in Thread::Clear() | 430 // - object target cleared: Wakeup/set ready in Thread::Clear() |
431 _SendMessage smsg; | 431 _SendMessage smsg; |
432 | 432 |
433 crit_.Enter(); | 433 crit_.Enter(); |
434 while (PopSendMessageFromThread(source, &smsg)) { | 434 while (PopSendMessageFromThread(source, &smsg)) { |
435 crit_.Leave(); | 435 crit_.Leave(); |
436 | 436 |
437 smsg.msg.phandler->OnMessage(&smsg.msg); | 437 smsg.msg.phandler->OnMessage(&smsg.msg); |
438 | 438 |
439 crit_.Enter(); | 439 crit_.Enter(); |
440 *smsg.ready = true; | 440 *smsg.ready = true; |
441 smsg.thread->socketserver()->WakeUp(); | 441 smsg.thread->socketserver()->WakeUp(); |
442 } | 442 } |
443 crit_.Leave(); | 443 crit_.Leave(); |
444 } | 444 } |
445 | 445 |
446 bool Thread::PopSendMessageFromThread(const Thread* source, _SendMessage* msg) { | 446 bool Thread::PopSendMessageFromThread(const Thread* source, _SendMessage* msg) { |
447 for (std::list<_SendMessage>::iterator it = sendlist_.begin(); | 447 for (std::list<_SendMessage>::iterator it = sendlist_.begin(); |
448 it != sendlist_.end(); ++it) { | 448 it != sendlist_.end(); ++it) { |
449 if (it->thread == source || source == NULL) { | 449 if (it->thread == source || source == nullptr) { |
450 *msg = *it; | 450 *msg = *it; |
451 sendlist_.erase(it); | 451 sendlist_.erase(it); |
452 return true; | 452 return true; |
453 } | 453 } |
454 } | 454 } |
455 return false; | 455 return false; |
456 } | 456 } |
457 | 457 |
458 void Thread::InvokeInternal(const Location& posted_from, | 458 void Thread::InvokeInternal(const Location& posted_from, |
459 MessageHandler* handler) { | 459 MessageHandler* handler) { |
460 TRACE_EVENT2("webrtc", "Thread::Invoke", "src_file_and_line", | 460 TRACE_EVENT2("webrtc", "Thread::Invoke", "src_file_and_line", |
461 posted_from.file_and_line(), "src_func", | 461 posted_from.file_and_line(), "src_func", |
462 posted_from.function_name()); | 462 posted_from.function_name()); |
463 Send(posted_from, handler); | 463 Send(posted_from, handler); |
464 } | 464 } |
465 | 465 |
466 void Thread::Clear(MessageHandler* phandler, | 466 void Thread::Clear(MessageHandler* phandler, |
467 uint32_t id, | 467 uint32_t id, |
468 MessageList* removed) { | 468 MessageList* removed) { |
469 CritScope cs(&crit_); | 469 CritScope cs(&crit_); |
470 | 470 |
471 // Remove messages on sendlist_ with phandler | 471 // Remove messages on sendlist_ with phandler |
472 // Object target cleared: remove from send list, wakeup/set ready | 472 // Object target cleared: remove from send list, wakeup/set ready |
473 // if sender not NULL. | 473 // if sender not null. |
474 | 474 |
475 std::list<_SendMessage>::iterator iter = sendlist_.begin(); | 475 std::list<_SendMessage>::iterator iter = sendlist_.begin(); |
476 while (iter != sendlist_.end()) { | 476 while (iter != sendlist_.end()) { |
477 _SendMessage smsg = *iter; | 477 _SendMessage smsg = *iter; |
478 if (smsg.msg.Match(phandler, id)) { | 478 if (smsg.msg.Match(phandler, id)) { |
479 if (removed) { | 479 if (removed) { |
480 removed->push_back(smsg.msg); | 480 removed->push_back(smsg.msg); |
481 } else { | 481 } else { |
482 delete smsg.msg.pdata; | 482 delete smsg.msg.pdata; |
483 } | 483 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 | 549 |
550 AutoThread::AutoThread() { | 550 AutoThread::AutoThread() { |
551 if (!ThreadManager::Instance()->CurrentThread()) { | 551 if (!ThreadManager::Instance()->CurrentThread()) { |
552 ThreadManager::Instance()->SetCurrentThread(this); | 552 ThreadManager::Instance()->SetCurrentThread(this); |
553 } | 553 } |
554 } | 554 } |
555 | 555 |
556 AutoThread::~AutoThread() { | 556 AutoThread::~AutoThread() { |
557 Stop(); | 557 Stop(); |
558 if (ThreadManager::Instance()->CurrentThread() == this) { | 558 if (ThreadManager::Instance()->CurrentThread() == this) { |
559 ThreadManager::Instance()->SetCurrentThread(NULL); | 559 ThreadManager::Instance()->SetCurrentThread(nullptr); |
560 } | 560 } |
561 } | 561 } |
562 | 562 |
563 #if defined(WEBRTC_WIN) | 563 #if defined(WEBRTC_WIN) |
564 void ComThread::Run() { | 564 void ComThread::Run() { |
565 HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); | 565 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); |
566 RTC_DCHECK(SUCCEEDED(hr)); | 566 RTC_DCHECK(SUCCEEDED(hr)); |
567 if (SUCCEEDED(hr)) { | 567 if (SUCCEEDED(hr)) { |
568 Thread::Run(); | 568 Thread::Run(); |
569 CoUninitialize(); | 569 CoUninitialize(); |
570 } else { | 570 } else { |
571 LOG(LS_ERROR) << "CoInitialize failed, hr=" << hr; | 571 LOG(LS_ERROR) << "CoInitialize failed, hr=" << hr; |
572 } | 572 } |
573 } | 573 } |
574 #endif | 574 #endif |
575 | 575 |
576 } // namespace rtc | 576 } // namespace rtc |
OLD | NEW |