Index: media/midi/midi_service.cc |
diff --git a/media/midi/midi_service.cc b/media/midi/midi_service.cc |
index 0d0112459a8c65939aa85a79ae81db5b80fd5129..a523ae4ff52df0775fb0cab587baf39076a65ded 100644 |
--- a/media/midi/midi_service.cc |
+++ b/media/midi/midi_service.cc |
@@ -4,36 +4,88 @@ |
#include "media/midi/midi_service.h" |
+#include "base/feature_list.h" |
+#include "base/memory/ptr_util.h" |
+#include "base/strings/stringprintf.h" |
#include "media/midi/midi_manager.h" |
+#include "media/midi/midi_switches.h" |
namespace midi { |
+namespace { |
+ |
+// TODO(toyoshim): Support on all platforms. See https://crbug.com/672793. |
+#if defined(OS_LINUX) |
+constexpr bool kIsDynamicInstantiationSupported = true; |
+#else |
+constexpr bool kIsDynamicInstantiationSupported = false; |
+#endif |
+ |
+MidiService* g_midi_service = nullptr; |
+ |
+} // namespace |
+ |
MidiService::MidiService(std::unique_ptr<MidiManager> manager) { |
base::AutoLock lock(lock_); |
- if (manager.get()) |
+ |
+ CHECK(!g_midi_service); |
+ g_midi_service = this; |
+ |
+ is_dynamic_instantiation_enabled_ = false; |
+ active_clients_ = 0u; |
+ if (manager.get()) { |
manager_ = std::move(manager); |
- else |
- manager_.reset(MidiManager::Create()); |
+ } else if (kIsDynamicInstantiationSupported && |
+ base::FeatureList::IsEnabled( |
+ features::kMidiManagerDynamicInstantiation)) { |
+ is_dynamic_instantiation_enabled_ = true; |
+ } else { |
+ manager_ = base::WrapUnique(MidiManager::Create()); |
+ } |
} |
MidiService::~MidiService() { |
base::AutoLock lock(lock_); |
+ |
manager_.reset(); |
+ |
+ CHECK(g_midi_service); |
+ g_midi_service = nullptr; |
+ |
+ base::AutoLock threads_lock(threads_lock_); |
+ threads_.clear(); |
} |
void MidiService::Shutdown() { |
base::AutoLock lock(lock_); |
- manager_->Shutdown(); |
+ if (manager_.get()) |
+ manager_->Shutdown(); |
} |
void MidiService::StartSession(MidiManagerClient* client) { |
base::AutoLock lock(lock_); |
+ if (!manager_.get()) { |
+ CHECK(is_dynamic_instantiation_enabled_); |
+ CHECK_EQ(0u, active_clients_); |
+ manager_.reset(MidiManager::Create()); |
+ } |
+ active_clients_++; |
manager_->StartSession(client); |
} |
void MidiService::EndSession(MidiManagerClient* client) { |
base::AutoLock lock(lock_); |
+ CHECK(manager_.get()); |
+ CHECK_NE(0u, active_clients_); |
manager_->EndSession(client); |
+ active_clients_--; |
+ if (is_dynamic_instantiation_enabled_ && !active_clients_) { |
+ // MidiManager for each platform should be able to shutdown correctly even |
+ // if following Shutdown() call happens in the middle of |
+ // StartInitialization() to support the dynamic instantiation feature. |
+ manager_->Shutdown(); |
+ manager_.reset(); |
+ } |
} |
void MidiService::DispatchSendMidiData(MidiManagerClient* client, |
@@ -44,4 +96,24 @@ void MidiService::DispatchSendMidiData(MidiManagerClient* client, |
manager_->DispatchSendMidiData(client, port_index, data, timestamp); |
} |
+// static |
+scoped_refptr<base::SingleThreadTaskRunner> MidiService::GetTaskRunner( |
+ size_t runner_id) { |
+ // MidiService outlives MidiManager that could call GetTaskRunner(). |
+ return g_midi_service->GetTaskRunnerImpl(runner_id); |
yhirano
2017/02/08 03:50:24
Is it possible to store a MidiService pointer in M
|
+} |
+ |
+scoped_refptr<base::SingleThreadTaskRunner> MidiService::GetTaskRunnerImpl( |
+ size_t runner_id) { |
+ base::AutoLock lock(threads_lock_); |
+ if (threads_.size() <= runner_id) |
+ threads_.resize(runner_id + 1); |
+ if (!threads_[runner_id].get()) { |
+ threads_[runner_id] = base::MakeUnique<base::Thread>( |
+ base::StringPrintf("MidiServiceThread(%zu)", runner_id)); |
+ threads_[runner_id]->Start(); |
+ } |
+ return threads_[runner_id]->task_runner(); |
+} |
+ |
} // namespace midi |