remold OutputSlot implementation structure

Better solution where to place the extension points
to be implemented by concrete output systems
This commit is contained in:
Fischlurch 2011-11-06 02:37:22 +01:00
parent 63dbc89b6f
commit 7ab7c8073d
4 changed files with 210 additions and 70 deletions

View file

@ -0,0 +1,162 @@
/*
OUTPUT-SLOT-CONNECTION.hpp - implementation API for concrete output slots
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program 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.
This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file output-slot-connection.hpp
** Interface for concrete output implementations to talk to the OutputSlot frontend.
** The OutputSlot concept helps to decouple the render engine implementation from the details
** of handling external output connections. For this to work, a concrete implementation of such
** an external output needs to integrate with the generic OutputSlot frontend, as used by the
** engine. This generic frontend uses a PImpl, pointing to a ConnectionState object, which embodies
** the actual implementation. Moreover, this actual implementation is free to use specifically crafted
** OutputSlot::Connection elements to handle the ongoing output for individual channels. The latter
** thus becomes the central implementation side API for providing actual output capabilities.
**
** @see OutputSlotProtocol_test
** @see diagnostic-output-slot.hpp ////TODO
*/
#ifndef PROC_PLAY_OUTPUT_SLOT_CONNECTION_H
#define PROC_PLAY_OUTPUT_SLOT_CONNECTION_H
#include "lib/error.hpp"
#include "proc/play/output-slot.hpp"
#include "lib/handle.hpp"
//#include "lib/time/timevalue.hpp"
//#include "proc/engine/buffer-provider.hpp"
//#include "proc/play/timings.hpp"
#include "lib/iter-source.hpp"
#include "lib/iter-adapter-stl.hpp"
//#include "lib/sync.hpp"
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
//#include <string>
//#include <vector>
//#include <tr1/memory>
namespace proc {
namespace play {
//using ::engine::BuffHandle;
//using ::engine::BufferProvider;
//using lib::time::Time;
//using std::string;
using lib::transform;
using lib::iter_stl::eachElm;
//using std::vector;
//using std::tr1::shared_ptr;
using boost::scoped_ptr;
/** established output channel */
class OutputSlot::Connection
{
public:
virtual ~Connection();
virtual void lock (FrameID) =0;
virtual void transfer (FrameID) =0;
virtual void pushout (FrameID) =0;
};
class OutputSlot::ConnectionState
: public OutputSlot::Allocation
, boost::noncopyable
{
public:
virtual ~ConnectionState() { }
};
template<class CON>
class ConnectionStateManager
: public OutputSlot::ConnectionState
, public vector<CON>
{
typedef OutputSlot::OpenedSinks OpenedSinks;
/* == Allocation Interface == */
OpenedSinks
getOpenedSinks()
{
REQUIRE (this->isActive());
return transform (eachElm(*this), connectOutputSink);
}
bool
isActive()
{
return 0 < vector<CON>::size();
}
public:
ConnectionStateManager()
{
UNIMPLEMENTED ("immediately build up the necessary number of connections");
}
virtual
~ConnectionStateManager()
{
UNIMPLEMENTED ("shut down all connections");
}
virtual
CON
buildConnection() =0;
private: // Implementation details
DataSink
connectOutputSink (CON& connection)
{
DataSink newSink;
newSink.activate(&connection, shutdownConnection);
return newSink;
}
void
shutdownConnection (CON* toClose)
{
UNIMPLEMENTED ("how to mark a connection as closed");
}
};
}} // namespace proc::play
#endif

View file

