Add Darwin thread.h implementation.
Due to quirks of the Cocoa runtime several platform-specific fixes were in place. See the deleted files maccocoathreadhelper and scoped_autorelease_pool for examples. There is no way to do a stack-based RAII autoreleasepool that is compatible with ARC, and autoreleasepool blocks can't be used with c++. The solution was to separate out the implementation of some methods in thread.h to an ObjC++ file for Darwin platforms, allowing us to get rid of the helper classes and enable ARC everywhere. BUG=webrtc:6412 Review-Url: https://codereview.webrtc.org/2784483002 Cr-Commit-Position: refs/heads/master@{#17436}
This commit is contained in:
parent
0f0a849cba
commit
61abe15829
@ -33,7 +33,6 @@ config("common_inherited_config") {
|
||||
"FEATURE_ENABLE_VOICEMAIL",
|
||||
"EXPAT_RELATIVE_PATH",
|
||||
"GTEST_RELATIVE_PATH",
|
||||
"NO_MAIN_THREAD_WRAPPING",
|
||||
"NO_SOUND_SYSTEM",
|
||||
"WEBRTC_CHROMIUM_BUILD",
|
||||
]
|
||||
|
||||
@ -544,11 +544,8 @@ rtc_static_library("rtc_base") {
|
||||
|
||||
if (is_ios || is_mac) {
|
||||
sources += [
|
||||
"maccocoathreadhelper.h",
|
||||
"maccocoathreadhelper.mm",
|
||||
"macifaddrs_converter.cc",
|
||||
"scoped_autorelease_pool.h",
|
||||
"scoped_autorelease_pool.mm",
|
||||
"thread_darwin.mm",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 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.
|
||||
*/
|
||||
|
||||
// Helper function for using Cocoa with Posix threads. This header should be
|
||||
// included from C/C++ files that want to use some Cocoa functionality without
|
||||
// using the .mm extension (mostly for files that are compiled on multiple
|
||||
// platforms).
|
||||
|
||||
#ifndef WEBRTC_BASE_MACCOCOATHREADHELPER_H__
|
||||
#define WEBRTC_BASE_MACCOCOATHREADHELPER_H__
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Cocoa must be "put into multithreading mode" before Cocoa functionality can
|
||||
// be used on POSIX threads. This function does that.
|
||||
void InitCocoaMultiThreading();
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_MACCOCOATHREADHELPER_H__
|
||||
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007 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.
|
||||
*/
|
||||
// Helper function for using Cocoa with Posix threading.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "webrtc/base/maccocoathreadhelper.h"
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// Cocoa must be "put into multithreading mode" before Cocoa functionality can
|
||||
// be used on POSIX threads. The way to do that is to spawn one thread that may
|
||||
// immediately exit.
|
||||
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.
|
||||
// Doing NSAutoreleasePool* hack = [[NSAutoreleasePool alloc] init];
|
||||
// causes unused variable error.
|
||||
NSAutoreleasePool* hack;
|
||||
hack = [[NSAutoreleasePool alloc] init];
|
||||
[NSThread detachNewThreadSelector:@selector(class)
|
||||
toTarget:[NSObject class]
|
||||
withObject:nil];
|
||||
[hack drain];
|
||||
}
|
||||
|
||||
RTC_DCHECK([NSThread isMultiThreaded]);
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 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.
|
||||
*/
|
||||
|
||||
// Automatically initialize and and free an autoreleasepool. Never allocate
|
||||
// an instance of this class using "new" - that will result in a compile-time
|
||||
// error. Only use it as a stack object.
|
||||
//
|
||||
// Note: NSAutoreleasePool docs say that you should not normally need to
|
||||
// declare an NSAutoreleasePool as a member of an object - but there's nothing
|
||||
// that indicates it will be a problem, as long as the stack lifetime of the
|
||||
// pool exactly matches the stack lifetime of the object.
|
||||
|
||||
#ifndef WEBRTC_BASE_SCOPED_AUTORELEASE_POOL_H__
|
||||
#define WEBRTC_BASE_SCOPED_AUTORELEASE_POOL_H__
|
||||
|
||||
#if defined(WEBRTC_MAC)
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
|
||||
// This header may be included from Obj-C files or C++ files.
|
||||
#ifdef __OBJC__
|
||||
@class NSAutoreleasePool;
|
||||
#else
|
||||
class NSAutoreleasePool;
|
||||
#endif
|
||||
|
||||
namespace rtc {
|
||||
|
||||
class ScopedAutoreleasePool {
|
||||
public:
|
||||
ScopedAutoreleasePool();
|
||||
~ScopedAutoreleasePool();
|
||||
|
||||
private:
|
||||
// Declaring private overrides of new and delete here enforces the "only use
|
||||
// as a stack object" discipline.
|
||||
//
|
||||
// Note: new is declared as "throw()" to get around a gcc warning about new
|
||||
// returning null, but this method will never get called and therefore will
|
||||
// never actually throw any exception.
|
||||
void* operator new(size_t size) throw() { return nullptr; }
|
||||
void operator delete (void* ptr) {}
|
||||
|
||||
NSAutoreleasePool* pool_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(ScopedAutoreleasePool);
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_MAC
|
||||
#endif // WEBRTC_BASE_SCOPED_AUTORELEASE_POOL_H__
|
||||
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "webrtc/base/scoped_autorelease_pool.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
ScopedAutoreleasePool::ScopedAutoreleasePool() {
|
||||
pool_ = [[NSAutoreleasePool alloc] init];
|
||||
}
|
||||
|
||||
ScopedAutoreleasePool::~ScopedAutoreleasePool() {
|
||||
[pool_ drain];
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
@ -24,11 +24,6 @@
|
||||
#include "webrtc/base/timeutils.h"
|
||||
#include "webrtc/base/trace_event.h"
|
||||
|
||||
#if defined(WEBRTC_MAC)
|
||||
#include "webrtc/base/maccocoathreadhelper.h"
|
||||
#include "webrtc/base/scoped_autorelease_pool.h"
|
||||
#endif
|
||||
|
||||
namespace rtc {
|
||||
|
||||
ThreadManager* ThreadManager::Instance() {
|
||||
@ -42,28 +37,19 @@ Thread* Thread::Current() {
|
||||
}
|
||||
|
||||
#if defined(WEBRTC_POSIX)
|
||||
#if !defined(WEBRTC_MAC)
|
||||
ThreadManager::ThreadManager() {
|
||||
pthread_key_create(&key_, nullptr);
|
||||
#ifndef NO_MAIN_THREAD_WRAPPING
|
||||
WrapCurrentThread();
|
||||
#endif
|
||||
#if defined(WEBRTC_MAC)
|
||||
// This is necessary to alert the cocoa runtime of the fact that
|
||||
// we are running in a multithreaded environment.
|
||||
InitCocoaMultiThreading();
|
||||
#endif
|
||||
}
|
||||
|
||||
ThreadManager::~ThreadManager() {
|
||||
#if defined(WEBRTC_MAC)
|
||||
// This is called during exit, at which point apparently no NSAutoreleasePools
|
||||
// are available; but we might still need them to do cleanup (or we get the
|
||||
// "no autoreleasepool in place, just leaking" warning when exiting).
|
||||
ScopedAutoreleasePool pool;
|
||||
#endif
|
||||
UnwrapCurrentThread();
|
||||
pthread_key_delete(key_);
|
||||
}
|
||||
#endif
|
||||
|
||||
Thread *ThreadManager::CurrentThread() {
|
||||
return static_cast<Thread *>(pthread_getspecific(key_));
|
||||
@ -113,11 +99,6 @@ void ThreadManager::UnwrapCurrentThread() {
|
||||
}
|
||||
}
|
||||
|
||||
struct ThreadInit {
|
||||
Thread* thread;
|
||||
Runnable* runnable;
|
||||
};
|
||||
|
||||
Thread::ScopedDisallowBlockingCalls::ScopedDisallowBlockingCalls()
|
||||
: thread_(Thread::Current()),
|
||||
previous_state_(thread_->SetAllowBlockingCalls(false)) {
|
||||
@ -298,6 +279,7 @@ void Thread::AssertBlockingIsAllowedOnCurrentThread() {
|
||||
}
|
||||
|
||||
// static
|
||||
#if !defined(WEBRTC_MAC)
|
||||
#if defined(WEBRTC_WIN)
|
||||
DWORD WINAPI Thread::PreRun(LPVOID pv) {
|
||||
#else
|
||||
@ -306,10 +288,6 @@ void* Thread::PreRun(void* pv) {
|
||||
ThreadInit* init = static_cast<ThreadInit*>(pv);
|
||||
ThreadManager::Instance()->SetCurrentThread(init->thread);
|
||||
rtc::SetCurrentThreadName(init->thread->name_.c_str());
|
||||
#if defined(WEBRTC_MAC)
|
||||
// Make sure the new thread has an autoreleasepool
|
||||
ScopedAutoreleasePool pool;
|
||||
#endif
|
||||
if (init->runnable) {
|
||||
init->runnable->Run(init->thread);
|
||||
} else {
|
||||
@ -322,6 +300,7 @@ void* Thread::PreRun(void* pv) {
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void Thread::Run() {
|
||||
ProcessMessages(kForever);
|
||||
@ -478,18 +457,14 @@ void Thread::Clear(MessageHandler* phandler,
|
||||
MessageQueue::Clear(phandler, id, removed);
|
||||
}
|
||||
|
||||
#if !defined(WEBRTC_MAC)
|
||||
// Note that these methods have a separate implementation for mac and ios
|
||||
// defined in webrtc/base/thread_darwin.mm.
|
||||
bool Thread::ProcessMessages(int cmsLoop) {
|
||||
int64_t msEnd = (kForever == cmsLoop) ? 0 : TimeAfter(cmsLoop);
|
||||
int cmsNext = cmsLoop;
|
||||
|
||||
while (true) {
|
||||
#if defined(WEBRTC_MAC)
|
||||
// see: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/Reference/Reference.html
|
||||
// Each thread is supposed to have an autorelease pool. Also for event loops
|
||||
// like this, autorelease pool needs to be created and drained/released
|
||||
// for each cycle.
|
||||
ScopedAutoreleasePool pool;
|
||||
#endif
|
||||
Message msg;
|
||||
if (!Get(&msg, cmsNext))
|
||||
return !IsQuitting();
|
||||
@ -502,6 +477,7 @@ bool Thread::ProcessMessages(int cmsLoop) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Thread::WrapCurrentWithThreadManager(ThreadManager* thread_manager,
|
||||
bool need_synchronize_access) {
|
||||
|
||||
@ -238,6 +238,11 @@ class LOCKABLE Thread : public MessageQueue {
|
||||
friend class ScopedDisallowBlockingCalls;
|
||||
|
||||
private:
|
||||
struct ThreadInit {
|
||||
Thread* thread;
|
||||
Runnable* runnable;
|
||||
};
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
static DWORD WINAPI PreRun(LPVOID context);
|
||||
#else
|
||||
|
||||
93
webrtc/base/thread_darwin.mm
Normal file
93
webrtc/base/thread_darwin.mm
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 "webrtc/base/thread.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
|
||||
/*
|
||||
* 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() {
|
||||
pthread_key_create(&key_, nullptr);
|
||||
#ifndef NO_MAIN_THREAD_WRAPPING
|
||||
WrapCurrentThread();
|
||||
#endif
|
||||
// This is necessary to alert the cocoa runtime of the fact that
|
||||
// we are running in a multithreaded environment.
|
||||
InitCocoaMultiThreading();
|
||||
}
|
||||
|
||||
ThreadManager::~ThreadManager() {
|
||||
@autoreleasepool {
|
||||
UnwrapCurrentThread();
|
||||
pthread_key_delete(key_);
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
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…
x
Reference in New Issue
Block a user