summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2017-02-12 14:59:56 +0100
committerDavid Robillard <d@drobilla.net>2017-02-12 15:07:11 +0100
commit81d45973412c675e3c0b4a10b64d811a219feeae (patch)
treed1bcab9fb49798d51611730351c611f79f290d79
parentac0042bfe278e86696bea2d52f88730489e97f87 (diff)
downloadingen-81d45973412c675e3c0b4a10b64d811a219feeae.tar.gz
ingen-81d45973412c675e3c0b4a10b64d811a219feeae.tar.bz2
ingen-81d45973412c675e3c0b4a10b64d811a219feeae.zip
Fix atomic event execution
-rw-r--r--src/server/Event.hpp2
-rw-r--r--src/server/PreProcessor.cpp52
-rw-r--r--src/server/PreProcessor.hpp6
-rw-r--r--src/server/events/Delta.cpp9
4 files changed, 42 insertions, 27 deletions
diff --git a/src/server/Event.hpp b/src/server/Event.hpp
index a0adb564..45231cdd 100644
--- a/src/server/Event.hpp
+++ b/src/server/Event.hpp
@@ -95,7 +95,7 @@ public:
/** Return the status (success or error code) of this event. */
Status status() const { return _status; }
- /** Return the blocking behaviour of this event (after pre_process()) */
+ /** Return the blocking behaviour of this event (after construction). */
virtual Execution get_execution() const { return Execution::NORMAL; }
/** Return undo mode of this event. */
diff --git a/src/server/PreProcessor.cpp b/src/server/PreProcessor.cpp
index b5153436..4e2ac364 100644
--- a/src/server/PreProcessor.cpp
+++ b/src/server/PreProcessor.cpp
@@ -92,13 +92,17 @@ PreProcessor::process(RunContext& context, PostProcessor& dest, size_t limit)
case BlockState::PRE_BLOCKED:
if (ev->get_execution() == Event::Execution::BLOCK) {
_block_state = BlockState::BLOCKED;
+ } else if (ev->get_execution() == Event::Execution::ATOMIC) {
+ _block_state = BlockState::PROCESSING;
}
break;
case BlockState::BLOCKED:
break;
case BlockState::PRE_UNBLOCKED:
assert(ev->get_execution() == Event::Execution::BLOCK);
- _block_state = BlockState::PROCESSING;
+ if (ev->get_execution() == Event::Execution::BLOCK) {
+ _block_state = BlockState::PROCESSING;
+ }
break;
case BlockState::PROCESSING:
if (ev->get_execution() == Event::Execution::UNBLOCK) {
@@ -120,8 +124,8 @@ PreProcessor::process(RunContext& context, PostProcessor& dest, size_t limit)
++n_processed;
// Unblock pre-processing if this is a non-bundled atomic event
- if (ev->get_execution() == Event::Execution::ATOMIC &&
- _block_state.load() == BlockState::PRE_BLOCKED) {
+ if (ev->get_execution() == Event::Execution::ATOMIC) {
+ assert(_block_state.load() == BlockState::PROCESSING);
_block_state = BlockState::UNBLOCKED;
}
@@ -194,6 +198,24 @@ PreProcessor::run()
continue;
}
+ // Set block state before enqueueing event
+ switch (ev->get_execution()) {
+ case Event::Execution::NORMAL:
+ break;
+ case Event::Execution::ATOMIC:
+ assert(_block_state == BlockState::UNBLOCKED);
+ _block_state = BlockState::PRE_BLOCKED;
+ break;
+ case Event::Execution::BLOCK:
+ assert(_block_state == BlockState::UNBLOCKED);
+ _block_state = BlockState::PRE_BLOCKED;
+ break;
+ case Event::Execution::UNBLOCK:
+ wait_for_block_state(BlockState::BLOCKED);
+ _block_state = BlockState::PRE_UNBLOCKED;
+ }
+
+ // Prepare event, allowing it to be processed
assert(!ev->is_prepared());
if (ev->pre_process(ctx)) {
switch (ev->get_mode()) {
@@ -214,27 +236,9 @@ PreProcessor::run()
}
assert(ev->is_prepared());
- switch (ev->get_execution()) {
- case Event::Execution::NORMAL:
- break;
- case Event::Execution::ATOMIC:
- assert(_block_state == BlockState::UNBLOCKED);
- _block_state = BlockState::PRE_BLOCKED;
- while (_block_state != BlockState::UNBLOCKED) {
- // Wait for process thread to execute event
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- }
- break;
- case Event::Execution::BLOCK:
- assert(_block_state == BlockState::UNBLOCKED);
- _block_state = BlockState::PRE_BLOCKED;
- break;
- case Event::Execution::UNBLOCK:
- while (_block_state != BlockState::BLOCKED) {
- // Wait for process thread to reach blocking event
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- }
- _block_state = BlockState::PRE_UNBLOCKED;
+ // Wait for process() if necessary
+ if (ev->get_execution() == Event::Execution::ATOMIC) {
+ wait_for_block_state(BlockState::UNBLOCKED);
}
back = (Event*)ev->next();
diff --git a/src/server/PreProcessor.hpp b/src/server/PreProcessor.hpp
index 61598ee0..eb72328e 100644
--- a/src/server/PreProcessor.hpp
+++ b/src/server/PreProcessor.hpp
@@ -65,6 +65,12 @@ private:
PROCESSING ///< Process thread is executing all events in-between
};
+ void wait_for_block_state(const BlockState state) {
+ while (_block_state != state) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ }
+
Engine& _engine;
std::mutex _mutex;
Raul::Semaphore _sem;
diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp
index 3ee17ee2..2ad258fd 100644
--- a/src/server/events/Delta.cpp
+++ b/src/server/events/Delta.cpp
@@ -72,6 +72,13 @@ Delta::Delta(Engine& engine,
p.second.set_context(context);
}
}
+
+ // Set atomic execution if polyphony is to be changed
+ const Ingen::URIs& uris = _engine.world()->uris();
+ if (properties.count(uris.ingen_polyphonic) ||
+ properties.count(uris.ingen_polyphony)) {
+ _block = true;
+ }
}
Delta::~Delta()
@@ -360,7 +367,6 @@ Delta::pre_process(PreProcessContext& ctx)
if (value.get<int32_t>() < 1 || value.get<int32_t>() > 128) {
_status = Status::INVALID_POLY;
} else {
- _block = true;
op = SpecialType::POLYPHONY;
_graph->prepare_internal_poly(
*_engine.buffer_factory(), value.get<int32_t>());
@@ -378,7 +384,6 @@ Delta::pre_process(PreProcessContext& ctx)
} else if (value.type() != uris.forge.Bool) {
_status = Status::BAD_VALUE_TYPE;
} else {
- _block = true;
op = SpecialType::POLYPHONIC;
obj->set_property(key, value, value.context());
BlockImpl* block = dynamic_cast<BlockImpl*>(obj);