# HG changeset patch # User František Kučera # Date 1601940682 -7200 # Node ID ccc4e509c1f0a4e4be92b0a9509cd7380a29fb4c # Parent dcd98589f4b82a6580018c48dc28dc0de38ae29c use signal instead of sleep while waiting in attribute() diff -r dcd98589f4b8 -r ccc4e509c1f0 src/JackHandler.h --- 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) {