ProcessThread improvements.

* Added a way to notify a Module that it's been attached to a ProcessThread.
  The benefit of this is to give the module a way to wake up the thread
  when it needs work to happen on the worker thread, immediately.
  Today, module instances are typically registered with a process thread
  outside the control of the modules themselves.  I.e. they typically
  don't know about the process thread they're attached to.

* Improve ProcessThread's WakeUp algorithm to not call TimeUntilNextProcess
  when a WakeUp call is requested.  This is an optimization for the above
  case which avoids the module having to acquire a lock or do an interlocked
  operation before calling WakeUp(), which would ensure the module's
  TimeUntilNextProcess() implementation would return 0.

BUG=2822
R=stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/39239004

Cr-Commit-Position: refs/heads/master@{#8527}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8527 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/interface/module.h b/webrtc/modules/interface/module.h
index dfa1ad4..a83f148 100644
--- a/webrtc/modules/interface/module.h
+++ b/webrtc/modules/interface/module.h
@@ -15,6 +15,8 @@
 
 namespace webrtc {
 
+class ProcessThread;
+
 class Module {
  public:
   // Returns the number of milliseconds until the module wants a worker
@@ -32,6 +34,27 @@
   // Called on a worker thread.
   virtual int32_t Process() = 0;
 
+  // This method is called when the module is attached to a *running* process
+  // thread or detached from one.  In the case of detaching, |process_thread|
+  // will be nullptr.
+  //
+  // This method will be called in the following cases:
+  //
+  // * Non-null process_thread:
+  //   * ProcessThread::RegisterModule() is called while the thread is running.
+  //   * ProcessThread::Start() is called and RegisterModule has previously
+  //     been called.  The thread will be started immediately after notifying
+  //     all modules.
+  //
+  // * Null process_thread:
+  //   * ProcessThread::DeRegisterModule() is called while the thread is
+  //     running.
+  //   * ProcessThread::Stop() was called and the thread has been stopped.
+  //
+  // NOTE: This method is not called from the worker thread itself, but from
+  //       the thread that registers/deregisters the module or calls Start/Stop.
+  virtual void ProcessThreadAttached(ProcessThread* process_thread) {}
+
  protected:
   virtual ~Module() {}
 };
diff --git a/webrtc/modules/utility/interface/mock/mock_process_thread.h b/webrtc/modules/utility/interface/mock/mock_process_thread.h
index a181812..a722180 100644
--- a/webrtc/modules/utility/interface/mock/mock_process_thread.h
+++ b/webrtc/modules/utility/interface/mock/mock_process_thread.h
@@ -19,11 +19,11 @@
 
 class MockProcessThread : public ProcessThread {
  public:
-  MOCK_METHOD0(Start, int32_t());
-  MOCK_METHOD0(Stop, int32_t());
+  MOCK_METHOD0(Start, void());
+  MOCK_METHOD0(Stop, void());
   MOCK_METHOD1(WakeUp, void(Module* module));
-  MOCK_METHOD1(RegisterModule, int32_t(Module* module));
-  MOCK_METHOD1(DeRegisterModule, int32_t(const Module* module));
+  MOCK_METHOD1(RegisterModule, void(Module* module));
+  MOCK_METHOD1(DeRegisterModule, void(Module* module));
 };
 
 }  // namespace webrtc
diff --git a/webrtc/modules/utility/interface/process_thread.h b/webrtc/modules/utility/interface/process_thread.h
index 2262f2d..e30325c 100644
--- a/webrtc/modules/utility/interface/process_thread.h
+++ b/webrtc/modules/utility/interface/process_thread.h
@@ -24,10 +24,10 @@
   static rtc::scoped_ptr<ProcessThread> Create();
 
   // Starts the worker thread.  Must be called from the construction thread.
-  virtual int32_t Start() = 0;
+  virtual void Start() = 0;
 
   // Stops the worker thread.  Must be called from the construction thread.
-  virtual int32_t Stop() = 0;
+  virtual void Stop() = 0;
 
   // Wakes the thread up to give a module a chance to do processing right
   // away.  This causes the worker thread to wake up and requery the specified
@@ -38,11 +38,11 @@
 
   // Adds a module that will start to receive callbacks on the worker thread.
   // Can be called from any thread.
-  virtual int32_t RegisterModule(Module* module) = 0;
+  virtual void RegisterModule(Module* module) = 0;
 
   // Removes a previously registered module.
   // Can be called from any thread.
-  virtual int32_t DeRegisterModule(const Module* module) = 0;
+  virtual void DeRegisterModule(Module* module) = 0;
 };
 
 }  // namespace webrtc
