From bb12144cbfb8c06f502ce0f963edefbb6009aea9 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 6 Oct 2011 17:51:43 +0000 Subject: Use an intrusive linked list for InputPort connections. This simplifies the code and avoids the overhead of allocating list nodes. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@3532 a436a847-0d15-0410-975c-d299462d15a1 --- src/server/BufferFactory.cpp | 6 ++++++ src/server/BufferFactory.hpp | 10 +++++++--- src/server/ConnectionImpl.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/server/ConnectionImpl.hpp | 35 +++++++++++++++++------------------ src/server/InputPort.cpp | 40 ++++++++++++++++++---------------------- src/server/InputPort.hpp | 17 +++++++++++------ src/server/events/Connect.cpp | 20 +++++--------------- src/server/events/Connect.hpp | 3 +-- src/server/events/Disconnect.cpp | 7 +++---- 9 files changed, 105 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/server/BufferFactory.cpp b/src/server/BufferFactory.cpp index f6f73fdc..54886e35 100644 --- a/src/server/BufferFactory.cpp +++ b/src/server/BufferFactory.cpp @@ -118,6 +118,12 @@ BufferFactory::get(PortType type, size_t size, bool force_create) return Ref(try_head); } +BufferFactory::Ref +BufferFactory::silent_buffer() +{ + return _silent_buffer; +} + BufferFactory::Ref BufferFactory::create(PortType type, size_t size) { diff --git a/src/server/BufferFactory.hpp b/src/server/BufferFactory.hpp index 5690113c..3fe46c35 100644 --- a/src/server/BufferFactory.hpp +++ b/src/server/BufferFactory.hpp @@ -19,10 +19,14 @@ #define INGEN_ENGINE_BUFFERFACTORY_HPP #include + #include -#include "glibmm/thread.h" -#include "raul/RingBuffer.hpp" +#include + #include "raul/AtomicPtr.hpp" +#include "raul/RingBuffer.hpp" +#include "raul/SharedPtr.hpp" + #include "PortType.hpp" #include "types.hpp" @@ -49,7 +53,7 @@ public: Ref get(PortType type, size_t size=0, bool force_create=false); - Ref silent_buffer() { return _silent_buffer; } + Ref silent_buffer(); void set_block_length(SampleCount block_length); diff --git a/src/server/ConnectionImpl.cpp b/src/server/ConnectionImpl.cpp index 49c45f43..9bb0d4f5 100644 --- a/src/server/ConnectionImpl.cpp +++ b/src/server/ConnectionImpl.cpp @@ -66,6 +66,18 @@ ConnectionImpl::dump() const << "POLY: " << _src_port->poly() << " => " << _dst_port->poly() << endl; } +const Raul::Path& +ConnectionImpl::src_port_path() const +{ + return _src_port->path(); +} + +const Raul::Path& +ConnectionImpl::dst_port_path() const +{ + return _dst_port->path(); +} + void ConnectionImpl::get_sources(Context& context, uint32_t voice, boost::intrusive_ptr* srcs, uint32_t max_num_srcs, uint32_t& num_srcs) @@ -119,6 +131,31 @@ ConnectionImpl::queue(Context& context) } } +BufferFactory::Ref +ConnectionImpl::buffer(uint32_t voice) const +{ + assert(!must_mix()); + assert(!must_queue()); + assert(_src_port->poly() == 1 || _src_port->poly() > voice); + if (_src_port->poly() == 1) { + return _src_port->buffer(0); + } else { + return _src_port->buffer(voice); + } +} + +bool +ConnectionImpl::must_mix() const +{ + return _src_port->poly() > _dst_port->poly(); +} + +bool +ConnectionImpl::must_queue() const +{ + return _src_port->context() != _dst_port->context(); +} + bool ConnectionImpl::can_connect(const OutputPort* src, const InputPort* dst) { diff --git a/src/server/ConnectionImpl.hpp b/src/server/ConnectionImpl.hpp index 33ec0608..35441d7d 100644 --- a/src/server/ConnectionImpl.hpp +++ b/src/server/ConnectionImpl.hpp @@ -20,6 +20,7 @@ #include +#include #include #include @@ -28,7 +29,8 @@ #include "raul/Deletable.hpp" #include "raul/log.hpp" -#include "PortImpl.hpp" +#include "BufferFactory.hpp" +#include "Context.hpp" using namespace std; @@ -51,7 +53,10 @@ class BufferFactory; * * \ingroup engine */ -class ConnectionImpl : public Raul::Deletable, public Connection +class ConnectionImpl : public Raul::Deletable + , private Raul::Noncopyable + , public Connection + , public boost::intrusive::list_base_hook<> { public: ConnectionImpl(BufferFactory& bufs, PortImpl* src_port, PortImpl* dst_port); @@ -59,8 +64,8 @@ public: PortImpl* src_port() const { return _src_port; } PortImpl* dst_port() const { return _dst_port; } - const Raul::Path& src_port_path() const { return _src_port->path(); } - const Raul::Path& dst_port_path() const { return _dst_port->path(); } + const Raul::Path& src_port_path() const; + const Raul::Path& dst_port_path() const; /** Used by some (recursive) events to prevent double disconnections */ bool pending_disconnection() { return _pending_disconnection; } @@ -68,30 +73,24 @@ public: void queue(Context& context); - void get_sources(Context& context, uint32_t voice, - boost::intrusive_ptr* srcs, uint32_t max_num_srcs, uint32_t& num_srcs); + void get_sources(Context& context, + uint32_t voice, + boost::intrusive_ptr* srcs, + uint32_t max_num_srcs, + uint32_t& num_srcs); /** Get the buffer for a particular voice. * A Connection is smart - it knows the destination port requesting the * buffer, and will return accordingly (e.g. the same buffer for every * voice in a mono->poly connection). */ - inline BufferFactory::Ref buffer(uint32_t voice) const { - assert(!must_mix()); - assert(!must_queue()); - assert(_src_port->poly() == 1 || _src_port->poly() > voice); - if (_src_port->poly() == 1) { - return _src_port->buffer(0); - } else { - return _src_port->buffer(voice); - } - } + BufferFactory::Ref buffer(uint32_t voice) const; /** Returns true if this connection must mix down voices into a local buffer */ - inline bool must_mix() const { return _src_port->poly() > _dst_port->poly(); } + bool must_mix() const; /** Returns true if this connection crosses contexts and must buffer */ - inline bool must_queue() const { return _src_port->context() != _dst_port->context(); } + bool must_queue() const; static bool can_connect(const OutputPort* src, const InputPort* dst); diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index 98922b07..3525bb59 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -91,10 +91,10 @@ InputPort::get_buffers(BufferFactory& bufs, } else if (num_connections == 1) { if (ThreadManager::thread_is(THREAD_PROCESS)) { - if (!_connections.front()->must_mix() && !_connections.front()->must_queue()) { + if (!_connections.front().must_mix() && !_connections.front().must_queue()) { // Single non-mixing conneciton, use buffers directly for (uint32_t v = 0; v < poly; ++v) - buffers->at(v) = _connections.front()->buffer(v); + buffers->at(v) = _connections.front().buffer(v); return false; } } @@ -117,11 +117,11 @@ InputPort::get_buffers(BufferFactory& bufs, * will audibly take effect. */ void -InputPort::add_connection(Connections::Node* const c) +InputPort::add_connection(ConnectionImpl* c) { ThreadManager::assert_thread(THREAD_PROCESS); - _connections.push_back(c); + _connections.push_front(*c); // Broadcast value/activity of connected input _broadcast = true; @@ -132,31 +132,27 @@ InputPort::add_connection(Connections::Node* const c) * Note that setup_buffers must be called after this before the change * will audibly take effect. */ -InputPort::Connections::Node* +ConnectionImpl* InputPort::remove_connection(ProcessContext& context, const OutputPort* src_port) { ThreadManager::assert_thread(THREAD_PROCESS); - Connections::Node* connection = NULL; - for (Connections::iterator i = _connections.begin(); i != _connections.end();) { - Connections::iterator next = i; - ++next; - - if ((*i)->src_port() == src_port) { - connection = _connections.erase(i); + ConnectionImpl* connection = NULL; + for (Connections::iterator i = _connections.begin(); i != _connections.end(); ++i) { + if (i->src_port() == src_port) { + connection = &*i; + _connections.erase(i); break; } - - i = next; } - if ( ! connection) { + if (!connection) { error << "[InputPort::remove_connection] Connection not found!" << endl; return NULL; } // Turn off broadcasting if we're no longer connected - if (_connections.size() == 0) { + if (_connections.empty()) { if (is_a(PortType::AUDIO)) { // Send an update peak of 0.0 to reset to silence const Notification note = Notification::make( @@ -184,23 +180,23 @@ InputPort::pre_process(Context& context) } } else if (direct_connect()) { for (uint32_t v = 0; v < _poly; ++v) { - _buffers->at(v) = _connections.front()->buffer(v); + _buffers->at(v) = _connections.front().buffer(v); _buffers->at(v)->prepare_read(context); } } else { uint32_t max_num_srcs = 0; for (Connections::const_iterator c = _connections.begin(); c != _connections.end(); ++c) { - max_num_srcs += (*c)->src_port()->poly(); + max_num_srcs += c->src_port()->poly(); } boost::intrusive_ptr srcs[max_num_srcs]; for (uint32_t v = 0; v < _poly; ++v) { uint32_t num_srcs = 0; - for (Connections::const_iterator c = _connections.begin(); + for (Connections::iterator c = _connections.begin(); c != _connections.end(); ++c) { - (*c)->get_sources(context, v, srcs, max_num_srcs, num_srcs); + c->get_sources(context, v, srcs, max_num_srcs, num_srcs); } mix(context, buffer(v).get(), srcs, num_srcs); @@ -231,8 +227,8 @@ InputPort::direct_connect() const { return (context() == Context::AUDIO) && _connections.size() == 1 - && !_connections.front()->must_mix() - && !_connections.front()->must_queue(); + && !_connections.front().must_mix() + && !_connections.front().must_queue(); } } // namespace Server diff --git a/src/server/InputPort.hpp b/src/server/InputPort.hpp index ec3a14ef..ccd651c7 100644 --- a/src/server/InputPort.hpp +++ b/src/server/InputPort.hpp @@ -18,12 +18,16 @@ #ifndef INGEN_ENGINE_INPUTPORT_HPP #define INGEN_ENGINE_INPUTPORT_HPP -#include -#include #include -#include "raul/List.hpp" +#include +#include + +#include + #include "raul/SharedPtr.hpp" + #include "PortImpl.hpp" +#include "ConnectionImpl.hpp" namespace Ingen { namespace Server { @@ -59,10 +63,11 @@ public: virtual ~InputPort() {} - typedef Raul::List< SharedPtr > Connections; + typedef boost::intrusive::list Connections; - void add_connection(Connections::Node* c); - Connections::Node* remove_connection(ProcessContext& context, const OutputPort* src_port); + void add_connection(ConnectionImpl* c); + ConnectionImpl* remove_connection(ProcessContext& context, + const OutputPort* src_port); bool apply_poly(Raul::Maid& maid, uint32_t poly); diff --git a/src/server/events/Connect.cpp b/src/server/events/Connect.cpp index 39438d43..edd004c3 100644 --- a/src/server/events/Connect.cpp +++ b/src/server/events/Connect.cpp @@ -56,7 +56,6 @@ Connect::Connect(Engine& engine, , _src_output_port(NULL) , _dst_input_port(NULL) , _compiled_patch(NULL) - , _port_listnode(NULL) , _buffers(NULL) {} @@ -129,8 +128,6 @@ Connect::pre_process() _connection = SharedPtr( new ConnectionImpl(*_engine.buffer_factory(), _src_output_port, _dst_input_port)); - _port_listnode = new InputPort::Connections::Node(_connection); - rlock.release(); { @@ -149,13 +146,9 @@ Connect::pre_process() _dst_input_port->increment_num_connections(); } - /*if ((_dst_input_port->num_connections() == 1 - && (_connection->must_mix() || _connection->must_queue())) - || _dst_input_port->num_connections() == 2) {*/ - _buffers = new Raul::Array(_dst_input_port->poly()); - _dst_input_port->get_buffers(*_engine.buffer_factory(), - _buffers, _dst_input_port->poly()); - //} + _buffers = new Raul::Array(_dst_input_port->poly()); + _dst_input_port->get_buffers(*_engine.buffer_factory(), + _buffers, _dst_input_port->poly()); if (_patch->enabled()) _compiled_patch = _patch->compile(); @@ -170,12 +163,9 @@ Connect::execute(ProcessContext& context) if (_error == NO_ERROR) { // This must be inserted here, since they're actually used by the audio thread - _dst_input_port->add_connection(_port_listnode); + _dst_input_port->add_connection(_connection.get()); assert(_buffers); - //if (_buffers) - _engine.maid()->push(_dst_input_port->set_buffers(_buffers)); - //else - // _dst_input_port->setup_buffers(*_engine.buffer_factory(), _dst_input_port->poly()); + _engine.maid()->push(_dst_input_port->set_buffers(_buffers)); _dst_input_port->connect_buffers(); _engine.maid()->push(_patch->compiled_patch()); _patch->compiled_patch(_compiled_patch); diff --git a/src/server/events/Connect.hpp b/src/server/events/Connect.hpp index d250b791..edb1344c 100644 --- a/src/server/events/Connect.hpp +++ b/src/server/events/Connect.hpp @@ -79,8 +79,7 @@ private: CompiledPatch* _compiled_patch; ///< New process order for Patch - SharedPtr _connection; - InputPort::Connections::Node* _port_listnode; + SharedPtr _connection; Raul::Array* _buffers; }; diff --git a/src/server/events/Disconnect.cpp b/src/server/events/Disconnect.cpp index c55ae1ae..c089fb11 100644 --- a/src/server/events/Disconnect.cpp +++ b/src/server/events/Disconnect.cpp @@ -185,9 +185,9 @@ Disconnect::Impl::execute(ProcessContext& context, bool set_dst_buffers) { ThreadManager::assert_thread(THREAD_PROCESS); - InputPort::Connections::Node* const port_connections_node + ConnectionImpl* const port_connection = _dst_input_port->remove_connection(context, _src_output_port); - if (!port_connections_node) { + if (!port_connection) { return false; } @@ -204,9 +204,8 @@ Disconnect::Impl::execute(ProcessContext& context, bool set_dst_buffers) } assert(_connection); - assert(port_connections_node->elem() == _connection); + assert(port_connection == _connection.get()); - _engine.maid()->push(port_connections_node); return true; } -- cgit v1.2.1