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 |
11 #include "webrtc/base/thread.h" | 11 #include "webrtc/base/thread.h" |
12 | 12 |
13 #ifndef __has_feature | |
14 #define __has_feature(x) 0 // Compatibility with non-clang or LLVM compilers. | |
15 #endif // __has_feature | |
16 | |
17 #if defined(WEBRTC_WIN) | 13 #if defined(WEBRTC_WIN) |
18 #include <comdef.h> | 14 #include <comdef.h> |
19 #elif defined(WEBRTC_POSIX) | 15 #elif defined(WEBRTC_POSIX) |
20 #include <time.h> | 16 #include <time.h> |
21 #endif | 17 #endif |
22 | 18 |
23 #include "webrtc/base/checks.h" | 19 #include "webrtc/base/checks.h" |
24 #include "webrtc/base/logging.h" | 20 #include "webrtc/base/logging.h" |
25 #include "webrtc/base/nullsocketserver.h" | 21 #include "webrtc/base/nullsocketserver.h" |
26 #include "webrtc/base/platform_thread.h" | 22 #include "webrtc/base/platform_thread.h" |
27 #include "webrtc/base/stringutils.h" | 23 #include "webrtc/base/stringutils.h" |
28 #include "webrtc/base/timeutils.h" | 24 #include "webrtc/base/timeutils.h" |
29 #include "webrtc/base/trace_event.h" | 25 #include "webrtc/base/trace_event.h" |
30 | 26 |
31 #if !__has_feature(objc_arc) && (defined(WEBRTC_MAC)) | 27 #if defined(WEBRTC_MAC) |
32 #include "webrtc/base/maccocoathreadhelper.h" | 28 #include "webrtc/base/maccocoathreadhelper.h" |
33 #include "webrtc/base/scoped_autorelease_pool.h" | 29 #include "webrtc/base/scoped_autorelease_pool.h" |
34 #endif | 30 #endif |
35 | 31 |
36 namespace rtc { | 32 namespace rtc { |
37 | 33 |
38 ThreadManager* ThreadManager::Instance() { | 34 ThreadManager* ThreadManager::Instance() { |
39 RTC_DEFINE_STATIC_LOCAL(ThreadManager, thread_manager, ()); | 35 RTC_DEFINE_STATIC_LOCAL(ThreadManager, thread_manager, ()); |
40 return &thread_manager; | 36 return &thread_manager; |
41 } | 37 } |
42 | 38 |
43 // static | 39 // static |
44 Thread* Thread::Current() { | 40 Thread* Thread::Current() { |
45 return ThreadManager::Instance()->CurrentThread(); | 41 return ThreadManager::Instance()->CurrentThread(); |
46 } | 42 } |
47 | 43 |
48 #if defined(WEBRTC_POSIX) | 44 #if defined(WEBRTC_POSIX) |
49 ThreadManager::ThreadManager() { | 45 ThreadManager::ThreadManager() { |
50 pthread_key_create(&key_, NULL); | 46 pthread_key_create(&key_, NULL); |
51 #ifndef NO_MAIN_THREAD_WRAPPING | 47 #ifndef NO_MAIN_THREAD_WRAPPING |
52 WrapCurrentThread(); | 48 WrapCurrentThread(); |
53 #endif | 49 #endif |
54 #if !__has_feature(objc_arc) && (defined(WEBRTC_MAC)) | 50 #if defined(WEBRTC_MAC) |
55 // Under Automatic Reference Counting (ARC), you cannot use autorelease pools | 51 // This is necessary to alert the cocoa runtime of the fact that |
56 // directly. Instead, you use @autoreleasepool blocks instead. Also, we are | 52 // we are running in a multithreaded environment. |
57 // maintaining thread safety using immutability within context of GCD dispatch | |
58 // queues in this case. | |
59 InitCocoaMultiThreading(); | 53 InitCocoaMultiThreading(); |
60 #endif | 54 #endif |
61 } | 55 } |
62 | 56 |
63 ThreadManager::~ThreadManager() { | 57 ThreadManager::~ThreadManager() { |
64 #if __has_feature(objc_arc) | 58 #if defined(WEBRTC_MAC) |
65 @autoreleasepool | |
66 #elif defined(WEBRTC_MAC) | |
67 // This is called during exit, at which point apparently no NSAutoreleasePools | 59 // This is called during exit, at which point apparently no NSAutoreleasePools |
68 // are available; but we might still need them to do cleanup (or we get the | 60 // are available; but we might still need them to do cleanup (or we get the |
69 // "no autoreleasepool in place, just leaking" warning when exiting). | 61 // "no autoreleasepool in place, just leaking" warning when exiting). |
70 ScopedAutoreleasePool pool; | 62 ScopedAutoreleasePool pool; |
71 #endif | 63 #endif |
72 { | 64 UnwrapCurrentThread(); |
73 UnwrapCurrentThread(); | 65 pthread_key_delete(key_); |
74 pthread_key_delete(key_); | |
75 } | |
76 } | 66 } |
77 | 67 |
78 Thread *ThreadManager::CurrentThread() { | 68 Thread *ThreadManager::CurrentThread() { |
79 return static_cast<Thread *>(pthread_getspecific(key_)); | 69 return static_cast<Thread *>(pthread_getspecific(key_)); |
80 } | 70 } |
81 | 71 |
82 void ThreadManager::SetCurrentThread(Thread *thread) { | 72 void ThreadManager::SetCurrentThread(Thread *thread) { |
83 pthread_setspecific(key_, thread); | 73 pthread_setspecific(key_, thread); |
84 } | 74 } |
85 #endif | 75 #endif |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 | 299 |
310 // static | 300 // static |
311 #if defined(WEBRTC_WIN) | 301 #if defined(WEBRTC_WIN) |
312 DWORD WINAPI Thread::PreRun(LPVOID pv) { | 302 DWORD WINAPI Thread::PreRun(LPVOID pv) { |
313 #else | 303 #else |
314 void* Thread::PreRun(void* pv) { | 304 void* Thread::PreRun(void* pv) { |
315 #endif | 305 #endif |
316 ThreadInit* init = static_cast<ThreadInit*>(pv); | 306 ThreadInit* init = static_cast<ThreadInit*>(pv); |
317 ThreadManager::Instance()->SetCurrentThread(init->thread); | 307 ThreadManager::Instance()->SetCurrentThread(init->thread); |
318 rtc::SetCurrentThreadName(init->thread->name_.c_str()); | 308 rtc::SetCurrentThreadName(init->thread->name_.c_str()); |
319 #if __has_feature(objc_arc) | 309 #if defined(WEBRTC_MAC) |
320 @autoreleasepool | |
321 #elif defined(WEBRTC_MAC) | |
322 // Make sure the new thread has an autoreleasepool | 310 // Make sure the new thread has an autoreleasepool |
323 ScopedAutoreleasePool pool; | 311 ScopedAutoreleasePool pool; |
324 #endif | 312 #endif |
325 { | 313 if (init->runnable) { |
326 if (init->runnable) { | 314 init->runnable->Run(init->thread); |
327 init->runnable->Run(init->thread); | 315 } else { |
328 } else { | 316 init->thread->Run(); |
329 init->thread->Run(); | 317 } |
330 } | 318 delete init; |
331 delete init; | |
332 #ifdef WEBRTC_WIN | 319 #ifdef WEBRTC_WIN |
333 return 0; | 320 return 0; |
334 #else | 321 #else |
335 return nullptr; | 322 return nullptr; |
336 #endif | 323 #endif |
337 } | |
338 } | 324 } |
339 | 325 |
340 void Thread::Run() { | 326 void Thread::Run() { |
341 ProcessMessages(kForever); | 327 ProcessMessages(kForever); |
342 } | 328 } |
343 | 329 |
344 bool Thread::IsOwned() { | 330 bool Thread::IsOwned() { |
345 return owned_; | 331 return owned_; |
346 } | 332 } |
347 | 333 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 } | 476 } |
491 | 477 |
492 MessageQueue::Clear(phandler, id, removed); | 478 MessageQueue::Clear(phandler, id, removed); |
493 } | 479 } |
494 | 480 |
495 bool Thread::ProcessMessages(int cmsLoop) { | 481 bool Thread::ProcessMessages(int cmsLoop) { |
496 int64_t msEnd = (kForever == cmsLoop) ? 0 : TimeAfter(cmsLoop); | 482 int64_t msEnd = (kForever == cmsLoop) ? 0 : TimeAfter(cmsLoop); |
497 int cmsNext = cmsLoop; | 483 int cmsNext = cmsLoop; |
498 | 484 |
499 while (true) { | 485 while (true) { |
500 #if __has_feature(objc_arc) | 486 #if defined(WEBRTC_MAC) |
501 @autoreleasepool | |
502 #elif defined(WEBRTC_MAC) | |
503 // see: http://developer.apple.com/library/mac/#documentation/Cocoa/Referenc
e/Foundation/Classes/NSAutoreleasePool_Class/Reference/Reference.html | 487 // see: http://developer.apple.com/library/mac/#documentation/Cocoa/Referenc
e/Foundation/Classes/NSAutoreleasePool_Class/Reference/Reference.html |
504 // Each thread is supposed to have an autorelease pool. Also for event loops | 488 // Each thread is supposed to have an autorelease pool. Also for event loops |
505 // like this, autorelease pool needs to be created and drained/released | 489 // like this, autorelease pool needs to be created and drained/released |
506 // for each cycle. | 490 // for each cycle. |
507 ScopedAutoreleasePool pool; | 491 ScopedAutoreleasePool pool; |
508 #endif | 492 #endif |
509 { | 493 Message msg; |
510 Message msg; | 494 if (!Get(&msg, cmsNext)) |
511 if (!Get(&msg, cmsNext)) | 495 return !IsQuitting(); |
512 return !IsQuitting(); | 496 Dispatch(&msg); |
513 Dispatch(&msg); | |
514 | 497 |
515 if (cmsLoop != kForever) { | 498 if (cmsLoop != kForever) { |
516 cmsNext = static_cast<int>(TimeUntil(msEnd)); | 499 cmsNext = static_cast<int>(TimeUntil(msEnd)); |
517 if (cmsNext < 0) | 500 if (cmsNext < 0) |
518 return true; | 501 return true; |
519 } | |
520 } | 502 } |
521 } | 503 } |
522 } | 504 } |
523 | 505 |
524 bool Thread::WrapCurrentWithThreadManager(ThreadManager* thread_manager, | 506 bool Thread::WrapCurrentWithThreadManager(ThreadManager* thread_manager, |
525 bool need_synchronize_access) { | 507 bool need_synchronize_access) { |
526 if (running()) | 508 if (running()) |
527 return false; | 509 return false; |
528 | 510 |
529 #if defined(WEBRTC_WIN) | 511 #if defined(WEBRTC_WIN) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
571 if (SUCCEEDED(hr)) { | 553 if (SUCCEEDED(hr)) { |
572 Thread::Run(); | 554 Thread::Run(); |
573 CoUninitialize(); | 555 CoUninitialize(); |
574 } else { | 556 } else { |
575 LOG(LS_ERROR) << "CoInitialize failed, hr=" << hr; | 557 LOG(LS_ERROR) << "CoInitialize failed, hr=" << hr; |
576 } | 558 } |
577 } | 559 } |
578 #endif | 560 #endif |
579 | 561 |
580 } // namespace rtc | 562 } // namespace rtc |
OLD | NEW |