diff --git a/webrtc/modules/utility/source/process_thread_impl.cc b/webrtc/modules/utility/source/process_thread_impl.cc
index 1e498d4..c408b2c 100644
--- a/webrtc/modules/utility/source/process_thread_impl.cc
+++ b/webrtc/modules/utility/source/process_thread_impl.cc
@@ -17,6 +17,12 @@
 
 namespace webrtc {
 namespace {
+
+// We use this constant internally to signal that a module has requested
+// a callback right away.  When this is set, no call to TimeUntilNextProcess
+// should be made, but Process() should be called directly.
+const int64_t kCallProcessImmediately = -1;
+
 int64_t GetNextCallbackTime(Module* module, int64_t time_now) {
   int64_t interval = module->TimeUntilNextProcess();
   // Currently some implementations erroneously return error codes from
@@ -47,28 +53,27 @@
   DCHECK(!stop_);
 }
 
-int32_t ProcessThreadImpl::Start() {
+void ProcessThreadImpl::Start() {
   DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(!thread_.get());
   if (thread_.get())
-    return -1;
+    return;
 
   DCHECK(!stop_);
 
+  for (ModuleCallback& m : modules_)
+    m.module->ProcessThreadAttached(this);
+
   thread_.reset(ThreadWrapper::CreateThread(
       &ProcessThreadImpl::Run, this, kNormalPriority, "ProcessThread"));
   unsigned int id;
-  if (!thread_->Start(id)) {
-    thread_.reset();
-    return -1;
-  }
-
-  return 0;
+  CHECK(thread_->Start(id));
 }
 
-int32_t ProcessThreadImpl::Stop() {
+void ProcessThreadImpl::Stop() {
   DCHECK(thread_checker_.CalledOnValidThread());
   if(!thread_.get())
-    return 0;
+    return;
 
   {
     rtc::CritScope lock(&lock_);
@@ -77,11 +82,12 @@
 
   wake_up_->Set();
 
-  thread_->Stop();
+  CHECK(thread_->Stop());
   thread_.reset();
   stop_ = false;
 
-  return 0;
+  for (ModuleCallback& m : modules_)
+    m.module->ProcessThreadAttached(nullptr);
 }
 
 void ProcessThreadImpl::WakeUp(Module* module) {
@@ -90,23 +96,33 @@
     rtc::CritScope lock(&lock_);
     for (ModuleCallback& m : modules_) {
       if (m.module == module)
-        m.next_callback = 0;
+        m.next_callback = kCallProcessImmediately;
     }
   }
   wake_up_->Set();
 }
 
-int32_t ProcessThreadImpl::RegisterModule(Module* module) {
+void ProcessThreadImpl::RegisterModule(Module* module) {
   // Allowed to be called on any thread.
   DCHECK(module);
+
+#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
+  {
+    // Catch programmer error.
+    rtc::CritScope lock(&lock_);
+    for (const ModuleCallback& mc : modules_)
+      DCHECK(mc.module != module);
+  }
+#endif
+
+  // Now that we know the module isn't in the list, we'll call out to notify
+  // the module that it's attached to the worker thread.  We don't hold
+  // the lock while we make this call.
+  if (thread_.get())
+    module->ProcessThreadAttached(this);
+
   {
     rtc::CritScope lock(&lock_);
-    // Only allow module to be registered once.
-    for (const ModuleCallback& mc : modules_) {
-      if (mc.module == module)
-        return -1;
-    }
-
     modules_.push_back(ModuleCallback(module));
   }
 
@@ -114,18 +130,21 @@
   // waiting time. The waiting time for the just registered module may be
   // shorter than all other registered modules.
   wake_up_->Set();
-
-  return 0;
 }
 
-int32_t ProcessThreadImpl::DeRegisterModule(const Module* module) {
+void ProcessThreadImpl::DeRegisterModule(Module* module) {
   // Allowed to be called on any thread.
   DCHECK(module);
-  rtc::CritScope lock(&lock_);
-  modules_.remove_if([&module](const ModuleCallback& m) {
-      return m.module == module;
-    });
-  return 0;
+  {
+    rtc::CritScope lock(&lock_);
+    modules_.remove_if([&module](const ModuleCallback& m) {
+        return m.module == module;
+      });
+  }
+
+  // Notify the module that it's been detached, while not holding the lock.
+  if (thread_.get())
+    module->ProcessThreadAttached(nullptr);
 }
 
 // static
@@ -148,7 +167,8 @@
       if (m.next_callback == 0)
         m.next_callback = GetNextCallbackTime(m.module, now);
 
-      if (m.next_callback <= now) {
+      if (m.next_callback <= now ||
+          m.next_callback == kCallProcessImmediately) {
         m.module->Process();
         // Use a new 'now' reference to calculate when the next callback
         // should occur.  We'll continue to use 'now' above for the baseline
diff --git a/webrtc/modules/utility/source/process_thread_impl.h b/webrtc/modules/utility/source/process_thread_impl.h
index 7e01ae5..0ba6f1f 100644
--- a/webrtc/modules/utility/source/process_thread_impl.h
+++ b/webrtc/modules/utility/source/process_thread_impl.h
@@ -27,13 +27,13 @@
   ProcessThreadImpl();
   ~ProcessThreadImpl() override;
 
-  int32_t Start() override;
-  int32_t Stop() override;
+  void Start() override;
+  void Stop() override;
 
   void WakeUp(Module* module) override;
 
-  int32_t RegisterModule(Module* module) override;
-  int32_t DeRegisterModule(const Module* module) override;
+  void RegisterModule(Module* module) override;
+  void DeRegisterModule(Module* module) override;
 
  protected:
   static bool Run(void* obj);
diff --git a/webrtc/modules/utility/source/process_thread_impl_unittest.cc b/webrtc/modules/utility/source/process_thread_impl_unittest.cc
index c8b03a6..47af4d8 100644
--- a/webrtc/modules/utility/source/process_thread_impl_unittest.cc
+++ b/webrtc/modules/utility/source/process_thread_impl_unittest.cc
@@ -27,6 +27,7 @@
  public:
   MOCK_METHOD0(TimeUntilNextProcess, int64_t());
   MOCK_METHOD0(Process, int32_t());
+  MOCK_METHOD1(ProcessThreadAttached, void(ProcessThread*));
 };
 
 ACTION_P(SetEvent, event) {
@@ -43,22 +44,22 @@
 
 TEST(ProcessThreadImpl, StartStop) {
   ProcessThreadImpl thread;
-  EXPECT_EQ(0, thread.Start());
-  EXPECT_EQ(0, thread.Stop());
+  thread.Start();
+  thread.Stop();
 }
 
 TEST(ProcessThreadImpl, MultipleStartStop) {
   ProcessThreadImpl thread;
   for (int i = 0; i < 5; ++i) {
-    EXPECT_EQ(0, thread.Start());
-    EXPECT_EQ(0, thread.Stop());
+    thread.Start();
+    thread.Stop();
   }
 }
 
 // Verifies that we get at least call back to Process() on the worker thread.
 TEST(ProcessThreadImpl, ProcessCall) {
   ProcessThreadImpl thread;
-  ASSERT_EQ(0, thread.Start());
+  thread.Start();
 
   rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());
 
@@ -67,10 +68,13 @@
   EXPECT_CALL(module, Process())
       .WillOnce(DoAll(SetEvent(event.get()), Return(0)))
       .WillRepeatedly(Return(0));
+  EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
 
-  ASSERT_EQ(0, thread.RegisterModule(&module));
+  thread.RegisterModule(&module);
   EXPECT_EQ(kEventSignaled, event->Wait(100));
-  EXPECT_EQ(0, thread.Stop());
+
+  EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
+  thread.Stop();
 }
 
 // Same as ProcessCall except the module is registered before the
@@ -85,10 +89,14 @@
       .WillOnce(DoAll(SetEvent(event.get()), Return(0)))
       .WillRepeatedly(Return(0));
 
-  ASSERT_EQ(0, thread.RegisterModule(&module));
-  ASSERT_EQ(thread.Start(), 0);
+  thread.RegisterModule(&module);
+
+  EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
+  thread.Start();
   EXPECT_EQ(kEventSignaled, event->Wait(100));
-  EXPECT_EQ(thread.Stop(), 0);
+
+  EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
+  thread.Stop();
 }
 
 // Tests setting up a module for callbacks and then unregister that module.
@@ -106,18 +114,23 @@
                       Return(0)))
       .WillRepeatedly(DoAll(Increment(&process_count), Return(0)));
 
-  ASSERT_EQ(0, thread.RegisterModule(&module));
-  ASSERT_EQ(0, thread.Start());
+  thread.RegisterModule(&module);
+
+  EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
+  thread.Start();
 
   EXPECT_EQ(kEventSignaled, event->Wait(100));
-  ASSERT_EQ(0, thread.DeRegisterModule(&module));
+
+  EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
+  thread.DeRegisterModule(&module);
+
   EXPECT_GE(process_count, 1);
   int count_after_deregister = process_count;
 
   // We shouldn't get any more callbacks.
   EXPECT_EQ(kEventTimeout, event->Wait(20));
   EXPECT_EQ(count_after_deregister, process_count);
-  EXPECT_EQ(0, thread.Stop());
+  thread.Stop();
 }
 
 // Helper function for testing receiving a callback after a certain amount of
@@ -125,7 +138,7 @@
 // flakiness on bots.
 void ProcessCallAfterAFewMs(int64_t milliseconds) {
   ProcessThreadImpl thread;
-  ASSERT_EQ(0, thread.Start());
+  thread.Start();
 
   rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());
 
@@ -142,12 +155,15 @@
                       Return(0)))
       .WillRepeatedly(Return(0));
 
-  EXPECT_EQ(0, thread.RegisterModule(&module));
+  EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
+  thread.RegisterModule(&module);
 
   // Add a buffer of 50ms due to slowness of some trybots
   // (e.g. win_drmemory_light)
   EXPECT_EQ(kEventSignaled, event->Wait(milliseconds + 50));
-  ASSERT_EQ(0, thread.Stop());
+
+  EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
+  thread.Stop();
 
   ASSERT_GT(start_time, 0);
   ASSERT_GT(called_time, 0);
@@ -187,7 +203,7 @@
 // TODO(tommi): Fix.
 TEST(ProcessThreadImpl, DISABLED_Process50Times) {
   ProcessThreadImpl thread;
-  ASSERT_EQ(0, thread.Start());
+  thread.Start();
 
   rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());
 
@@ -200,10 +216,13 @@
       .WillRepeatedly(DoAll(Increment(&callback_count),
                             Return(0)));
 
-  EXPECT_EQ(0, thread.RegisterModule(&module));
+  EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
+  thread.RegisterModule(&module);
 
   EXPECT_EQ(kEventTimeout, event->Wait(1000));
-  ASSERT_EQ(0, thread.Stop());
+
+  EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
+  thread.Stop();
 
   printf("Callback count: %i\n", callback_count);
   // Check that we got called back up to 50 times.
@@ -217,7 +236,7 @@
 // away when we know the thread is sleeping.
 TEST(ProcessThreadImpl, WakeUp) {
   ProcessThreadImpl thread;
-  ASSERT_EQ(0, thread.Start());
+  thread.Start();
 
   rtc::scoped_ptr<EventWrapper> started(EventWrapper::Create());
   rtc::scoped_ptr<EventWrapper> called(EventWrapper::Create());
@@ -225,24 +244,33 @@
   MockModule module;
   int64_t start_time = 0;
   int64_t called_time = 0;
-  // Ask for a callback after 1000ms first, then 0ms.
+  // Ask for a callback after 1000ms.
+  // TimeUntilNextProcess will be called twice.
+  // The first time we use it to get the thread into a waiting state.
+  // Then we  wake the thread and there should not be another call made to
+  // TimeUntilNextProcess before Process() is called.
+  // The second time TimeUntilNextProcess is then called, is after Process
+  // has been called and we don't expect any more calls.
   EXPECT_CALL(module, TimeUntilNextProcess())
       .WillOnce(DoAll(SetTimestamp(&start_time),
                       SetEvent(started.get()),
                       Return(1000)))
-      .WillRepeatedly(Return(0));
+      .WillOnce(Return(1000));
   EXPECT_CALL(module, Process())
       .WillOnce(DoAll(SetTimestamp(&called_time),
                       SetEvent(called.get()),
                       Return(0)))
       .WillRepeatedly(Return(0));
 
-  EXPECT_EQ(0, thread.RegisterModule(&module));
+  EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
+  thread.RegisterModule(&module);
 
   EXPECT_EQ(kEventSignaled, started->Wait(100));
   thread.WakeUp(&module);
   EXPECT_EQ(kEventSignaled, called->Wait(100));
-  ASSERT_EQ(0, thread.Stop());
+
+  EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
+  thread.Stop();
 
   ASSERT_GT(start_time, 0);
   ASSERT_GT(called_time, 0);
diff --git a/webrtc/video_engine/vie_capturer.cc b/webrtc/video_engine/vie_capturer.cc
index 1798af3..34c5754 100644
--- a/webrtc/video_engine/vie_capturer.cc
+++ b/webrtc/video_engine/vie_capturer.cc
@@ -150,10 +150,7 @@
   capture_module_ = capture_module;
   capture_module_->RegisterCaptureDataCallback(*this);
   capture_module_->AddRef();
-  if (module_process_thread_.RegisterModule(capture_module_) != 0) {
-    return -1;
-  }
-
+  module_process_thread_.RegisterModule(capture_module_);
   return 0;
 }
 
@@ -189,9 +186,7 @@
   }
   capture_module_->AddRef();
   capture_module_->RegisterCaptureDataCallback(*this);
