summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-07-26 16:38:44 +0000
committerDavid Robillard <d@drobilla.net>2012-07-26 16:38:44 +0000
commit024d857f0dc239726cc8c042e8b9296e8886af7d (patch)
tree3591b5ac01607b8879342ea8657285f2fecc9abf /src
parent1b38b8bc4e4e5ca9250cca15bb547ce926b0592e (diff)
downloadingen-024d857f0dc239726cc8c042e8b9296e8886af7d.tar.gz
ingen-024d857f0dc239726cc8c042e8b9296e8886af7d.tar.bz2
ingen-024d857f0dc239726cc8c042e8b9296e8886af7d.zip
Fix post processor ordering to be correctly monotonic between both pre-processed events and notifications.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4560 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/server/Context.cpp9
-rw-r--r--src/server/Context.hpp2
-rw-r--r--src/server/PostProcessor.cpp30
3 files changed, 22 insertions, 19 deletions
diff --git a/src/server/Context.cpp b/src/server/Context.cpp
index 0f7555a4..745b849f 100644
--- a/src/server/Context.cpp
+++ b/src/server/Context.cpp
@@ -33,10 +33,11 @@ struct Notification
LV2_URID k = 0,
uint32_t s = 0,
Raul::Atom::TypeID t = 0)
- : port(p), key(k), size(s), type(t)
+ : port(p), time(f), key(k), size(s), type(t)
{}
PortImpl* port;
+ FrameTime time;
LV2_URID key;
uint32_t size;
Raul::Atom::TypeID type;
@@ -74,11 +75,15 @@ Context::notify(LV2_URID key,
}
void
-Context::emit_notifications()
+Context::emit_notifications(FrameTime end)
{
const uint32_t read_space = _event_sink.read_space();
Notification note;
for (uint32_t i = 0; i < read_space; i += sizeof(note)) {
+ if (_event_sink.peek(sizeof(note), &note) != sizeof(note) ||
+ note.time >= end) {
+ return;
+ }
if (_event_sink.read(sizeof(note), &note) == sizeof(note)) {
Raul::Atom value = _engine.world()->forge().alloc(
note.size, note.type, NULL);
diff --git a/src/server/Context.hpp b/src/server/Context.hpp
index bd740504..caebd7a4 100644
--- a/src/server/Context.hpp
+++ b/src/server/Context.hpp
@@ -62,7 +62,7 @@ public:
const void* body = NULL);
/** Emit pending notifications in some other non-realtime thread. */
- void emit_notifications();
+ void emit_notifications(FrameTime end);
inline ID id() const { return _id; }
diff --git a/src/server/PostProcessor.cpp b/src/server/PostProcessor.cpp
index 16b0317d..984f69b5 100644
--- a/src/server/PostProcessor.cpp
+++ b/src/server/PostProcessor.cpp
@@ -54,34 +54,32 @@ PostProcessor::append(ProcessContext& context, Event* first, Event* last)
void
PostProcessor::process()
{
- const FrameTime end_time = _max_time.get();
+ const FrameTime end_time = _max_time.get() + 1;
- /* FIXME: The order here is a bit tricky: if the normal events are
- * processed first, then a deleted port may still have a pending
- * broadcast event which will segfault if executed afterwards.
- * If it's the other way around, broadcasts will be sent for
- * ports the client doesn't even know about yet... */
-
- /* FIXME: process events from all threads if parallel */
-
- /* Process audio thread generated events */
- _engine.process_context().emit_notifications();
+ // To avoid a race, we only process up to tail and never write to _tail
+ Event* const tail = _tail.get();
- /* Process normal events */
Event* ev = _head.get();
if (!ev) {
return;
}
- Event* const tail = _tail.get();
- _head = (Event*)tail->next();
- while (ev && ev->time() <= end_time) {
+ while (ev->time() < end_time) {
Event* const next = (Event*)ev->next();
+
+ // Process audio thread notifications up until this event's time
+ _engine.process_context().emit_notifications(ev->time());
+
+ // Process and delete this event
ev->post_process();
delete ev;
- if (ev == tail) {
+
+ if (ev == tail || next->time() >= end_time) {
+ // Reached end, update _head
+ _head = next;
break;
}
+
ev = next;
}
}