summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2014-03-30 21:13:41 +0000
committerDavid Robillard <d@drobilla.net>2014-03-30 21:13:41 +0000
commit641e6651220719a70c0fc2cdf9abac60458e587a (patch)
treef3c07b69cf9ec0bf65938a5aaad66a8f8044239f
parent8d3e4718aa1fe278b6f696dd3d91275d8f4ff5b2 (diff)
downloadingen-641e6651220719a70c0fc2cdf9abac60458e587a.tar.gz
ingen-641e6651220719a70c0fc2cdf9abac60458e587a.tar.bz2
ingen-641e6651220719a70c0fc2cdf9abac60458e587a.zip
Hopefully fix dead lock issues with locked events.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5346 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r--src/server/PostProcessor.cpp33
-rw-r--r--src/server/PreProcessor.cpp8
2 files changed, 24 insertions, 17 deletions
diff --git a/src/server/PostProcessor.cpp b/src/server/PostProcessor.cpp
index 69668f2b..af429c01 100644
--- a/src/server/PostProcessor.cpp
+++ b/src/server/PostProcessor.cpp
@@ -43,12 +43,16 @@ PostProcessor::append(ProcessContext& context, Event* first, Event* last)
{
assert(first);
assert(last);
- if (_head) {
- _tail.load()->next(first);
+ assert(!last->next());
+
+ /* Note that tail is only used here, not in process(). The head must be
+ checked first here, since if it is NULL the tail pointer is junk. */
+ if (!_head) {
_tail = last;
+ _head = first;
} else {
+ _tail.load()->next(first);
_tail = last;
- _head = first;
}
}
@@ -63,17 +67,14 @@ PostProcessor::process()
{
const FrameTime end_time = _max_time;
- // To avoid a race, we only process up to tail and never write to _tail
- Event* const tail = _tail.load();
-
Event* ev = _head.load();
if (!ev) {
- // Process audio thread notifications up until end
+ // Process audio thread notifications until end
_engine.process_context().emit_notifications(end_time);
return;
}
- while (ev->time() < end_time) {
+ while (ev && ev->time() < end_time) {
Event* const next = (Event*)ev->next();
// Process audio thread notifications up until this event's time
@@ -83,14 +84,18 @@ PostProcessor::process()
ev->post_process();
delete ev;
- if (ev == tail || (next && next->time() >= end_time)) {
- // Reached end, update _head
- _head = next;
- break;
- }
-
ev = next;
}
+
+ // Since _head was not NULL, we know it hasn't been changed since
+ _head = ev;
+
+ /* If next is NULL, then _tail may now be invalid. However, it would cause
+ a race to reset _tail here. Instead, append() checks only _head for
+ emptiness, and resets the tail appropriately. */
+
+ // Process remaining audio thread notifications until end
+ _engine.process_context().emit_notifications(end_time);
}
} // namespace Server
diff --git a/src/server/PreProcessor.cpp b/src/server/PreProcessor.cpp
index aa4f0b06..f786ca10 100644
--- a/src/server/PreProcessor.cpp
+++ b/src/server/PreProcessor.cpp
@@ -56,6 +56,8 @@ PreProcessor::event(Event* const ev)
assert(!ev->is_prepared());
assert(!ev->next());
+ /* Note that tail is only used here, not in process(). The head must be
+ checked first here, since if it is NULL the tail pointer is junk. */
Event* const head = _head.load();
if (!head) {
_head = ev;
@@ -105,9 +107,9 @@ PreProcessor::process(ProcessContext& context, PostProcessor& dest, size_t limit
// Since _head was not NULL, we know it hasn't been changed since
_head = next;
- /* If next is NULL, then _tail may now be invalid. However, in this
- case _head is also NULL so event() will not read _tail. Since it
- could cause a race with event(), _tail is not set to NULL here. */
+ /* If next is NULL, then _tail may now be invalid. However, it would cause
+ a race to reset _tail here. Instead, append() checks only _head for
+ emptiness, and resets the tail appropriately. */
}
return n_processed;