-  if (module_process_thread_.RegisterModule(capture_module_) != 0) {
-    return -1;
-  }
+  module_process_thread_.RegisterModule(capture_module_);
 
   return 0;
 }
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index 7a12b4e..0da41ca 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -141,15 +141,12 @@
 }
 
 int32_t ViEChannel::Init() {
-  if (module_process_thread_.RegisterModule(
-      vie_receiver_.GetReceiveStatistics()) != 0) {
-    return -1;
-  }
+  module_process_thread_.RegisterModule(vie_receiver_.GetReceiveStatistics());
+
   // RTP/RTCP initialization.
   rtp_rtcp_->SetSendingMediaStatus(false);
-  if (module_process_thread_.RegisterModule(rtp_rtcp_.get()) != 0) {
-    return -1;
-  }
+  module_process_thread_.RegisterModule(rtp_rtcp_.get());
+
   rtp_rtcp_->SetKeyFrameRequestMethod(kKeyFrameReqFirRtp);
   rtp_rtcp_->SetRTCPStatus(kRtcpCompound);
   if (paced_sender_) {
@@ -173,9 +170,10 @@
   vcm_->RegisterReceiveStatisticsCallback(this);
   vcm_->RegisterDecoderTimingCallback(this);
   vcm_->SetRenderDelay(kViEDefaultRenderDelayMs);
-  if (module_process_thread_.RegisterModule(vcm_) != 0) {
-    return -1;
-  }
+
+  module_process_thread_.RegisterModule(vcm_);
+  module_process_thread_.RegisterModule(&vie_sync_);
+
 #ifdef VIDEOCODEC_VP8
   if (!disable_default_encoder_) {
     VideoCodec video_codec;
@@ -1835,13 +1833,7 @@
 }
 
 int32_t ViEChannel::SetVoiceChannel(int32_t ve_channel_id,
-                                          VoEVideoSync* ve_sync_interface) {
-  if (ve_sync_interface) {
-    // Register lip sync
-    module_process_thread_.RegisterModule(&vie_sync_);
-  } else {
-    module_process_thread_.DeRegisterModule(&vie_sync_);
-  }
+                                    VoEVideoSync* ve_sync_interface) {
   return vie_sync_.ConfigureSync(ve_channel_id,
                                  ve_sync_interface,
                                  rtp_rtcp_.get(),
diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc
index 9ad2cf8..927440a 100644
--- a/webrtc/voice_engine/channel.cc
+++ b/webrtc/voice_engine/channel.cc
@@ -914,12 +914,8 @@
                      " (Audio coding module)");
     }
     // De-register modules in process thread
-    if (_moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get()) == -1)
-    {
-        WEBRTC_TRACE(kTraceInfo, kTraceVoice,
-                     VoEId(_instanceId,_channelId),
-                     "~Channel() failed to deregister RTP/RTCP module");
-    }
+    _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get());
+
     // End of modules shutdown
 
     // Delete other objects
