diff options
36 files changed, 233 insertions, 81 deletions
diff --git a/ingen/ingen.h b/ingen/ingen.h index e4a36ade..11fd592a 100644 --- a/ingen/ingen.h +++ b/ingen/ingen.h @@ -34,6 +34,14 @@ # define INGEN_API #endif +#ifndef INGEN_WARN_UNUSED_RESULT +# if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 4 +# define INGEN_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +# else +# define INGEN_WARN_UNUSED_RESULT +# endif +#endif + #define INGEN_NS "http://drobilla.net/ns/ingen#" #define INGEN__Arc INGEN_NS "Arc" diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index 893f6f92..0b468ce1 100644 --- a/src/server/Engine.cpp +++ b/src/server/Engine.cpp @@ -47,6 +47,7 @@ #include "GraphImpl.hpp" #include "LV2Options.hpp" #include "PostProcessor.hpp" +#include "PreProcessContext.hpp" #include "PreProcessor.hpp" #include "RunContext.hpp" #include "ThreadManager.hpp" @@ -374,9 +375,10 @@ Engine::activate() *this, SPtr<Interface>(), -1, 0, Raul::Path("/"), graph_properties); // Execute in "fake" process context (we are single threaded) - RunContext context(run_context()); - ev.pre_process(); - ev.execute(context); + PreProcessContext pctx; + RunContext rctx(run_context()); + ev.pre_process(pctx); + ev.execute(rctx); ev.post_process(); _root_graph = ev.graph(); diff --git a/src/server/Event.hpp b/src/server/Event.hpp index 8ed25c0f..203e5d1d 100644 --- a/src/server/Event.hpp +++ b/src/server/Event.hpp @@ -35,6 +35,7 @@ namespace Server { class Engine; class RunContext; +class PreProcessContext; /** An event (command) to perform some action on Ingen. * @@ -60,7 +61,7 @@ public: enum class Execution { NORMAL, BLOCK, UNBLOCK }; /** Pre-process event before execution (non-realtime). */ - virtual bool pre_process() = 0; + virtual bool pre_process(PreProcessContext& ctx) = 0; /** Execute this event in the audio thread (realtime). */ virtual void execute(RunContext& context) = 0; diff --git a/src/server/GraphImpl.cpp b/src/server/GraphImpl.cpp index bdd0a69a..c1ee6a2b 100644 --- a/src/server/GraphImpl.cpp +++ b/src/server/GraphImpl.cpp @@ -297,14 +297,15 @@ GraphImpl::has_arc(const PortImpl* tail, const PortImpl* dst_port) const return (i != _arcs.end()); } -void -GraphImpl::set_compiled_graph(CompiledGraph* cg) +CompiledGraph* +GraphImpl::swap_compiled_graph(CompiledGraph* cg) { - if (_compiled_graph && _compiled_graph != cg) { - _engine.maid()->dispose(_compiled_graph); + CompiledGraph* const old = _compiled_graph; + if (old && cg != old) { _engine.reset_load(); } _compiled_graph = cg; + return old; } uint32_t diff --git a/src/server/GraphImpl.hpp b/src/server/GraphImpl.hpp index 124614de..f7d0be32 100644 --- a/src/server/GraphImpl.hpp +++ b/src/server/GraphImpl.hpp @@ -19,6 +19,8 @@ #include <cstdlib> +#include "ingen/ingen.h" + #include "BlockImpl.hpp" #include "CompiledGraph.hpp" #include "DuplexPort.hpp" @@ -160,7 +162,8 @@ public: bool has_arc(const PortImpl* tail, const PortImpl* head) const; - void set_compiled_graph(CompiledGraph* cp); + /** Set a new compiled graph to run, and return the old one. */ + CompiledGraph* swap_compiled_graph(CompiledGraph* cp) INGEN_WARN_UNUSED_RESULT; Raul::Array<PortImpl*>* external_ports() { return _ports; } void external_ports(Raul::Array<PortImpl*>* pa) { _ports = pa; } @@ -185,7 +188,7 @@ private: Ports _inputs; ///< Pre-process thread only Ports _outputs; ///< Pre-process thread only Blocks _blocks; ///< Pre-process thread only - bool _process; + bool _process; ///< True iff graph is enabled }; } // namespace Server diff --git a/src/server/PostProcessor.cpp b/src/server/PostProcessor.cpp index 65323f7f..6c709518 100644 --- a/src/server/PostProcessor.cpp +++ b/src/server/PostProcessor.cpp @@ -30,7 +30,7 @@ class Sentinel : public Event { public: Sentinel(Engine& engine) : Event(engine) {} - bool pre_process() { return false; } + bool pre_process(PreProcessContext& ctx) { return false; } void execute(RunContext& context) {} void post_process() {} }; diff --git a/src/server/PreProcessContext.hpp b/src/server/PreProcessContext.hpp new file mode 100644 index 00000000..bf1115e8 --- /dev/null +++ b/src/server/PreProcessContext.hpp @@ -0,0 +1,70 @@ +/* + This file is part of Ingen. + Copyright 2007-2016 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_ENGINE_PREPROCESSCONTEXT_HPP +#define INGEN_ENGINE_PREPROCESSCONTEXT_HPP + +#include <unordered_set> + +#include "GraphImpl.hpp" + +namespace Ingen { +namespace Server { + +/** Event pre-processing context. + * + * \ingroup engine + */ +class PreProcessContext +{ +public: + typedef std::unordered_set<GraphImpl*> DirtyGraphs; + + /** Return true iff an atomic bundle is currently being pre-processed. */ + bool in_bundle() const { return _in_bundle; } + + /** Set/unset atomic bundle flag. */ + void set_in_bundle(bool b) { _in_bundle = b; } + + /** Return true iff graph should be compiled now (after a change). + * + * This may return false when an atomic bundle is deferring compilation, in + * which case the graph is flagged as dirty for later compilation. + */ + bool must_compile(GraphImpl* graph) { + if (!graph->enabled()) { + return false; + } else if (_in_bundle) { + _dirty_graphs.insert(graph); + return false; + } else { + return true; + } + } + + /** Return all graphs that require compilation after an atomic bundle. */ + const DirtyGraphs& dirty_graphs() const { return _dirty_graphs; } + DirtyGraphs& dirty_graphs() { return _dirty_graphs; } + +private: + DirtyGraphs _dirty_graphs; + bool _in_bundle = false; +}; + +} // namespace Server +} // namespace Ingen + +#endif // INGEN_ENGINE_PREPROCESSCONTEXT_HPP diff --git a/src/server/PreProcessor.cpp b/src/server/PreProcessor.cpp index f0008afc..9933bde2 100644 --- a/src/server/PreProcessor.cpp +++ b/src/server/PreProcessor.cpp @@ -18,10 +18,12 @@ #include "ingen/AtomSink.hpp" #include "ingen/AtomWriter.hpp" +#include "ingen/Configuration.hpp" #include "Engine.hpp" #include "Event.hpp" #include "PostProcessor.hpp" +#include "PreProcessContext.hpp" #include "PreProcessor.hpp" #include "RunContext.hpp" #include "ThreadManager.hpp" @@ -131,6 +133,14 @@ PreProcessor::process(RunContext& context, PostProcessor& dest, size_t limit) } if (n_processed > 0) { + Engine& engine = context.engine(); + if (engine.world()->conf().option("trace").get<int32_t>()) { + const uint64_t start = engine.cycle_start_time(context); + const uint64_t end = engine.current_time(context); + fprintf(stderr, "Processed %zu events in %zu us\n", + n_processed, end - start); + } + Event* next = (Event*)last->next(); last->next(NULL); dest.append(context, head, last); @@ -149,6 +159,8 @@ PreProcessor::process(RunContext& context, PostProcessor& dest, size_t limit) void PreProcessor::run() { + PreProcessContext ctx; + UndoStack& undo_stack = *_engine.undo_stack(); UndoStack& redo_stack = *_engine.redo_stack(); AtomWriter undo_writer( @@ -168,7 +180,7 @@ PreProcessor::run() } assert(!ev->is_prepared()); - if (ev->pre_process()) { + if (ev->pre_process(ctx)) { switch (ev->get_mode()) { case Event::Mode::NORMAL: case Event::Mode::REDO: diff --git a/src/server/events/Connect.cpp b/src/server/events/Connect.cpp index 17fa640f..35084ea6 100644 --- a/src/server/events/Connect.cpp +++ b/src/server/events/Connect.cpp @@ -26,8 +26,9 @@ #include "InputPort.hpp" #include "OutputPort.hpp" #include "PortImpl.hpp" -#include "types.hpp" +#include "PreProcessContext.hpp" #include "internals/BlockDelay.hpp" +#include "types.hpp" namespace Ingen { namespace Server { @@ -49,7 +50,7 @@ Connect::Connect(Engine& engine, {} bool -Connect::pre_process() +Connect::pre_process(PreProcessContext& ctx) { std::lock_guard<std::mutex> lock(_engine.store()->mutex()); @@ -125,7 +126,7 @@ Connect::pre_process() tail_block->dependants().insert(head_block); } - if (_graph->enabled()) { + if (ctx.must_compile(_graph)) { if (!(_compiled_graph = CompiledGraph::compile(_graph))) { head_block->providers().erase(tail_block); tail_block->dependants().erase(head_block); @@ -161,7 +162,7 @@ Connect::execute(RunContext& context) } _head->connect_buffers(); if (_compiled_graph) { - _graph->set_compiled_graph(_compiled_graph); + _compiled_graph = _graph->swap_compiled_graph(_compiled_graph); } } } @@ -181,6 +182,8 @@ Connect::post_process() Node::path_to_uri(_tail_path), _tail_remove, _tail_add); } } + + delete _compiled_graph; } void diff --git a/src/server/events/Connect.hpp b/src/server/events/Connect.hpp index 84b2854b..9b98b167 100644 --- a/src/server/events/Connect.hpp +++ b/src/server/events/Connect.hpp @@ -52,7 +52,7 @@ public: const Raul::Path& tail, const Raul::Path& head); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); diff --git a/src/server/events/Copy.cpp b/src/server/events/Copy.cpp index 8959e4e1..03519610 100644 --- a/src/server/events/Copy.cpp +++ b/src/server/events/Copy.cpp @@ -26,6 +26,7 @@ #include "Engine.hpp" #include "EnginePort.hpp" #include "GraphImpl.hpp" +#include "PreProcessContext.hpp" #include "events/Copy.hpp" namespace Ingen { @@ -48,7 +49,7 @@ Copy::Copy(Engine& engine, {} bool -Copy::pre_process() +Copy::pre_process(PreProcessContext& ctx) { std::lock_guard<std::mutex> lock(_engine.store()->mutex()); @@ -69,16 +70,16 @@ Copy::pre_process() if (Node::uri_is_path(_new_uri)) { // Copy to path within the engine - return engine_to_engine(); + return engine_to_engine(ctx); } else if (_new_uri.scheme() == "file") { // Copy to filesystem path (i.e. save) - return engine_to_filesystem(); + return engine_to_filesystem(ctx); } else { return Event::pre_process_done(Status::BAD_REQUEST); } } else if (_old_uri.scheme() == "file") { if (Node::uri_is_path(_new_uri)) { - filesystem_to_engine(); + filesystem_to_engine(ctx); } else { // Ingen is not your file manager return Event::pre_process_done(Status::BAD_REQUEST); @@ -89,7 +90,7 @@ Copy::pre_process() } bool -Copy::engine_to_engine() +Copy::engine_to_engine(PreProcessContext& ctx) { // Only support a single source for now const Raul::Path new_path = Node::uri_to_path(_new_uri); @@ -125,7 +126,7 @@ Copy::engine_to_engine() _engine.store()->add(_block); // Compile graph with new block added for insertion in audio thread - if (_parent->enabled()) { + if (ctx.must_compile(_parent)) { _compiled_graph = CompiledGraph::compile(_parent); } @@ -142,7 +143,7 @@ ends_with(const std::string& str, const std::string& end) } bool -Copy::engine_to_filesystem() +Copy::engine_to_filesystem(PreProcessContext& ctx) { // Ensure source is a graph SPtr<GraphImpl> graph = dynamic_ptr_cast<GraphImpl>(_old_block); @@ -168,7 +169,7 @@ Copy::engine_to_filesystem() } bool -Copy::filesystem_to_engine() +Copy::filesystem_to_engine(PreProcessContext& ctx) { if (!_engine.world()->parser()) { return Event::pre_process_done(Status::INTERNAL_ERROR); @@ -196,9 +197,8 @@ Copy::filesystem_to_engine() void Copy::execute(RunContext& context) { - if (_block) { - _parent->set_compiled_graph(_compiled_graph); - _compiled_graph = NULL; // Graph takes ownership + if (_block && _compiled_graph) { + _compiled_graph = _parent->swap_compiled_graph(_compiled_graph); } } @@ -209,6 +209,7 @@ Copy::post_process() if (respond() == Status::SUCCESS) { _engine.broadcaster()->copy(_old_uri, _new_uri); } + delete _compiled_graph; } void diff --git a/src/server/events/Copy.hpp b/src/server/events/Copy.hpp index 68ee31da..55310757 100644 --- a/src/server/events/Copy.hpp +++ b/src/server/events/Copy.hpp @@ -46,15 +46,15 @@ public: const Raul::URI& old_uri, const Raul::URI& new_uri); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); private: - bool engine_to_engine(); - bool engine_to_filesystem(); - bool filesystem_to_engine(); + bool engine_to_engine(PreProcessContext& ctx); + bool engine_to_filesystem(PreProcessContext& ctx); + bool filesystem_to_engine(PreProcessContext& ctx); const Raul::URI _old_uri; const Raul::URI _new_uri; diff --git a/src/server/events/CreateBlock.cpp b/src/server/events/CreateBlock.cpp index d1060fa4..231df4e2 100644 --- a/src/server/events/CreateBlock.cpp +++ b/src/server/events/CreateBlock.cpp @@ -28,6 +28,7 @@ #include "GraphImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" +#include "PreProcessContext.hpp" namespace Ingen { namespace Server { @@ -53,7 +54,7 @@ CreateBlock::~CreateBlock() } bool -CreateBlock::pre_process() +CreateBlock::pre_process(PreProcessContext& ctx) { typedef Resource::Properties::const_iterator iterator; @@ -137,7 +138,7 @@ CreateBlock::pre_process() /* Compile graph with new block added for insertion in audio thread TODO: Since the block is not connected at this point, a full compilation could be avoided and the block simply appended. */ - if (_graph->enabled()) { + if (ctx.must_compile(_graph)) { _compiled_graph = CompiledGraph::compile(_graph); } @@ -149,9 +150,8 @@ CreateBlock::pre_process() void CreateBlock::execute(RunContext& context) { - if (_status == Status::SUCCESS) { - _graph->set_compiled_graph(_compiled_graph); - _compiled_graph = NULL; // Graph takes ownership + if (_status == Status::SUCCESS && _compiled_graph) { + _compiled_graph = _graph->swap_compiled_graph(_compiled_graph); } } diff --git a/src/server/events/CreateBlock.hpp b/src/server/events/CreateBlock.hpp index 00205c6a..b0aa6aa4 100644 --- a/src/server/events/CreateBlock.hpp +++ b/src/server/events/CreateBlock.hpp @@ -47,7 +47,7 @@ public: ~CreateBlock(); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); diff --git a/src/server/events/CreateGraph.cpp b/src/server/events/CreateGraph.cpp index a2e4e6c4..ae359e17 100644 --- a/src/server/events/CreateGraph.cpp +++ b/src/server/events/CreateGraph.cpp @@ -23,6 +23,7 @@ #include "Driver.hpp" #include "Engine.hpp" #include "GraphImpl.hpp" +#include "PreProcessContext.hpp" #include "events/CreateGraph.hpp" #include "events/CreatePort.hpp" @@ -92,7 +93,7 @@ CreateGraph::build_child_events() } bool -CreateGraph::pre_process() +CreateGraph::pre_process(PreProcessContext& ctx) { if (_engine.store()->get(_path)) { return Event::pre_process_done(Status::EXISTS, _path); @@ -163,6 +164,8 @@ CreateGraph::pre_process() _parent->add_block(*_graph); if (_parent->enabled()) { _graph->enable(); + } + if (ctx.must_compile(_parent)) { _compiled_graph = CompiledGraph::compile(_parent); } } @@ -179,7 +182,7 @@ CreateGraph::pre_process() // Build and pre-process child events to create standard ports build_child_events(); for (SPtr<Event> ev : _child_events) { - ev->pre_process(); + ev->pre_process(ctx); } return Event::pre_process_done(Status::SUCCESS); @@ -189,8 +192,8 @@ void CreateGraph::execute(RunContext& context) { if (_graph) { - if (_parent) { - _parent->set_compiled_graph(_compiled_graph); + if (_parent && _compiled_graph) { + _compiled_graph = _parent->swap_compiled_graph(_compiled_graph); } for (SPtr<Event> ev : _child_events) { @@ -213,6 +216,8 @@ CreateGraph::post_process() } } _child_events.clear(); + + delete _compiled_graph; } void diff --git a/src/server/events/CreateGraph.hpp b/src/server/events/CreateGraph.hpp index 9cae32ba..794742ac 100644 --- a/src/server/events/CreateGraph.hpp +++ b/src/server/events/CreateGraph.hpp @@ -44,7 +44,7 @@ public: const Raul::Path& path, const Resource::Properties& properties); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); diff --git a/src/server/events/CreatePort.cpp b/src/server/events/CreatePort.cpp index 9384ce09..60e57a71 100644 --- a/src/server/events/CreatePort.cpp +++ b/src/server/events/CreatePort.cpp @@ -86,7 +86,7 @@ CreatePort::CreatePort(Engine& engine, } bool -CreatePort::pre_process() +CreatePort::pre_process(PreProcessContext& ctx) { if (_port_type == PortType::UNKNOWN) { return Event::pre_process_done(Status::UNKNOWN_TYPE, _path); diff --git a/src/server/events/CreatePort.hpp b/src/server/events/CreatePort.hpp index c002df59..f3e2092d 100644 --- a/src/server/events/CreatePort.hpp +++ b/src/server/events/CreatePort.hpp @@ -51,7 +51,7 @@ public: const Raul::Path& path, const Resource::Properties& properties); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); diff --git a/src/server/events/Delete.cpp b/src/server/events/Delete.cpp index 0d202f84..bab2594a 100644 --- a/src/server/events/Delete.cpp +++ b/src/server/events/Delete.cpp @@ -29,6 +29,7 @@ #include "GraphImpl.hpp" #include "PluginImpl.hpp" #include "PortImpl.hpp" +#include "PreProcessContext.hpp" namespace Ingen { namespace Server { @@ -54,10 +55,11 @@ Delete::Delete(Engine& engine, Delete::~Delete() { delete _disconnect_event; + delete _compiled_graph; } bool -Delete::pre_process() +Delete::pre_process(PreProcessContext& ctx) { if (_path.is_root() || _path == "/control" || _path == "/notify") { return Event::pre_process_done(Status::NOT_DELETABLE, _path); @@ -91,19 +93,22 @@ Delete::pre_process() if (_block) { parent->remove_block(*_block); _disconnect_event = new DisconnectAll(_engine, parent, _block.get()); - _disconnect_event->pre_process(); + _disconnect_event->pre_process(ctx); - if (parent->enabled()) { + if (ctx.must_compile(parent)) { _compiled_graph = CompiledGraph::compile(parent); } } else if (_port) { parent->remove_port(*_port); _disconnect_event = new DisconnectAll(_engine, parent, _port.get()); - _disconnect_event->pre_process(); + _disconnect_event->pre_process(ctx); - if (parent->enabled()) { + if (ctx.must_compile(parent)) { _compiled_graph = CompiledGraph::compile(parent); - _ports_array = parent->build_ports_array(); + } + + if (parent->enabled()) { + _ports_array = parent->build_ports_array(); assert(_ports_array->size() == parent->num_ports_non_rt()); } @@ -137,8 +142,8 @@ Delete::execute(RunContext& context) } } - if (parent) { - parent->set_compiled_graph(_compiled_graph); + if (parent && _compiled_graph) { + _compiled_graph = parent->swap_compiled_graph(_compiled_graph); } } diff --git a/src/server/events/Delete.hpp b/src/server/events/Delete.hpp index 5cd40b14..fd797804 100644 --- a/src/server/events/Delete.hpp +++ b/src/server/events/Delete.hpp @@ -54,7 +54,7 @@ public: ~Delete(); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp index 8c94fac7..62d08367 100644 --- a/src/server/events/Delta.cpp +++ b/src/server/events/Delta.cpp @@ -79,6 +79,7 @@ Delta::~Delta() delete s; delete _create_event; + delete _compiled_graph; } void @@ -98,7 +99,6 @@ Delta::add_set_event(const char* port_symbol, _engine, _request_client, _request_id, _time, port, Atom(size, type, value), true); - ev->pre_process(); _set_events.push_back(ev); } @@ -155,7 +155,7 @@ get_file_node(LilvWorld* lworld, const URIs& uris, const Atom& value) */ bool -Delta::pre_process() +Delta::pre_process(PreProcessContext& ctx) { const Ingen::URIs& uris = _engine.world()->uris(); @@ -231,7 +231,7 @@ Delta::pre_process() path, _properties); } if (_create_event) { - if (_create_event->pre_process()) { + if (_create_event->pre_process(ctx)) { _object = _engine.store()->get(path); // Get object for setting } else { return Event::pre_process_done(Status::CREATION_FAILED, _subject); @@ -322,7 +322,6 @@ Delta::pre_process() } else if (key == uris.ingen_value || key == uris.ingen_activity) { SetPortValue* ev = new SetPortValue( _engine, _request_client, _request_id, _time, port, value); - ev->pre_process(); _set_events.push_back(ev); } else if (key == uris.midi_binding) { if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CV)) { @@ -449,6 +448,10 @@ Delta::pre_process() _types.push_back(op); } + for (auto& s : _set_events) { + s->pre_process(ctx); + } + if (poly_changed) { lock.unlock(); _poly_lock.lock(); @@ -496,7 +499,7 @@ Delta::execute(RunContext& context) if (_graph) { if (value.get<int32_t>()) { if (_compiled_graph) { - _graph->set_compiled_graph(_compiled_graph); + _compiled_graph = _graph->swap_compiled_graph(_compiled_graph); } _graph->enable(); } else { diff --git a/src/server/events/Delta.hpp b/src/server/events/Delta.hpp index 24330199..9e6cbecd 100644 --- a/src/server/events/Delta.hpp +++ b/src/server/events/Delta.hpp @@ -73,7 +73,7 @@ public: uint32_t size, uint32_t type); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); diff --git a/src/server/events/Disconnect.cpp b/src/server/events/Disconnect.cpp index ed9312d5..476a0cee 100644 --- a/src/server/events/Disconnect.cpp +++ b/src/server/events/Disconnect.cpp @@ -29,6 +29,7 @@ #include "InputPort.hpp" #include "OutputPort.hpp" #include "PortImpl.hpp" +#include "PreProcessContext.hpp" #include "RunContext.hpp" #include "ThreadManager.hpp" #include "events/Disconnect.hpp" @@ -55,6 +56,7 @@ Disconnect::Disconnect(Engine& engine, Disconnect::~Disconnect() { delete _impl; + delete _compiled_graph; } Disconnect::Impl::Impl(Engine& e, @@ -112,7 +114,7 @@ Disconnect::Impl::Impl(Engine& e, } bool -Disconnect::pre_process() +Disconnect::pre_process(PreProcessContext& ctx) { std::lock_guard<std::mutex> lock(_engine.store()->mutex()); @@ -166,8 +168,9 @@ Disconnect::pre_process() dynamic_cast<OutputPort*>(tail), dynamic_cast<InputPort*>(head)); - if (_graph->enabled()) + if (ctx.must_compile(_graph)) { _compiled_graph = CompiledGraph::compile(_graph); + } return Event::pre_process_done(Status::SUCCESS); } @@ -204,7 +207,9 @@ Disconnect::execute(RunContext& context) { if (_status == Status::SUCCESS) { if (_impl->execute(context, true)) { - _graph->set_compiled_graph(_compiled_graph); + if (_compiled_graph) { + _compiled_graph = _graph->swap_compiled_graph(_compiled_graph); + } } else { _status = Status::NOT_FOUND; } diff --git a/src/server/events/Disconnect.hpp b/src/server/events/Disconnect.hpp index 69d9469c..19ffcf3b 100644 --- a/src/server/events/Disconnect.hpp +++ b/src/server/events/Disconnect.hpp @@ -54,7 +54,7 @@ public: ~Disconnect(); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); diff --git a/src/server/events/DisconnectAll.cpp b/src/server/events/DisconnectAll.cpp index e4866d30..2dea6a76 100644 --- a/src/server/events/DisconnectAll.cpp +++ b/src/server/events/DisconnectAll.cpp @@ -31,6 +31,7 @@ #include "InputPort.hpp" #include "OutputPort.hpp" #include "PortImpl.hpp" +#include "PreProcessContext.hpp" #include "events/Disconnect.hpp" #include "events/DisconnectAll.hpp" #include "util.hpp" @@ -76,10 +77,12 @@ DisconnectAll::~DisconnectAll() { for (auto& i : _impls) delete i; + + delete _compiled_graph; } bool -DisconnectAll::pre_process() +DisconnectAll::pre_process(PreProcessContext& ctx) { std::unique_lock<std::mutex> lock(_engine.store()->mutex(), std::defer_lock); @@ -136,7 +139,7 @@ DisconnectAll::pre_process() dynamic_cast<InputPort*>(a->head()))); } - if (!_deleting && _parent->enabled()) { + if (!_deleting && ctx.must_compile(_parent)) { if (!(_compiled_graph = CompiledGraph::compile(_parent))) { return Event::pre_process_done(Status::COMPILATION_FAILED); } @@ -155,7 +158,9 @@ DisconnectAll::execute(RunContext& context) } } - _parent->set_compiled_graph(_compiled_graph); + if (_compiled_graph) { + _compiled_graph = _parent->swap_compiled_graph(_compiled_graph); + } } void diff --git a/src/server/events/DisconnectAll.hpp b/src/server/events/DisconnectAll.hpp index 1ddfc536..1fc1f757 100644 --- a/src/server/events/DisconnectAll.hpp +++ b/src/server/events/DisconnectAll.hpp @@ -56,7 +56,7 @@ public: ~DisconnectAll(); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); diff --git a/src/server/events/Get.cpp b/src/server/events/Get.cpp index b018c1a9..dfa16ef5 100644 --- a/src/server/events/Get.cpp +++ b/src/server/events/Get.cpp @@ -46,7 +46,7 @@ Get::Get(Engine& engine, {} bool -Get::pre_process() +Get::pre_process(PreProcessContext& ctx) { std::lock_guard<std::mutex> lock(_engine.store()->mutex()); diff --git a/src/server/events/Get.hpp b/src/server/events/Get.hpp index f685df21..35955d9a 100644 --- a/src/server/events/Get.hpp +++ b/src/server/events/Get.hpp @@ -47,7 +47,7 @@ public: SampleCount timestamp, const Raul::URI& uri); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context) {} void post_process(); diff --git a/src/server/events/Mark.cpp b/src/server/events/Mark.cpp index 11690487..c72cc14f 100644 --- a/src/server/events/Mark.cpp +++ b/src/server/events/Mark.cpp @@ -15,6 +15,7 @@ */ #include "Engine.hpp" +#include "PreProcessContext.hpp" #include "UndoStack.hpp" #include "events/Mark.hpp" @@ -32,8 +33,15 @@ Mark::Mark(Engine& engine, , _depth(0) {} +Mark::~Mark() +{ + for (const auto& g : _compiled_graphs) { + delete g.second; + } +} + bool -Mark::pre_process() +Mark::pre_process(PreProcessContext& ctx) { UndoStack* const stack = ((_mode == Mode::UNDO) ? _engine.redo_stack() @@ -41,10 +49,21 @@ Mark::pre_process() switch (_type) { case Type::BUNDLE_START: + ctx.set_in_bundle(true); _depth = stack->start_entry(); break; case Type::BUNDLE_END: _depth = stack->finish_entry(); + ctx.set_in_bundle(false); + if (!ctx.dirty_graphs().empty()) { + for (GraphImpl* g : ctx.dirty_graphs()) { + CompiledGraph* cg = CompiledGraph::compile(g); + if (cg) { + _compiled_graphs.insert(std::make_pair(g, cg)); + } + } + ctx.dirty_graphs().clear(); + } break; } @@ -53,7 +72,11 @@ Mark::pre_process() void Mark::execute(RunContext& context) -{} +{ + for (auto& g : _compiled_graphs) { + g.second = g.first->swap_compiled_graph(g.second); + } +} void Mark::post_process() diff --git a/src/server/events/Mark.hpp b/src/server/events/Mark.hpp index d2db0834..68ba5149 100644 --- a/src/server/events/Mark.hpp +++ b/src/server/events/Mark.hpp @@ -44,15 +44,20 @@ public: SampleCount timestamp, Type type); - bool pre_process(); + ~Mark(); + + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); Execution get_execution() const; private: - Type _type; - int _depth; + typedef std::map<GraphImpl*, CompiledGraph*> CompiledGraphs; + + CompiledGraphs _compiled_graphs; + Type _type; + int _depth; }; } // namespace Events diff --git a/src/server/events/Move.cpp b/src/server/events/Move.cpp index d6eae6d6..aee74ab6 100644 --- a/src/server/events/Move.cpp +++ b/src/server/events/Move.cpp @@ -46,7 +46,7 @@ Move::~Move() } bool -Move::pre_process() +Move::pre_process(PreProcessContext& ctx) { std::lock_guard<std::mutex> lock(_engine.store()->mutex()); diff --git a/src/server/events/Move.hpp b/src/server/events/Move.hpp index ef308a01..c45c73aa 100644 --- a/src/server/events/Move.hpp +++ b/src/server/events/Move.hpp @@ -45,7 +45,7 @@ public: ~Move(); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); void undo(Interface& target); diff --git a/src/server/events/SetPortValue.cpp b/src/server/events/SetPortValue.cpp index 0fac88c2..5bcb6dbf 100644 --- a/src/server/events/SetPortValue.cpp +++ b/src/server/events/SetPortValue.cpp @@ -53,7 +53,7 @@ SetPortValue::~SetPortValue() } bool -SetPortValue::pre_process() +SetPortValue::pre_process(PreProcessContext& ctx) { if (_port->is_output()) { return Event::pre_process_done(Status::DIRECTION_MISMATCH, _port->path()); diff --git a/src/server/events/SetPortValue.hpp b/src/server/events/SetPortValue.hpp index 7b49096f..aac5e033 100644 --- a/src/server/events/SetPortValue.hpp +++ b/src/server/events/SetPortValue.hpp @@ -47,7 +47,7 @@ public: ~SetPortValue(); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); diff --git a/src/server/events/Undo.cpp b/src/server/events/Undo.cpp index 0510d50f..83279744 100644 --- a/src/server/events/Undo.cpp +++ b/src/server/events/Undo.cpp @@ -34,7 +34,7 @@ Undo::Undo(Engine& engine, {} bool -Undo::pre_process() +Undo::pre_process(PreProcessContext& ctx) { UndoStack* const stack = _is_redo ? _engine.redo_stack() : _engine.undo_stack(); const Event::Mode mode = _is_redo ? Event::Mode::REDO : Event::Mode::UNDO; diff --git a/src/server/events/Undo.hpp b/src/server/events/Undo.hpp index c95daea9..300c74f2 100644 --- a/src/server/events/Undo.hpp +++ b/src/server/events/Undo.hpp @@ -38,7 +38,7 @@ public: SampleCount timestamp, bool is_redo); - bool pre_process(); + bool pre_process(PreProcessContext& ctx); void execute(RunContext& context); void post_process(); |