Browse Source

Use queue instead of priority queue for midi::InputQueue. Don't sort by timestamp, assume it is monotonically increasing.

tags/v2.4.0
Andrew Belt 1 year ago
parent
commit
b119ab34eb
1 changed files with 16 additions and 24 deletions
  1. +16
    -24
      src/midi.cpp

+ 16
- 24
src/midi.cpp View File

@@ -1,6 +1,6 @@
#include <map> #include <map>
#include <utility> #include <utility>
#include <queue>
#include <deque>
#include <mutex> #include <mutex>


#include <midi.hpp> #include <midi.hpp>
@@ -288,30 +288,13 @@ std::vector<int> Input::getChannels() {


static const size_t InputQueue_maxSize = 8192; 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<Message, std::vector<Message>, 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 { struct InputQueue::Internal {
InputQueue_Queue queue;
std::deque<Message> queue;
std::mutex mutex; std::mutex mutex;
}; };


InputQueue::InputQueue() { InputQueue::InputQueue() {
internal = new Internal; internal = new Internal;
internal->queue.reserve(InputQueue_maxSize);
} }


InputQueue::~InputQueue() { InputQueue::~InputQueue() {
@@ -323,19 +306,28 @@ void InputQueue::onMessage(const Message& message) {
// Reject MIDI message if queue is full // Reject MIDI message if queue is full
if (internal->queue.size() >= InputQueue_maxSize) if (internal->queue.size() >= InputQueue_maxSize)
return; 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 // Push to queue
internal->queue.push(message);
internal->queue.push_back(message);
} }


bool InputQueue::tryPop(Message* messageOut, int64_t maxFrame) { bool InputQueue::tryPop(Message* messageOut, int64_t maxFrame) {
// Check if queue is empty before locking, to avoid frequent unnecessary locking
if (internal->queue.empty()) if (internal->queue.empty())
return false; return false;


std::lock_guard<std::mutex> lock(internal->mutex); std::lock_guard<std::mutex> 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; return true;
} }




Loading…
Cancel
Save