@@ -955,16 +951,8 @@
 
     // --- Add modules to process thread (for periodic schedulation)
 
-    const bool processThreadFail =
-        ((_moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get()) != 0) ||
-        false);
-    if (processThreadFail)
-    {
-        _engineStatisticsPtr->SetLastError(
-            VE_CANNOT_INIT_CHANNEL, kTraceError,
-            "Channel::Init() modules not registered");
-        return -1;
-    }
+    _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get());
+
     // --- ACM initialization
 
     if ((audio_coding_->InitializeReceiver() == -1) ||
diff --git a/webrtc/voice_engine/transmit_mixer.cc b/webrtc/voice_engine/transmit_mixer.cc
index e8fda19..edd77b8 100644
--- a/webrtc/voice_engine/transmit_mixer.cc
+++ b/webrtc/voice_engine/transmit_mixer.cc
@@ -259,15 +259,8 @@
     _engineStatisticsPtr = &engineStatistics;
     _channelManagerPtr = &channelManager;
 
-    if (_processThreadPtr->RegisterModule(&_monitorModule) == -1)
-    {
-        WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
-                     "TransmitMixer::SetEngineInformation() failed to"
-                     "register the monitor module");
-    } else
-    {
-        _monitorModule.RegisterObserver(*this);
-    }
+    _processThreadPtr->RegisterModule(&_monitorModule);
+    _monitorModule.RegisterObserver(*this);
 
     return 0;
 }
