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}
diff --git a/webrtc/BUILD.gn b/webrtc/BUILD.gn
index 5ac3132..a10b953 100644
--- a/webrtc/BUILD.gn
+++ b/webrtc/BUILD.gn
@@ -33,7 +33,6 @@
       "FEATURE_ENABLE_VOICEMAIL",
       "EXPAT_RELATIVE_PATH",
       "GTEST_RELATIVE_PATH",
-      "NO_MAIN_THREAD_WRAPPING",
       "NO_SOUND_SYSTEM",
       "WEBRTC_CHROMIUM_BUILD",
     ]
diff --git a/webrtc/base/BUILD.gn b/webrtc/base/BUILD.gn
index 7514b07..3d0a3f4 100644
--- a/webrtc/base/BUILD.gn
+++ b/webrtc/base/BUILD.gn
@@ -544,11 +544,8 @@
 
   if (is_ios || is_mac) {
     sources += [
-      "maccocoathreadhelper.h",
-      "maccocoathreadhelper.mm",
       "macifaddrs_converter.cc",
-      "scoped_autorelease_pool.h",
-      "scoped_autorelease_pool.mm",
+      "thread_darwin.mm",
     ]
   }
 
diff --git a/webrtc/base/maccocoathreadhelper.h b/webrtc/base/maccocoathreadhelper.h
deleted file mode 100644
index 255d081..0000000
--- a/webrtc/base/maccocoathreadhelper.h
+++ /dev/null
@@ -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__
diff --git a/webrtc/base/maccocoathreadhelper.mm b/webrtc/base/maccocoathreadhelper.mm
deleted file mode 100644
index 70d920d..0000000
--- a/webrtc/base/maccocoathreadhelper.mm
+++ /dev/null
@@ -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
diff --git a/webrtc/base/scoped_autorelease_pool.h b/webrtc/base/scoped_autorelease_pool.h
deleted file mode 100644
index 2e0a204..0000000
--- a/webrtc/base/scoped_autorelease_pool.h
+++ /dev/null
@@ -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__
diff --git a/webrtc/base/scoped_autorelease_pool.mm b/webrtc/base/scoped_autorelease_pool.mm
deleted file mode 100644
index 4176aad..0000000
--- a/webrtc/base/scoped_autorelease_pool.mm
+++ /dev/null
@@ -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
diff --git a/webrtc/base/thread.cc b/webrtc/base/thread.cc
index a7db418..66542bb 100644
--- a/webrtc/base/thread.cc
+++ b/webrtc/base/thread.cc
@@ -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 @@
 }
 
 #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 @@
   }
 }
 
-struct ThreadInit {
-  Thread* thread;
-  Runnable* runnable;
-};
-
 Thread::ScopedDisallowBlockingCalls::ScopedDisallowBlockingCalls()
   : thread_(Thread::Current()),
     previous_state_(thread_->SetAllowBlockingCalls(false)) {
@@ -298,6 +279,7 @@
 }
 
 // static
+#if !defined(WEBRTC_MAC)
 #if defined(WEBRTC_WIN)
 DWORD WINAPI Thread::PreRun(LPVOID pv) {
 #else
@@ -306,10 +288,6 @@
   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 @@
   return nullptr;
 #endif
 }
+#endif
 
 void Thread::Run() {
   ProcessMessages(kForever);
@@ -478,18 +457,14 @@
   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 @@
     }
   }
 }
+#endif
 
 bool Thread::WrapCurrentWithThreadManager(ThreadManager* thread_manager,
                                           bool need_synchronize_access) {
diff --git a/webrtc/base/thread.h b/webrtc/base/thread.h
index 5751df3..398063d 100644
--- a/webrtc/base/thread.h
+++ b/webrtc/base/thread.h
@@ -238,6 +238,11 @@
   friend class ScopedDisallowBlockingCalls;
 
  private:
+  struct ThreadInit {
+    Thread* thread;
+    Runnable* runnable;
+  };
+
 #if defined(WEBRTC_WIN)
   static DWORD WINAPI PreRun(LPVOID context);
 #else
diff --git a/webrtc/base/thread_darwin.mm b/webrtc/base/thread_darwin.mm
new file mode 100644
index 0000000..5bcc5c8
--- /dev/null
+++ b/webrtc/base/thread_darwin.mm
@@ -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