From 987710474b824cb92d83ff6fa7a090f50e10756f Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 16 Apr 2011 05:05:32 +0000 Subject: Hide process slave stuff from Engine.hpp. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@3151 a436a847-0d15-0410-975c-d299462d15a1 --- src/engine/Driver.hpp | 8 ++++--- src/engine/Engine.cpp | 35 ++++++++-------------------- src/engine/Engine.hpp | 44 +++++++++++++++-------------------- src/engine/EngineStore.hpp | 2 +- src/engine/JackDriver.cpp | 13 +++++++---- src/engine/PatchImpl.cpp | 19 ++++++++------- src/engine/ProcessContext.cpp | 36 +++++++++++++++++++++++++++++ src/engine/ProcessContext.hpp | 26 +++++++++++++-------- src/engine/ProcessSlave.cpp | 2 +- src/engine/ProcessSlave.hpp | 45 +++++++++++++++++++++--------------- src/engine/QueuedEngineInterface.cpp | 6 +---- src/engine/wscript | 1 + 12 files changed, 132 insertions(+), 105 deletions(-) create mode 100644 src/engine/ProcessContext.cpp (limited to 'src/engine') diff --git a/src/engine/Driver.hpp b/src/engine/Driver.hpp index c744b54f..6951d357 100644 --- a/src/engine/Driver.hpp +++ b/src/engine/Driver.hpp @@ -97,15 +97,17 @@ public: virtual void add_port(DriverPort* port) = 0; /** Remove a system visible port. */ - virtual Raul::Deletable* remove_port(const Raul::Path& path, Ingen::DriverPort** port=NULL) = 0; + virtual Raul::Deletable* remove_port(const Raul::Path& path, + Ingen::DriverPort** port=NULL) = 0; /** Return true iff this driver supports the given type of I/O */ - virtual bool supports(Shared::PortType port_type, Shared::EventType event_type) = 0; + virtual bool supports(Shared::PortType port_type, + Shared::EventType event_type) = 0; virtual void set_root_patch(PatchImpl* patch) = 0; virtual PatchImpl* root_patch() = 0; - /** Return the audio buffer size in frames (i.e. the maximum length of a process cycle) */ + /** Return the audio buffer size in frames */ virtual SampleCount block_length() const = 0; /** Return the sample rate in Hz */ diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index b57fa542..538b967f 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -43,7 +43,6 @@ #include "PatchImpl.hpp" #include "PostProcessor.hpp" #include "ProcessContext.hpp" -#include "ProcessSlave.hpp" #include "QueuedEngineInterface.hpp" #include "ThreadManager.hpp" #include "tuning.hpp" @@ -67,7 +66,6 @@ Engine::Engine(Ingen::Shared::World* a_world) , _buffer_factory(new BufferFactory(*this, a_world->uris())) , _control_bindings(new ControlBindings(*this)) , _quit_flag(false) - , _activated(false) { if (a_world->store()) { assert(PtrCast(a_world->store())); @@ -126,6 +124,13 @@ Engine::add_event_source(SharedPtr source) } +void +Engine::set_driver(SharedPtr driver) +{ + _driver = driver; +} + + static void execute_and_delete_event(ProcessContext& context, QueuedEvent* ev) { @@ -139,19 +144,13 @@ execute_and_delete_event(ProcessContext& context, QueuedEvent* ev) bool Engine::activate() { - if (_activated) - return true; - assert(_driver); - //assert(ThreadManager::single_threaded == true); ThreadManager::single_threaded = true; _buffer_factory->set_block_length(_driver->block_length()); _message_context->Thread::start(); - uint32_t parallelism = _world->conf()->option("parallelism").get_int32(); - for (EventSources::iterator i = _event_sources.begin(); i != _event_sources.end(); ++i) (*i)->activate_source(); @@ -205,15 +204,8 @@ Engine::activate() } _driver->activate(); - - _process_slaves.clear(); - _process_slaves.reserve(parallelism); - for (size_t i=0; i < parallelism - 1; ++i) - _process_slaves.push_back(new ProcessSlave(*this, _driver->is_realtime())); - root_patch->enable(); - _activated = true; ThreadManager::single_threaded = false; return true; @@ -223,16 +215,12 @@ Engine::activate() void Engine::deactivate() { - if (!_activated) - return; - for (EventSources::iterator i = _event_sources.begin(); i != _event_sources.end(); ++i) (*i)->deactivate_source(); _driver->deactivate(); _driver->root_patch()->deactivate(); - _activated = false; ThreadManager::single_threaded = true; } @@ -240,16 +228,11 @@ Engine::deactivate() void Engine::process_events(ProcessContext& context) { + ThreadManager::assert_thread(THREAD_PROCESS); + for (EventSources::iterator i = _event_sources.begin(); i != _event_sources.end(); ++i) (*i)->process(*_post_processor, context); } -bool -Engine::activated() -{ - return _activated; -} - - } // namespace Ingen diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp index c2756e11..e50704f5 100644 --- a/src/engine/Engine.hpp +++ b/src/engine/Engine.hpp @@ -44,8 +44,6 @@ class MessageContext; class NodeFactory; class PostProcessor; class ProcessContext; -class ProcessSlave; - /** The engine which executes the process graph. @@ -54,7 +52,7 @@ class ProcessSlave; that make up the engine implementation. In processes with a local engine, it can be accessed via the Ingen::Shared::World. - \ingroup engine + @ingroup engine */ class Engine : public boost::noncopyable { @@ -63,6 +61,9 @@ public: virtual ~Engine(); + virtual void set_driver(SharedPtr driver); + virtual void add_event_source(SharedPtr source); + virtual bool activate(); virtual void deactivate(); @@ -70,26 +71,29 @@ public: Indicate that a quit is desired This function simply sets a flag which affects the return value of - main iteration, it does not actually force the engine to stop running - or block. The code driving the engine is responsible for stopping - and cleaning up when main_iteration returns false. + main_iteration, it does not actually force the engine to stop running or + block. The code driving the engine is responsible for stopping and + cleaning up when main_iteration returns false. */ virtual void quit(); /** Run a single iteration of the main context. - The main context performs housekeeping duties like collecting garbage. - This should be called regularly, e.g. a few times per second. - The return value indicates whether execution should continue; i.e. if - false is returned, the caller should cease calling main_iteration() - and stop the engine. + The main context post-processes events and performs housekeeping duties + like collecting garbage. This should be called regularly, e.g. a few + times per second. The return value indicates whether execution should + continue; i.e. if false is returned, a quit has been requested and the + caller should cease calling main_iteration() and stop the engine. */ virtual bool main_iteration(); - virtual void process_events(ProcessContext& context); + /** + Process all events for this process cycle. - virtual bool activated(); + Must be called (likely by the Driver) from the process thread. + */ + virtual void process_events(ProcessContext& context); virtual BufferFactory* buffer_factory() const { return _buffer_factory; } virtual ClientBroadcaster* broadcaster() const { return _broadcaster; } @@ -99,24 +103,14 @@ public: virtual NodeFactory* node_factory() const { return _node_factory; } virtual PostProcessor* post_processor() const { return _post_processor; } virtual Raul::Maid* maid() const { return _maid; } + virtual Shared::World* world() const { return _world; } virtual SharedPtr engine_store() const; - virtual void set_driver(SharedPtr driver) { _driver = driver; } - - virtual void add_event_source(SharedPtr source); - - virtual Ingen::Shared::World* world() { return _world; } - - typedef std::vector ProcessSlaves; - virtual const ProcessSlaves& process_slaves() const { return _process_slaves; } - virtual ProcessSlaves& process_slaves() { return _process_slaves; } - private: typedef std::set< SharedPtr > EventSources; EventSources _event_sources; - ProcessSlaves _process_slaves; Ingen::Shared::World* _world; SharedPtr _driver; Raul::Maid* _maid; @@ -128,10 +122,8 @@ private: ControlBindings* _control_bindings; bool _quit_flag; - bool _activated; }; - } // namespace Ingen #endif // INGEN_ENGINE_ENGINE_HPP diff --git a/src/engine/EngineStore.hpp b/src/engine/EngineStore.hpp index c6d428fd..0e30f9cb 100644 --- a/src/engine/EngineStore.hpp +++ b/src/engine/EngineStore.hpp @@ -18,8 +18,8 @@ #ifndef INGEN_ENGINE_OBJECTSTORE_HPP #define INGEN_ENGINE_OBJECTSTORE_HPP -#include #include "raul/SharedPtr.hpp" + #include "shared/Store.hpp" namespace Ingen { diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp index c807c098..e3c89ca6 100644 --- a/src/engine/JackDriver.cpp +++ b/src/engine/JackDriver.cpp @@ -291,19 +291,24 @@ JackDriver::attach(const std::string& server_name, void JackDriver::activate() { + Shared::World* world = _engine.world(); + if (_is_activated) { LOG(warn) << "Jack driver already activated." << endl; return; } if (!_client) - attach(_engine.world()->conf()->option("jack-server").get_string(), - _engine.world()->conf()->option("jack-client").get_string(), NULL); + attach(world->conf()->option("jack-server").get_string(), + world->conf()->option("jack-client").get_string(), NULL); jack_set_process_callback(_client, process_cb, this); _is_activated = true; + _process_context.activate(world->conf()->option("parallelism").get_int32(), + is_realtime()); + if (jack_activate(_client)) { LOG(error) << "Could not activate Jack client, aborting." << endl; exit(EXIT_FAILURE); @@ -446,8 +451,8 @@ JackDriver::_process_cb(jack_nframes_t nframes) _process_context.locate(start_of_current_cycle, nframes, 0); - for (Engine::ProcessSlaves::iterator i = _engine.process_slaves().begin(); - i != _engine.process_slaves().end(); ++i) { + for (ProcessContext::Slaves::iterator i = _process_context.slaves().begin(); + i != _process_context.slaves().end(); ++i) { (*i)->context().locate(start_of_current_cycle, nframes, 0); } diff --git a/src/engine/PatchImpl.cpp b/src/engine/PatchImpl.cpp index eab1aed5..a9be238f 100644 --- a/src/engine/PatchImpl.cpp +++ b/src/engine/PatchImpl.cpp @@ -166,7 +166,7 @@ PatchImpl::process(ProcessContext& context) // Run all nodes if (_compiled_patch && _compiled_patch->size() > 0) { - if (_engine.process_slaves().size() > 0) { + if (context.slaves().size() > 0) { process_parallel(context); } else { process_single(context); @@ -186,7 +186,7 @@ PatchImpl::process(ProcessContext& context) void PatchImpl::process_parallel(ProcessContext& context) { - size_t n_slaves = _engine.process_slaves().size(); + size_t n_slaves = context.slaves().size(); CompiledPatch* const cp = _compiled_patch; @@ -196,11 +196,11 @@ PatchImpl::process_parallel(ProcessContext& context) n_slaves = cp->size()-1; if (n_slaves > 0) { - for (size_t i=0; i < cp->size(); ++i) + for (size_t i = 0; i < cp->size(); ++i) (*cp)[i].node()->reset_input_ready(); - for (size_t i=0; i < n_slaves; ++i) - _engine.process_slaves()[i]->whip(cp, i+1, context); + for (size_t i = 0; i < n_slaves; ++i) + context.slaves()[i]->whip(cp, i+1, context); } @@ -211,11 +211,10 @@ PatchImpl::process_parallel(ProcessContext& context) * waiting in the Jack thread which pisses Jack off. */ - size_t index = 0; + size_t index = 0; size_t num_finished = 0; // Number of consecutive finished nodes hit while (num_finished < cp->size()) { - CompiledNode& n = (*cp)[index]; if (n.node()->process_lock()) { @@ -223,7 +222,7 @@ PatchImpl::process_parallel(ProcessContext& context) n.node()->process(context); /* Signal dependants their input is ready */ - for (size_t i=0; i < n.dependants().size(); ++i) + for (uint32_t i = 0; i < n.dependants().size(); ++i) n.dependants()[i]->signal_input_ready(); ++num_finished; @@ -246,8 +245,8 @@ PatchImpl::process_parallel(ProcessContext& context) * FIXME: This probably breaks (race) at extremely small nframes where * ingen is the majority of the DSP load. */ - for (size_t i=0; i < n_slaves; ++i) - _engine.process_slaves()[i]->finish(); + for (uint32_t i = 0; i < n_slaves; ++i) + context.slaves()[i]->finish(); } diff --git a/src/engine/ProcessContext.cpp b/src/engine/ProcessContext.cpp new file mode 100644 index 00000000..ad405f3b --- /dev/null +++ b/src/engine/ProcessContext.cpp @@ -0,0 +1,36 @@ +/* This file is part of Ingen. + * Copyright 2007-2011 David Robillard + * + * Ingen is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "ProcessContext.hpp" +#include "ProcessSlave.hpp" + +namespace Ingen { + +void +ProcessContext::activate(uint32_t parallelism, bool sched_rt) +{ + for (uint32_t i = 0; i < _slaves.size(); ++i) { + delete _slaves[i]; + } + _slaves.clear(); + _slaves.reserve(parallelism); + for (uint32_t i = 0; i < parallelism - 1; ++i) { + _slaves.push_back(new ProcessSlave(_engine, sched_rt)); + } +} + +} diff --git a/src/engine/ProcessContext.hpp b/src/engine/ProcessContext.hpp index e7e8a001..9e43cc3d 100644 --- a/src/engine/ProcessContext.hpp +++ b/src/engine/ProcessContext.hpp @@ -1,5 +1,5 @@ /* This file is part of Ingen. - * Copyright (C) 2007-2009 David Robillard + * Copyright 2007-2011 David Robillard * * Ingen is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software @@ -18,26 +18,33 @@ #ifndef INGEN_ENGINE_PROCESSCONTEXT_HPP #define INGEN_ENGINE_PROCESSCONTEXT_HPP -#include "types.hpp" -#include "EventSink.hpp" +#include + #include "Context.hpp" +#include "EventSink.hpp" +#include "types.hpp" namespace Ingen { +class ProcessSlave; /** Context of a process() call (the audio context). - * - * This class currently adds no functionality to Context, but the - * separate type is useful for writing functions that must only - * be run in the audio context (the function taking a ProcessContext - * parameter makes this clear, and makes breaking the rules obvious). - * * \ingroup engine */ class ProcessContext : public Context { public: explicit ProcessContext(Engine& engine) : Context(engine, AUDIO) {} + + typedef std::vector Slaves; + + const Slaves& slaves() const { return _slaves; } + Slaves& slaves() { return _slaves; } + + void activate(uint32_t parallelism, bool sched_rt); + +private: + Slaves _slaves; }; @@ -45,4 +52,3 @@ public: } // namespace Ingen #endif // INGEN_ENGINE_PROCESSCONTEXT_HPP - diff --git a/src/engine/ProcessSlave.cpp b/src/engine/ProcessSlave.cpp index 234f8cf1..a02d1140 100644 --- a/src/engine/ProcessSlave.cpp +++ b/src/engine/ProcessSlave.cpp @@ -48,7 +48,7 @@ ProcessSlave::_whipped() n.node()->wait_for_input(n.n_providers()); - n.node()->process(_process_context); + n.node()->process(*_context); /* Signal dependants their input is ready */ for (size_t i=0; i < n.dependants().size(); ++i) diff --git a/src/engine/ProcessSlave.hpp b/src/engine/ProcessSlave.hpp index bee231d3..1d3c169d 100644 --- a/src/engine/ProcessSlave.hpp +++ b/src/engine/ProcessSlave.hpp @@ -19,9 +19,13 @@ #define INGEN_ENGINE_PROCESSSLAVE_HPP #include -#include "raul/Slave.hpp" + #include "raul/Array.hpp" #include "raul/AtomicInt.hpp" +#include "raul/Slave.hpp" + +#include "Driver.hpp" +#include "Engine.hpp" #include "ProcessContext.hpp" namespace Ingen { @@ -33,11 +37,12 @@ class CompiledPatch; class ProcessSlave : protected Raul::Slave { public: ProcessSlave(Engine& engine, bool realtime) - : _id(_next_id++) + : _engine(engine) + , _id(_next_id++) , _index(0) , _state(STATE_FINISHED) , _compiled_patch(NULL) - , _process_context(engine) + , _context(NULL) { std::stringstream ss; ss << "Process Slave "; @@ -54,12 +59,15 @@ public: stop(); } - inline void whip(CompiledPatch* compiled_patch, uint32_t start_index, ProcessContext& context) { + inline void whip(CompiledPatch* compiled_patch, + uint32_t start_index, + ProcessContext& context) + { assert(_state == STATE_FINISHED); - _index = start_index; - _state = STATE_RUNNING; + _index = start_index; + _state = STATE_RUNNING; _compiled_patch = compiled_patch; - _process_context.locate(context); + _context = &context; Raul::Slave::whip(); } @@ -70,28 +78,27 @@ public: } inline uint32_t id() const { return _id; } - inline const ProcessContext& context() const { return _process_context; } - inline ProcessContext& context() { return _process_context; } + inline const ProcessContext& context() const { return _engine.driver()->context(); } + inline ProcessContext& context() { return _engine.driver()->context(); } private: - void _whipped(); static uint32_t _next_id; - static const int STATE_RUNNING = 0; + static const int STATE_RUNNING = 0; static const int STATE_FINISH_SIGNALLED = 1; - static const int STATE_FINISHED = 2; - - uint32_t _id; - uint32_t _index; - Raul::AtomicInt _state; - CompiledPatch* _compiled_patch; - ProcessContext _process_context; + static const int STATE_FINISHED = 2; + + Engine& _engine; + uint32_t _id; + uint32_t _index; + Raul::AtomicInt _state; + CompiledPatch* _compiled_patch; + ProcessContext* _context; }; } // namespace Ingen #endif // INGEN_ENGINE_PROCESSSLAVE_HPP - diff --git a/src/engine/QueuedEngineInterface.cpp b/src/engine/QueuedEngineInterface.cpp index c1051c0a..eea27126 100644 --- a/src/engine/QueuedEngineInterface.cpp +++ b/src/engine/QueuedEngineInterface.cpp @@ -231,11 +231,7 @@ QueuedEngineInterface::set_property(const URI& uri, void QueuedEngineInterface::ping() { - if (_engine.activated()) { - push_queued(new Events::Ping(_engine, _request, now())); - } else if (_request) { - _request->respond_ok(); - } + push_queued(new Events::Ping(_engine, _request, now())); } diff --git a/src/engine/wscript b/src/engine/wscript index 61be8c01..1a801b92 100644 --- a/src/engine/wscript +++ b/src/engine/wscript @@ -31,6 +31,7 @@ def build(bld): PluginImpl.cpp PortImpl.cpp PostProcessor.cpp + ProcessContext.cpp ProcessSlave.cpp QueuedEngineInterface.cpp QueuedEvent.cpp -- cgit v1.2.1