mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 13:50:40 +01:00
Get rid of thread_darwin file.
This file has been causing problems for the build. ObjC was required for a few methods because autoreleasepools are necessary on new threads if those threads will be running objc code. This CL introduces a workaround by using ObjC runtime C APIs to create and drain autoreleasepools, but this comes with the cost of relying on an internal API that may break on future OS/clang releases. Bug: webrtc:9838 Change-Id: I18e765020c20c096c9ef8d80dfa82375ecb202ff Reviewed-on: https://webrtc-review.googlesource.com/c/105301 Commit-Queue: Kári Helgason <kthelgason@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25141}
This commit is contained in:
parent
c34cf71d60
commit
62b1345c85
6 changed files with 97 additions and 112 deletions
|
@ -692,29 +692,11 @@ rtc_static_library("rtc_base") {
|
||||||
if (!build_with_mozilla) {
|
if (!build_with_mozilla) {
|
||||||
public_deps += [ ":rtc_base_generic" ]
|
public_deps += [ ":rtc_base_generic" ]
|
||||||
}
|
}
|
||||||
if (is_win) {
|
if (is_win || is_mac || is_ios) {
|
||||||
sources = [
|
sources = [
|
||||||
"noop.cc",
|
"noop.cc",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
if (is_ios || is_mac) {
|
|
||||||
sources = [
|
|
||||||
"noop.mm",
|
|
||||||
]
|
|
||||||
public_deps += [ ":rtc_base_objc" ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_ios || is_mac) {
|
|
||||||
rtc_source_set("rtc_base_objc") {
|
|
||||||
sources = [
|
|
||||||
"thread_darwin.mm",
|
|
||||||
]
|
|
||||||
deps = [
|
|
||||||
":rtc_base_generic",
|
|
||||||
]
|
|
||||||
visibility = [ ":rtc_base" ]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc_static_library("rtc_base_generic") {
|
rtc_static_library("rtc_base_generic") {
|
||||||
|
@ -894,6 +876,7 @@ rtc_static_library("rtc_base_generic") {
|
||||||
|
|
||||||
if (is_ios || is_mac) {
|
if (is_ios || is_mac) {
|
||||||
sources += [ "macifaddrs_converter.cc" ]
|
sources += [ "macifaddrs_converter.cc" ]
|
||||||
|
deps += [ "system:cocoa_threading" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtc_use_x11) {
|
if (rtc_use_x11) {
|
||||||
|
|
|
@ -65,3 +65,15 @@ rtc_source_set("rtc_export") {
|
||||||
"rtc_export.h",
|
"rtc_export.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_mac || is_ios) {
|
||||||
|
rtc_source_set("cocoa_threading") {
|
||||||
|
sources = [
|
||||||
|
"cocoa_threading.h",
|
||||||
|
"cocoa_threading.mm",
|
||||||
|
]
|
||||||
|
deps = [
|
||||||
|
"..:checks",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
24
rtc_base/system/cocoa_threading.h
Normal file
24
rtc_base/system/cocoa_threading.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RTC_BASE_SYSTEM_COCOA_THREADING_H_
|
||||||
|
#define RTC_BASE_SYSTEM_COCOA_THREADING_H_
|
||||||
|
|
||||||
|
// If Cocoa is to be used on more than one thread, it must know that the
|
||||||
|
// application is multithreaded. Since it's possible to enter Cocoa code
|
||||||
|
// from threads created by pthread_thread_create, Cocoa won't necessarily
|
||||||
|
// be aware that the application is multithreaded. Spawning an NSThread is
|
||||||
|
// enough to get Cocoa to set up for multithreaded operation, so this is done
|
||||||
|
// if necessary before pthread_thread_create spawns any threads.
|
||||||
|
//
|
||||||
|
// http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/chapter_4_section_4.html
|
||||||
|
void InitCocoaMultiThreading();
|
||||||
|
|
||||||
|
#endif // RTC_BASE_SYSTEM_COCOA_THREADING_H_
|
24
rtc_base/system/cocoa_threading.mm
Normal file
24
rtc_base/system/cocoa_threading.mm
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 The WebRTC Project Authors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
#include "rtc_base/system/cocoa_threading.h"
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
|
void InitCocoaMultiThreading() {
|
||||||
|
static BOOL is_cocoa_multithreaded = [NSThread isMultiThreaded];
|
||||||
|
if (!is_cocoa_multithreaded) {
|
||||||
|
// +[NSObject class] is idempotent.
|
||||||
|
[NSThread detachNewThreadSelector:@selector(class) toTarget:[NSObject class] withObject:nil];
|
||||||
|
is_cocoa_multithreaded = YES;
|
||||||
|
RTC_DCHECK([NSThread isMultiThreaded]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,32 @@
|
||||||
#include "rtc_base/timeutils.h"
|
#include "rtc_base/timeutils.h"
|
||||||
#include "rtc_base/trace_event.h"
|
#include "rtc_base/trace_event.h"
|
||||||
|
|
||||||
|
#if defined(WEBRTC_MAC)
|
||||||
|
#include "rtc_base/system/cocoa_threading.h"
|
||||||
|
/*
|
||||||
|
* These are forward-declarations for methods that are part of the
|
||||||
|
* ObjC runtime. They are declared in the private header objc-internal.h.
|
||||||
|
* These calls are what clang inserts when using @autoreleasepool in ObjC,
|
||||||
|
* but here they are used directly in order to keep this file C++.
|
||||||
|
* https://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime-support
|
||||||
|
*/
|
||||||
|
extern "C" {
|
||||||
|
void* objc_autoreleasePoolPush(void);
|
||||||
|
void objc_autoreleasePoolPop(void* pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class ScopedAutoReleasePool {
|
||||||
|
public:
|
||||||
|
ScopedAutoReleasePool() : pool_(objc_autoreleasePoolPush()) {}
|
||||||
|
~ScopedAutoReleasePool() { objc_autoreleasePoolPop(pool_); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* const pool_;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
ThreadManager* ThreadManager::Instance() {
|
ThreadManager* ThreadManager::Instance() {
|
||||||
|
@ -62,11 +88,12 @@ Thread* Thread::Current() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WEBRTC_POSIX)
|
#if defined(WEBRTC_POSIX)
|
||||||
#if !defined(WEBRTC_MAC)
|
|
||||||
ThreadManager::ThreadManager() : main_thread_ref_(CurrentThreadRef()) {
|
ThreadManager::ThreadManager() : main_thread_ref_(CurrentThreadRef()) {
|
||||||
|
#if defined(WEBRTC_MAC)
|
||||||
|
InitCocoaMultiThreading();
|
||||||
|
#endif
|
||||||
pthread_key_create(&key_, nullptr);
|
pthread_key_create(&key_, nullptr);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Thread* ThreadManager::CurrentThread() {
|
Thread* ThreadManager::CurrentThread() {
|
||||||
return static_cast<Thread*>(pthread_getspecific(key_));
|
return static_cast<Thread*>(pthread_getspecific(key_));
|
||||||
|
@ -301,7 +328,6 @@ void Thread::AssertBlockingIsAllowedOnCurrentThread() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
#if !defined(WEBRTC_MAC)
|
|
||||||
#if defined(WEBRTC_WIN)
|
#if defined(WEBRTC_WIN)
|
||||||
DWORD WINAPI Thread::PreRun(LPVOID pv) {
|
DWORD WINAPI Thread::PreRun(LPVOID pv) {
|
||||||
#else
|
#else
|
||||||
|
@ -310,6 +336,9 @@ void* Thread::PreRun(void* pv) {
|
||||||
ThreadInit* init = static_cast<ThreadInit*>(pv);
|
ThreadInit* init = static_cast<ThreadInit*>(pv);
|
||||||
ThreadManager::Instance()->SetCurrentThread(init->thread);
|
ThreadManager::Instance()->SetCurrentThread(init->thread);
|
||||||
rtc::SetCurrentThreadName(init->thread->name_.c_str());
|
rtc::SetCurrentThreadName(init->thread->name_.c_str());
|
||||||
|
#if defined(WEBRTC_MAC)
|
||||||
|
ScopedAutoReleasePool pool;
|
||||||
|
#endif
|
||||||
if (init->runnable) {
|
if (init->runnable) {
|
||||||
init->runnable->Run(init->thread);
|
init->runnable->Run(init->thread);
|
||||||
} else {
|
} else {
|
||||||
|
@ -323,7 +352,6 @@ void* Thread::PreRun(void* pv) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void Thread::Run() {
|
void Thread::Run() {
|
||||||
ProcessMessages(kForever);
|
ProcessMessages(kForever);
|
||||||
|
@ -486,9 +514,6 @@ void Thread::Clear(MessageHandler* phandler,
|
||||||
ClearInternal(phandler, id, removed);
|
ClearInternal(phandler, id, removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(WEBRTC_MAC)
|
|
||||||
// Note that these methods have a separate implementation for mac and ios
|
|
||||||
// defined in webrtc/rtc_base/thread_darwin.mm.
|
|
||||||
bool Thread::ProcessMessages(int cmsLoop) {
|
bool Thread::ProcessMessages(int cmsLoop) {
|
||||||
// Using ProcessMessages with a custom clock for testing and a time greater
|
// Using ProcessMessages with a custom clock for testing and a time greater
|
||||||
// than 0 doesn't work, since it's not guaranteed to advance the custom
|
// than 0 doesn't work, since it's not guaranteed to advance the custom
|
||||||
|
@ -499,6 +524,9 @@ bool Thread::ProcessMessages(int cmsLoop) {
|
||||||
int cmsNext = cmsLoop;
|
int cmsNext = cmsLoop;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
#if defined(WEBRTC_MAC)
|
||||||
|
ScopedAutoReleasePool pool;
|
||||||
|
#endif
|
||||||
Message msg;
|
Message msg;
|
||||||
if (!Get(&msg, cmsNext))
|
if (!Get(&msg, cmsNext))
|
||||||
return !IsQuitting();
|
return !IsQuitting();
|
||||||
|
@ -511,7 +539,6 @@ bool Thread::ProcessMessages(int cmsLoop) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool Thread::WrapCurrentWithThreadManager(ThreadManager* thread_manager,
|
bool Thread::WrapCurrentWithThreadManager(ThreadManager* thread_manager,
|
||||||
bool need_synchronize_access) {
|
bool need_synchronize_access) {
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2017 The WebRTC Project Authors. All rights reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "rtc_base/thread.h"
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
#include "rtc_base/platform_thread.h"
|
|
||||||
#include "rtc_base/timeutils.h" // for TimeAfter, TimeUntil
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file contains platform-specific implementations for several
|
|
||||||
* methods in rtc::Thread.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
void InitCocoaMultiThreading() {
|
|
||||||
if ([NSThread isMultiThreaded] == NO) {
|
|
||||||
// The sole purpose of this autorelease pool is to avoid a console
|
|
||||||
// message on Leopard that tells us we're autoreleasing the thread
|
|
||||||
// with no autorelease pool in place.
|
|
||||||
@autoreleasepool {
|
|
||||||
[NSThread detachNewThreadSelector:@selector(class)
|
|
||||||
toTarget:[NSObject class]
|
|
||||||
withObject:nil];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RTC_DCHECK([NSThread isMultiThreaded]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace rtc {
|
|
||||||
|
|
||||||
ThreadManager::ThreadManager() : main_thread_ref_(CurrentThreadRef()) {
|
|
||||||
pthread_key_create(&key_, nullptr);
|
|
||||||
// This is necessary to alert the cocoa runtime of the fact that
|
|
||||||
// we are running in a multithreaded environment.
|
|
||||||
InitCocoaMultiThreading();
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void* Thread::PreRun(void* pv) {
|
|
||||||
ThreadInit* init = static_cast<ThreadInit*>(pv);
|
|
||||||
ThreadManager::Instance()->SetCurrentThread(init->thread);
|
|
||||||
rtc::SetCurrentThreadName(init->thread->name_.c_str());
|
|
||||||
@autoreleasepool {
|
|
||||||
if (init->runnable) {
|
|
||||||
init->runnable->Run(init->thread);
|
|
||||||
} else {
|
|
||||||
init->thread->Run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ThreadManager::Instance()->SetCurrentThread(nullptr);
|
|
||||||
delete init;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Thread::ProcessMessages(int cmsLoop) {
|
|
||||||
int64_t msEnd = (kForever == cmsLoop) ? 0 : TimeAfter(cmsLoop);
|
|
||||||
int cmsNext = cmsLoop;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
@autoreleasepool {
|
|
||||||
Message msg;
|
|
||||||
if (!Get(&msg, cmsNext))
|
|
||||||
return !IsQuitting();
|
|
||||||
Dispatch(&msg);
|
|
||||||
|
|
||||||
if (cmsLoop != kForever) {
|
|
||||||
cmsNext = static_cast<int>(TimeUntil(msEnd));
|
|
||||||
if (cmsNext < 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace rtc
|
|
Loading…
Reference in a new issue