Index: media/midi/midi_manager_alsa.cc |
diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc |
index 682197b558429db297a48caeaa42f183aa5f9880..1ef6e569483722ee66154c981a067fce98d06dba 100644 |
--- a/media/midi/midi_manager_alsa.cc |
+++ b/media/midi/midi_manager_alsa.cc |
@@ -28,6 +28,7 @@ |
#include "crypto/sha2.h" |
#include "media/midi/midi_port_info.h" |
#include "media/midi/midi_service.h" |
+#include "media/midi/task_service.h" |
namespace midi { |
@@ -36,15 +37,17 @@ namespace { |
using mojom::PortState; |
using mojom::Result; |
-// TODO(toyoshim): use constexpr for following const values. |
-const int kEventTaskRunner = 0; |
-const int kSendTaskRunner = 1; |
+enum { |
+ kDefaultRunnerNotUsedOnAlsa = TaskService::kDefaultRunnerId, |
+ kEventTaskRunner, |
+ kSendTaskRunner |
+}; |
// Per-output buffer. This can be smaller, but then large sysex messages |
// will be (harmlessly) split across multiple seq events. This should |
// not have any real practical effect, except perhaps to slightly reorder |
// realtime messages with respect to sysex. |
-const size_t kSendBufferSize = 256; |
+constexpr size_t kSendBufferSize = 256; |
// Minimum client id for which we will have ALSA card devices for. When we |
// are searching for card devices (used to get the path, id, and manufacturer), |
@@ -52,7 +55,7 @@ const size_t kSendBufferSize = 256; |
// See seq_clientmgr.c in the ALSA code for this. |
// TODO(agoode): Add proper client -> card export from the kernel to avoid |
// hardcoding. |
-const int kMinimumClientIdForCards = 16; |
+constexpr int kMinimumClientIdForCards = 16; |
// ALSA constants. |
const char kAlsaHw[] = "hw"; |
@@ -83,37 +86,18 @@ const char kCardSyspath[] = "/card"; |
// Constants for the capabilities we search for in inputs and outputs. |
// See http://www.alsa-project.org/alsa-doc/alsa-lib/seq.html. |
-const unsigned int kRequiredInputPortCaps = |
+constexpr unsigned int kRequiredInputPortCaps = |
SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; |
-const unsigned int kRequiredOutputPortCaps = |
+constexpr unsigned int kRequiredOutputPortCaps = |
SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; |
-const unsigned int kCreateOutputPortCaps = |
+constexpr unsigned int kCreateOutputPortCaps = |
SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_NO_EXPORT; |
-const unsigned int kCreateInputPortCaps = |
+constexpr unsigned int kCreateInputPortCaps = |
SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT; |
-const unsigned int kCreatePortType = |
+constexpr unsigned int kCreatePortType = |
SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION; |
-// Global variables to identify MidiManagerAlsa instance. |
-const int kInvalidInstanceId = -1; |
-int g_active_instance_id = kInvalidInstanceId; |
-int g_next_instance_id = 0; |
- |
-struct MidiManagerLockHelper { |
- base::Lock instance_id_lock; |
- |
- // Prevent current instance from quiting Finalize() while tasks run on |
- // external TaskRunners. |
- base::Lock event_task_lock; |
- base::Lock send_task_lock; |
-}; |
- |
-MidiManagerLockHelper* GetLockHelper() { |
- static MidiManagerLockHelper* lock_helper = new MidiManagerLockHelper(); |
- return lock_helper; |
-} |
- |
int AddrToInt(int client, int port) { |
return (client << 8) | port; |
} |
@@ -180,34 +164,20 @@ void SetStringIfNonEmpty(base::DictionaryValue* value, |
MidiManagerAlsa::MidiManagerAlsa(MidiService* service) : MidiManager(service) {} |
MidiManagerAlsa::~MidiManagerAlsa() { |
- // Take lock to ensure that the members initialized on the IO thread |
- // are not destructed here. |
- base::AutoLock lock(lazy_init_member_lock_); |
- |
// Extra CHECK to verify all members are already reset. |
- CHECK(!initialization_thread_checker_); |
CHECK(!in_client_); |
CHECK(!out_client_); |
CHECK(!decoder_); |
CHECK(!udev_); |
CHECK(!udev_monitor_); |
- |
- base::AutoLock instance_id_lock(GetLockHelper()->instance_id_lock); |
- CHECK_EQ(kInvalidInstanceId, g_active_instance_id); |
} |
void MidiManagerAlsa::StartInitialization() { |
- { |
- base::AutoLock lock(GetLockHelper()->instance_id_lock); |
- CHECK_EQ(kInvalidInstanceId, g_active_instance_id); |
- instance_id_ = g_next_instance_id++; |
- g_active_instance_id = instance_id_; |
+ if (!service()->task_service()->BindInstance()) { |
+ NOTREACHED(); |
+ return CompleteInitialization(Result::INITIALIZATION_ERROR); |
} |
- base::AutoLock lock(lazy_init_member_lock_); |
- |
- initialization_thread_checker_.reset(new base::ThreadChecker()); |
- |
// Create client handles. |
snd_seq_t* tmp_seq = nullptr; |
int err = |
@@ -318,43 +288,27 @@ void MidiManagerAlsa::StartInitialization() { |
// Start processing events. Don't do this before enumeration of both |
// ALSA and udev. |
- service() |
- ->GetTaskRunner(kEventTaskRunner) |
- ->PostTask(FROM_HERE, base::Bind(&MidiManagerAlsa::EventLoop, |
- base::Unretained(this), instance_id_)); |
+ service()->task_service()->PostBoundTask( |
+ kEventTaskRunner, |
+ base::BindOnce(&MidiManagerAlsa::EventLoop, base::Unretained(this))); |
CompleteInitialization(Result::OK); |
} |
void MidiManagerAlsa::Finalize() { |
- base::AutoLock lock(lazy_init_member_lock_); |
- DCHECK(initialization_thread_checker_->CalledOnValidThread()); |
- |
- // Tell tasks running on TaskRunners it will soon be time to shut down. This |
- // gives us assurance a task running on kEventTaskRunner will stop in case the |
- // SND_SEQ_EVENT_CLIENT_EXIT message is lost. |
- { |
- base::AutoLock lock(GetLockHelper()->instance_id_lock); |
- CHECK_EQ(instance_id_, g_active_instance_id); |
- g_active_instance_id = kInvalidInstanceId; |
- } |
- |
- // Ensure that no tasks run on kSendTaskRunner. |
- base::AutoLock send_runner_lock(GetLockHelper()->send_task_lock); |
- |
// Close the out client. This will trigger the event thread to stop, |
// because of SND_SEQ_EVENT_CLIENT_EXIT. |
out_client_.reset(); |
- // Ensure that no tasks run on kEventTaskRunner. |
- base::AutoLock event_runner_lock(GetLockHelper()->event_task_lock); |
+ // Ensure that no task is running any more. |
+ bool result = service()->task_service()->UnbindInstance(); |
+ CHECK(result); |
// Destruct the other stuff we initialized in StartInitialization(). |
udev_monitor_.reset(); |
udev_.reset(); |
decoder_.reset(); |
in_client_.reset(); |
- initialization_thread_checker_.reset(); |
} |
void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client, |
@@ -369,13 +323,11 @@ void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client, |
delay = std::max(time_to_send - base::TimeTicks::Now(), base::TimeDelta()); |
} |
- service() |
- ->GetTaskRunner(kSendTaskRunner) |
- ->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&MidiManagerAlsa::SendMidiData, base::Unretained(this), |
- instance_id_, client, port_index, data), |
- delay); |
+ service()->task_service()->PostBoundDelayedTask( |
+ kSendTaskRunner, |
+ base::BindOnce(&MidiManagerAlsa::SendMidiData, base::Unretained(this), |
+ client, port_index, data), |
+ delay); |
} |
MidiManagerAlsa::MidiPort::Id::Id() = default; |
@@ -892,23 +844,9 @@ std::string MidiManagerAlsa::AlsaCard::ExtractManufacturerString( |
return ""; |
} |
-void MidiManagerAlsa::SendMidiData(int instance_id, |
- MidiManagerClient* client, |
+void MidiManagerAlsa::SendMidiData(MidiManagerClient* client, |
uint32_t port_index, |
const std::vector<uint8_t>& data) { |
- DCHECK(service()->GetTaskRunner(kSendTaskRunner)->BelongsToCurrentThread()); |
- |
- // Obtain the lock so that the instance could not be destructed while this |
- // method is running on the kSendTaskRunner. |
- base::AutoLock lock(GetLockHelper()->send_task_lock); |
- { |
- // Check if Finalize() already runs. After this check, we can access |this| |
- // safely on the kEventTaskRunner. |
- base::AutoLock instance_id_lock(GetLockHelper()->instance_id_lock); |
- if (instance_id != g_active_instance_id) |
- return; |
- } |
- |
snd_midi_event_t* encoder; |
snd_midi_event_new(kSendBufferSize, &encoder); |
for (const auto datum : data) { |
@@ -932,18 +870,7 @@ void MidiManagerAlsa::SendMidiData(int instance_id, |
AccumulateMidiBytesSent(client, data.size()); |
} |
-void MidiManagerAlsa::EventLoop(int instance_id) { |
- // Obtain the lock so that the instance could not be destructed while this |
- // method is running on the kEventTaskRunner. |
- base::AutoLock lock(GetLockHelper()->event_task_lock); |
- { |
- // Check if Finalize() already runs. After this check, we can access |this| |
- // safely on the kEventTaskRunner. |
- base::AutoLock instance_id_lock(GetLockHelper()->instance_id_lock); |
- if (instance_id != g_active_instance_id) |
- return; |
- } |
- |
+void MidiManagerAlsa::EventLoop() { |
bool loop_again = true; |
struct pollfd pfd[2]; |
@@ -1020,10 +947,9 @@ void MidiManagerAlsa::EventLoop(int instance_id) { |
// Do again. |
if (loop_again) { |
- service() |
- ->GetTaskRunner(kEventTaskRunner) |
- ->PostTask(FROM_HERE, base::Bind(&MidiManagerAlsa::EventLoop, |
- base::Unretained(this), instance_id)); |
+ service()->task_service()->PostBoundTask( |
+ kEventTaskRunner, |
+ base::BindOnce(&MidiManagerAlsa::EventLoop, base::Unretained(this))); |
} |
} |