summaryrefslogtreecommitdiffstats
path: root/src/server/events/Delta.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2017-01-18 15:28:04 -0500
committerDavid Robillard <d@drobilla.net>2017-01-18 15:28:04 -0500
commit02ae3e9d8bf3f6a5e844706721aad8c0ac9f4340 (patch)
tree5bbfb3eba51024529e3970103bfb0065b26bc8ec /src/server/events/Delta.cpp
parent4e1c349bd3687b866597afda56dc5f1b0c4be4ef (diff)
downloadingen-02ae3e9d8bf3f6a5e844706721aad8c0ac9f4340.tar.gz
ingen-02ae3e9d8bf3f6a5e844706721aad8c0ac9f4340.tar.bz2
ingen-02ae3e9d8bf3f6a5e844706721aad8c0ac9f4340.zip
Fix invalid cross-thread use of mutex
Instead of abusing store mutex for this purpose, extend blocking mechanism of the PreProcessor (designed for atomic bundle execution) to support execution of individual atomic events which must be executed before the next event can be pre-processed.
Diffstat (limited to 'src/server/events/Delta.cpp')
-rw-r--r--src/server/events/Delta.cpp29
1 files changed, 12 insertions, 17 deletions
diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp
index c623d51e..3ee17ee2 100644
--- a/src/server/events/Delta.cpp
+++ b/src/server/events/Delta.cpp
@@ -65,7 +65,7 @@ Delta::Delta(Engine& engine,
, _state(NULL)
, _context(context)
, _type(type)
- , _poly_lock(engine.store()->mutex(), std::defer_lock)
+ , _block(false)
{
if (context != Resource::Graph::DEFAULT) {
for (auto& p : _properties) {
@@ -136,7 +136,6 @@ Delta::pre_process(PreProcessContext& ctx)
const bool is_client = (_subject == "ingen:/clients/this");
const bool is_engine = (_subject == "ingen:/");
const bool is_file = (_subject.substr(0, 5) == "file:");
- bool poly_changed = false;
if (_type == Type::PUT && is_file) {
// Ensure type is Preset, the only supported file put
@@ -175,8 +174,7 @@ Delta::pre_process(PreProcessContext& ctx)
}
}
- // Take a writer lock while we modify the store
- std::unique_lock<Store::Mutex> lock(_engine.store()->mutex());
+ std::lock_guard<Store::Mutex> lock(_engine.store()->mutex());
_object = is_graph_object
? static_cast<Ingen::Resource*>(_engine.store()->get(Node::uri_to_path(_subject)))
@@ -362,8 +360,8 @@ Delta::pre_process(PreProcessContext& ctx)
if (value.get<int32_t>() < 1 || value.get<int32_t>() > 128) {
_status = Status::INVALID_POLY;
} else {
- poly_changed = true;
- op = SpecialType::POLYPHONY;
+ _block = true;
+ op = SpecialType::POLYPHONY;
_graph->prepare_internal_poly(
*_engine.buffer_factory(), value.get<int32_t>());
}
@@ -380,8 +378,8 @@ Delta::pre_process(PreProcessContext& ctx)
} else if (value.type() != uris.forge.Bool) {
_status = Status::BAD_VALUE_TYPE;
} else {
- poly_changed = true;
- op = SpecialType::POLYPHONIC;
+ _block = true;
+ op = SpecialType::POLYPHONIC;
obj->set_property(key, value, value.context());
BlockImpl* block = dynamic_cast<BlockImpl*>(obj);
if (block) {
@@ -427,11 +425,6 @@ Delta::pre_process(PreProcessContext& ctx)
s->pre_process(ctx);
}
- if (poly_changed) {
- lock.unlock();
- _poly_lock.lock();
- }
-
return Event::pre_process_done(
_status == Status::NOT_PREPARED ? Status::SUCCESS : _status,
_subject);
@@ -536,10 +529,6 @@ Delta::execute(RunContext& context)
void
Delta::post_process()
{
- if (_poly_lock.owns_lock()) {
- _poly_lock.unlock();
- }
-
if (_state) {
BlockImpl* block = dynamic_cast<BlockImpl*>(_object);
if (block) {
@@ -620,6 +609,12 @@ Delta::undo(Interface& target)
}
}
+Event::Execution
+Delta::get_execution() const
+{
+ return _block ? Execution::ATOMIC : Execution::NORMAL;
+}
+
} // namespace Events
} // namespace Server
} // namespace Ingen