--- a/src/JackHandler.h Sun Oct 04 20:42:51 2020 +0200
+++ b/src/JackHandler.h Tue Oct 06 01:31:22 2020 +0200
@@ -177,6 +177,13 @@
throw JackException(errorMessage);
}
+ /**
+ * Wait for the signal that is emitted at the end of the real-time processCallback() cycle.
+ */
+ void waitForRTCycle() {
+ pthread_cond_wait(&realTimeContext.processingDone, &realTimeContext.processingLock);
+ }
+
public:
JackHandler(Configuration& configuration) : configuration(configuration) {
@@ -232,7 +239,6 @@
void attribute(const relpipe::common::type::StringX& value) override {
if (relationContext.skip) return;
// TODO: switch to RelationalReaderValueHandler
- // TODO: if (continueProcessing) {} ?
RelationContext& rel = relationContext;
RelationContext::RecordContext& rec = rel.recordContext;
@@ -252,7 +258,8 @@
if (rec.attributeIndex == rel.attributes.size()) {
- while (jack_ringbuffer_write_space(realTimeContext.ringBuffer) < sizeof (MidiMessage)) usleep(1000); // should not happen, the real-time thread should be faster
+ while (continueProcessing && jack_ringbuffer_write_space(realTimeContext.ringBuffer) < sizeof (MidiMessage)) waitForRTCycle(); // should not happen, the real-time thread should be faster; see also note in endOfPipe()
+ if (!continueProcessing) return;
MidiMessage m;
@@ -300,6 +307,13 @@
// Wait until the ring buffer is empty (messages dequeued from the buffer) and real-time cycle was finished (messages passed to JACK)
while (continueProcessing && jack_ringbuffer_read_space(realTimeContext.ringBuffer)) pthread_cond_wait(&realTimeContext.processingDone, &realTimeContext.processingLock);
+
+ // There might be a (rare) race condition.
+ // Between jack_ringbuffer_read_space() and pthread_cond_wait() the real-time thread might finish the cycle and we will miss the pthread_cond_signal()
+ // and will sleep until the next cycle. In endOfPipe() it is not a big problem.
+ // But missing the cycle in attribute() might be worse.
+ // However it should not happen due to the buffer size
+ // and amount of work done in the real-time thread (message copying) vs. amount of work done between the jack_ringbuffer_write_space() and pthread_cond_wait() calls (nothing).
}
void finish(int sig) {