| 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 |