diff --git a/webrtc/voice_engine/voe_base_impl.cc b/webrtc/voice_engine/voe_base_impl.cc
index e44c1a7..72bbad8 100644
--- a/webrtc/voice_engine/voe_base_impl.cc
+++ b/webrtc/voice_engine/voe_base_impl.cc
@@ -314,12 +314,7 @@
 
     if (_shared->process_thread())
     {
-        if (_shared->process_thread()->Start() != 0)
-        {
-            _shared->SetLastError(VE_THREAD_ERROR, kTraceError,
-                "Init() failed to start module process thread");
-            return -1;
-        }
+        _shared->process_thread()->Start();
     }
 
     // Create an internal ADM if the user has not added an external
@@ -347,12 +342,9 @@
 
     // Register the ADM to the process thread, which will drive the error
     // callback mechanism
-    if (_shared->process_thread() &&
-        _shared->process_thread()->RegisterModule(_shared->audio_device()) != 0)
+    if (_shared->process_thread())
     {
-        _shared->SetLastError(VE_AUDIO_DEVICE_MODULE_ERROR, kTraceError,
-            "Init() failed to register the ADM");
-        return -1;
+        _shared->process_thread()->RegisterModule(_shared->audio_device());
     }
 
     bool available(false);
@@ -945,18 +937,10 @@
     {
         if (_shared->audio_device())
         {
-            if (_shared->process_thread()->
-                    DeRegisterModule(_shared->audio_device()) != 0)
-            {
-                _shared->SetLastError(VE_THREAD_ERROR, kTraceError,
-                    "TerminateInternal() failed to deregister ADM");
-            }
+            _shared->process_thread()->DeRegisterModule(
+                _shared->audio_device());
         }
-        if (_shared->process_thread()->Stop() != 0)
-        {
-            _shared->SetLastError(VE_THREAD_ERROR, kTraceError,
-                "TerminateInternal() failed to stop module process thread");
-        }
+        _shared->process_thread()->Stop();
     }
 
     if (_shared->audio_device())