@ -23,6 +23,7 @@
#include "lib/error.hpp"
#include "proc/play/output-slot.hpp"
#include "proc/play/output-slot-connection.hpp"
#include <boost/noncopyable.hpp>
#include <vector>
@ -42,48 +43,8 @@ namespace play {
} // (End) hidden service impl details
class Connection
{
public:
};
class ConnectionState
: public OutputSlot::Allocation
, public vector<Connection>
, boost::noncopyable
{
typedef OutputSlot::OpenedSinks OpenedSinks;
private: /* == Allocation Interface == */
OpenedSinks
getOpenedSinks()
{
UNIMPLEMENTED ("yield all opened channels");
}
bool
isActive()
{
return 0 < size();
}
public:
ConnectionState()
{
UNIMPLEMENTED ("immediately build up the necessary number of connections");
}
virtual
~ConnectionState()
{
UNIMPLEMENTED ("shut down all connections");
}
};
OutputSlot::~OutputSlot() { } // emit VTables here....
@ -114,10 +75,19 @@ namespace play {
UNIMPLEMENTED ("internal interface to determine the number of channel-connections");
this->state_.reset(new ConnectionState());
state_.reset (this->buildState());
return *state_;
}
void
OutputSlot::disconnect()
{
if (!isFree())
state_.reset(0);
}
}} // namespace proc::play

View file

@ -38,7 +38,7 @@
#include "lib/error.hpp"
#include "lib/handle.hpp"
#include "lib/time/timevalue.hpp"
//#include "lib/time/timevalue.hpp"
#include "proc/engine/buffer-provider.hpp"
#include "proc/play/timings.hpp"
#include "lib/iter-source.hpp"
@ -56,7 +56,7 @@ namespace play {
using ::engine::BuffHandle;
using ::engine::BufferProvider;
using lib::time::Time;
//using lib::time::Time;
//using std::string;
//using std::vector;
@ -64,25 +64,10 @@ namespace play {
using boost::scoped_ptr;
/** established output channel */
class Connection;
/** Table to maintain connection state */
class ConnectionState;
typedef int64_t FrameNr;
class DataSink
: public lib::Handle<Connection>
{
public:
BuffHandle lockBufferFor(FrameNr);
void emit(FrameNr);
};
class DataSink;
typedef int64_t FrameID;
@ -94,8 +79,16 @@ namespace play {
class OutputSlot
: boost::noncopyable
{
protected:
/** Table to maintain connection state */
class ConnectionState;
scoped_ptr<ConnectionState> state_;
virtual ConnectionState* buildState() =0;
public:
virtual ~OutputSlot();
@ -113,17 +106,19 @@ namespace play {
~Allocation();
};
/** established output channel */
class Connection;
/** can this OutputSlot be allocated? */
bool isFree() const;
/** claim this slot for exclusive use */
Allocation& allocate();
protected:
friend class DataSink;
virtual void lock (FrameNr, uint channel) =0;
virtual void transfer (FrameNr, uint channel) =0;
virtual void pushout (FrameNr, uint channel) =0;
/** disconnect from this OutputSlot
* @warning may block until DataSinks are gone */
void disconnect();
private:
@ -131,5 +126,18 @@ namespace play {
class DataSink
: public lib::Handle<OutputSlot::Connection>
{
public:
BuffHandle lockBufferFor(FrameID);
void emit(FrameID);
};
}} // namespace proc::play
#endif

View file

@ -105,28 +105,28 @@ namespace play {
bool
buffer_was_used (uint channel, FrameNr frame)
buffer_was_used (uint channel, FrameID frame)
{
UNIMPLEMENTED ("determine if the denoted buffer was indeed used");
}
bool
buffer_unused (uint channel, FrameNr frame)
buffer_unused (uint channel, FrameID frame)
{
UNIMPLEMENTED ("determine if the specified buffer was never touched/locked for use");
}
bool
buffer_was_closed (uint channel, FrameNr frame)
buffer_was_closed (uint channel, FrameID frame)
{
UNIMPLEMENTED ("determine if the specified buffer was indeed closed properly");
}
bool
emitted (uint channel, FrameNr frame)
emitted (uint channel, FrameID frame)
{
UNIMPLEMENTED ("determine if the specivied buffer was indeed handed over for emitting output");
}