From b119ab34ebbe79a986fbbd56d255b5097af2ac35 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 3 Aug 2023 20:40:31 -0400 Subject: [PATCH] Use queue instead of priority queue for midi::InputQueue. Don't sort by timestamp, assume it is monotonically increasing. --- src/midi.cpp | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/midi.cpp b/src/midi.cpp index 83cba6a2..92a71617 100644 --- a/src/midi.cpp +++ b/src/midi.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include @@ -288,30 +288,13 @@ std::vector Input::getChannels() { static const size_t InputQueue_maxSize = 8192; -struct InputQueue_Compare { - bool operator()(const Message& a, const Message& b) { - return a.getFrame() > b.getFrame(); - } -}; - -struct InputQueue_Queue : std::priority_queue, InputQueue_Compare> { - void reserve(size_t capacity) { - c.reserve(capacity); - } - void clear() { - // Messing with the protected container is dangerous, but completely clearing it should be fine. - c.clear(); - } -}; - struct InputQueue::Internal { - InputQueue_Queue queue; + std::deque queue; std::mutex mutex; }; InputQueue::InputQueue() { internal = new Internal; - internal->queue.reserve(InputQueue_maxSize); } InputQueue::~InputQueue() { @@ -323,19 +306,28 @@ void InputQueue::onMessage(const Message& message) { // Reject MIDI message if queue is full if (internal->queue.size() >= InputQueue_maxSize) return; + // Message timestamp must be monotonically increasing, otherwise clear the queue. + if (!internal->queue.empty() && message.getFrame() < internal->queue.back().getFrame()) { + internal->queue.clear(); + } // Push to queue - internal->queue.push(message); + internal->queue.push_back(message); } bool InputQueue::tryPop(Message* messageOut, int64_t maxFrame) { + // Check if queue is empty before locking, to avoid frequent unnecessary locking if (internal->queue.empty()) return false; std::lock_guard lock(internal->mutex); - const Message& msg = internal->queue.top(); - if (msg.getFrame() <= maxFrame) { - *messageOut = msg; - internal->queue.pop(); + + if (internal->queue.empty()) + return false; + + const Message& message = internal->queue.front(); + if (message.getFrame() <= maxFrame) { + *messageOut = message; + internal->queue.pop_front(); return true; }