diff options
author | David Robillard <d@drobilla.net> | 2017-02-12 14:59:56 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2017-02-12 15:07:11 +0100 |
commit | 81d45973412c675e3c0b4a10b64d811a219feeae (patch) | |
tree | d1bcab9fb49798d51611730351c611f79f290d79 | |
parent | ac0042bfe278e86696bea2d52f88730489e97f87 (diff) | |
download | ingen-81d45973412c675e3c0b4a10b64d811a219feeae.tar.gz ingen-81d45973412c675e3c0b4a10b64d811a219feeae.tar.bz2 ingen-81d45973412c675e3c0b4a10b64d811a219feeae.zip |
Fix atomic event execution
-rw-r--r-- | src/server/Event.hpp | 2 | ||||
-rw-r--r-- | src/server/PreProcessor.cpp | 52 | ||||
-rw-r--r-- | src/server/PreProcessor.hpp | 6 | ||||
-rw-r--r-- | src/server/events/Delta.cpp | 9 |
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); |