Chromium Code Reviews| Index: media/audio/audio_manager_base.cc |
| diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc |
| index 696dd869aa79888e0fbd7769fc90a835cd2348cc..9202e58c0f39804522637a89b77813b4b30efa53 100644 |
| --- a/media/audio/audio_manager_base.cc |
| +++ b/media/audio/audio_manager_base.cc |
| @@ -5,6 +5,8 @@ |
| #include "media/audio/audio_manager_base.h" |
| #include "base/bind.h" |
| +#include "base/message_loop_proxy.h" |
| +#include "base/threading/thread.h" |
| #include "media/audio/audio_output_dispatcher.h" |
| #include "media/audio/audio_output_proxy.h" |
| @@ -14,8 +16,7 @@ const char AudioManagerBase::kDefaultDeviceName[] = "Default"; |
| const char AudioManagerBase::kDefaultDeviceId[] = "default"; |
| AudioManagerBase::AudioManagerBase() |
| - : audio_thread_("AudioThread"), |
| - num_active_input_streams_(0) { |
| + : num_active_input_streams_(0) { |
| } |
| AudioManagerBase::~AudioManagerBase() { |
| @@ -24,36 +25,45 @@ AudioManagerBase::~AudioManagerBase() { |
| #ifndef NDEBUG |
| void AudioManagerBase::AddRef() const { |
| - const MessageLoop* loop = audio_thread_.message_loop(); |
| - DCHECK(loop == NULL || loop != MessageLoop::current()); |
| + { |
| + base::AutoLock lock(audio_thread_lock_); |
| + const MessageLoop* loop = audio_thread_.get() ? |
| + audio_thread_->message_loop() : NULL; |
| + DCHECK(loop == NULL || loop != MessageLoop::current()); |
| + } |
| AudioManager::AddRef(); |
| } |
| void AudioManagerBase::Release() const { |
| - const MessageLoop* loop = audio_thread_.message_loop(); |
| - DCHECK(loop == NULL || loop != MessageLoop::current()); |
| + { |
| + base::AutoLock lock(audio_thread_lock_); |
| + const MessageLoop* loop = audio_thread_.get() ? |
| + audio_thread_->message_loop() : NULL; |
| + DCHECK(loop == NULL || loop != MessageLoop::current()); |
| + } |
| AudioManager::Release(); |
| } |
| #endif |
| void AudioManagerBase::Init() { |
| - CHECK(audio_thread_.Start()); |
| + base::AutoLock lock(audio_thread_lock_); |
| + DCHECK(!audio_thread_.get()); |
| + audio_thread_.reset(new base::Thread("AudioThread")); |
| + CHECK(audio_thread_->Start()); |
| } |
| string16 AudioManagerBase::GetAudioInputDeviceModel() { |
| return string16(); |
| } |
| -MessageLoop* AudioManagerBase::GetMessageLoop() { |
| - return audio_thread_.message_loop(); |
| +scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetMessageLoop() { |
| + base::AutoLock lock(audio_thread_lock_); |
| + return audio_thread_.get() ? audio_thread_->message_loop_proxy() : NULL; |
| } |
| AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( |
| const AudioParameters& params) { |
| - DCHECK_EQ(MessageLoop::current(), GetMessageLoop()); |
| - |
| - if (!initialized()) |
| - return NULL; |
| + DCHECK(GetMessageLoop()->BelongsToCurrentThread()); |
| scoped_refptr<AudioOutputDispatcher>& dispatcher = |
| output_dispatchers_[params]; |
| @@ -88,23 +98,34 @@ bool AudioManagerBase::IsRecordingInProcess() { |
| } |
| void AudioManagerBase::Shutdown() { |
| - if (!initialized()) |
| - return; |
| + // To avoid running into deadlocks while we stop the thread, shut it down |
| + // via a local variable while not holding the audio thread lock. |
| + scoped_ptr<base::Thread> audio_thread; |
| + { |
| + base::AutoLock lock(audio_thread_lock_); |
| + audio_thread_.swap(audio_thread); |
| + } |
| - DCHECK_NE(MessageLoop::current(), GetMessageLoop()); |
| + if (!audio_thread.get()) |
| + return; |
|
scherkus (not reviewing)
2012/01/18 18:12:31
indent
|
| + |
| + CHECK_NE(MessageLoop::current(), audio_thread->message_loop()); |
| // We must use base::Unretained since Shutdown might have been called from |
| // the destructor and we can't alter the refcount of the object at that point. |
| - GetMessageLoop()->PostTask(FROM_HERE, base::Bind( |
| + audio_thread->message_loop()->PostTask(FROM_HERE, base::Bind( |
| &AudioManagerBase::ShutdownOnAudioThread, |
| base::Unretained(this))); |
| + |
| // Stop() will wait for any posted messages to be processed first. |
| - audio_thread_.Stop(); |
| + audio_thread->Stop(); |
| } |
| void AudioManagerBase::ShutdownOnAudioThread() { |
| - DCHECK_EQ(MessageLoop::current(), GetMessageLoop()); |
| - |
| + // This should always be running on the audio thread, but since we've cleared |
| + // the audio_thread_ member pointer when we get here, we can't verify exactly |
| + // what thread we're running on. The method is not public though and only |
| + // called from one place, so we'll leave it at that. |
| AudioOutputDispatchersMap::iterator it = output_dispatchers_.begin(); |
| for (; it != output_dispatchers_.end(); ++it) { |
| scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it).second; |