resolve the remaining liblumieracommon.so dependency problems

now this library doesn't refer to any symbols from
Proc-Layer anymore. Resolving these problems
highlighted IMHO a serious shortcomming of our
interface system, which hinders the building
of abstractions at interface level
This commit is contained in:
Fischlurch 2013-01-04 07:45:18 +01:00
parent ef9a6e6f11
commit 4ede0453be
6 changed files with 85 additions and 28 deletions

View file

@ -25,7 +25,6 @@
#include "lib/error.hpp"
#include "common/query.hpp"
#include "common/config-rules.hpp"
#include "proc/mobject/session/query/fake-configrules.hpp"
using lumiera::QueryKey;

View file

@ -74,10 +74,12 @@ namespace lumiera {
/** get an implementation instance of this service */
static lumiera::facade::Accessor<DummyPlayer> facade;
class ProcessImplementationLink;
/**
* Continuous playback process, which has been started with a specific
* output size, format and framerate. It is a handle to a calculation process,
* Playback process, front-end to be used by client code.
* This handle represents a continuous playback process, which has been started
* with a specific output size, format and framerate. It is a handle to a calculation process,
* which is about to produce a stream of frames and push them to the viewer widget,
* specified by a LumieraDisplaySlot when starting this process.
*
@ -89,14 +91,33 @@ namespace lumiera {
* @see dummy-player-service.cpp implementation
*/
class Process
: public lib::Handle<proc::play::ProcessImpl>
: public lib::Handle<ProcessImplementationLink>
{
public:
void play(bool); ///< play/pause toggle
};
/**
* Mediator to allow the client to communicate with
* the Process implementation via the Process handle,
* without having to map each implementation-level function
* into the dummy player interface. We can't access the
* implementation in Proc-Layer without this indirection
* through a VTable, since a direct call would require
* us to link against liblumieraproc.so
*/
class ProcessImplementationLink
: public lumiera_playprocess
{
public:
virtual ~ProcessImplementationLink(); ///< this is an interface
virtual Process createHandle() =0; ///< activate the Process-frontend and link it to the process implementation
virtual void doPlay(bool yes) =0; ///< forward the play/pause toggle to the play process implementation
};
//////////////////TODO: define some dummy negotiation about size and framerate....
/** create a new playback process outputting to the given viewer/display */
virtual Process start(LumieraDisplaySlot viewerHandle) =0;

View file

@ -27,7 +27,8 @@
** a callback can be registered to be executed on a specific application lifecycle
** event. Examples being #ON_BASIC_INIT, #ON_GLOBAL_INIT. Other subsystems may
** register additional events for more specific purpose.
**
**
** @note the implementation resides in lib/lifecycle.cpp and gets linked into liblumiera.so
** @see lumiera::AppState
** @see main.cpp
*/
@ -48,6 +49,7 @@ namespace lumiera {
using lib::Symbol;
//defined in liblumiera.so
extern const char * ON_BASIC_INIT; ///< automatic static init. treated specially
extern const char * ON_GLOBAL_INIT; ///< to be triggered in main() @note no magic!
extern const char * ON_GLOBAL_SHUTDOWN; ///< to be triggered at the end of main() @note no magic!
@ -95,6 +97,7 @@ namespace lumiera {
#else /* =========== C interface ====================== */
//defined in liblumiera.so
extern const char * lumiera_ON_BASIC_INIT;
extern const char * lumiera_ON_GLOBAL_INIT;
extern const char * lumiera_ON_GLOBAL_SHUTDOWN;

View file

@ -27,7 +27,20 @@
**
** The purpose is to define a proxy implementation of lumiera::DummyPlayer, in order to
** redirect any calls through the associated C Language Interface "lumieraorg_DummyPlayer"
**
**
** @remarks the implementation of this interface proxy for the DummyPlayer highlighted
** some interesting design issues. The way we're defining our interfaces and
** bindings seems to have some shortcomings when attempting to express an
** interface (here DummyPlayer) in terms of another abstraction
** (here the DummyPlayer::Process), since the implementation of this
** abstraction has to be mapped and indirected via the interface-system
** as well. This forces us to duplicate all of these secondary interface
** functions several times, and incurs a further forwarding through the
** smart-Handle, since our interface system doesn't support suitable
** lifecycle support out of the box and instead places this burden
** onto the client code (or, as in this case here, the intermediary
** proxy used by the client code to access the interface).
**
** @see dummy-player-facade.hpp
** @see dummy-player-service.hpp actual implementation within the Proc-Layer
*/
@ -39,7 +52,8 @@
/* ==================== DummyPlayer ======================================= */
#include "proc/play/dummy-player-service.hpp"
//#include "proc/play/dummy-player-service.hpp"
#include "include/dummy-player-facade.h"
namespace lumiera {
@ -56,7 +70,7 @@ namespace lumiera {
namespace facade {
typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_DummyPlayer, 0)
, proc::play::DummyPlayer
, lumiera::DummyPlayer
> IHandle_DummyPlayer;
@ -65,7 +79,7 @@ namespace lumiera {
: public Holder<IHandle_DummyPlayer>
{
//----Proxy-Implementation-of-DummyPlayer--------
typedef proc::play::DummyPlayer::Process Process;
typedef lumiera::DummyPlayer::Process Process;
typedef proc::play::ProcessImpl ProcessImpl;
/** @note as an optimisation we hand out a direct reference
@ -74,17 +88,19 @@ namespace lumiera {
* it directly within the client (=GUI) bypasses the C interface
* and thus leaves us only with one level of indirection,
* irrespective if using the C or C++ interface.
* @note in hindsight this turned out as a very bad idea
* @note in hindsight this turned out as a very bad idea,
* since it complicated the definition of the facade proxy
* and created quite involved library dependency problems.
*/
Process start(LumieraDisplaySlot viewerHandle)
{
ProcessImpl* pP = static_cast<ProcessImpl*> (_i_.startPlay (viewerHandle));
ProcessImplementationLink* pP = static_cast<ProcessImplementationLink*> (_i_.startPlay (viewerHandle));
if (!pP)
throw lumiera::error::State("failed to start DummyPlayer", lumiera_error());
return pP->createHandle();
} //////////////////TODO here we get library linking problems: createHandle is implemented in liblumieraproc.so and this is necessarily so.
}
@ -99,4 +115,19 @@ namespace lumiera {
} // namespace facade
/* === Forwarding function(s) on the Process handle === */
void
DummyPlayer::Process::play (bool yes)
{
// access the implementation via smart-Handle
impl().doPlay(yes);
}
// emit the VTable and typeinfo for this interface here (in liblumieracommon.so)
DummyPlayer::ProcessImplementationLink::~ProcessImplementationLink() { };
} // namespace lumiera

View file

@ -291,21 +291,29 @@ namespace proc {
}
/** deleter function for lib::Handle */
void
ProcessImpl::terminate (ProcessImpl* process) ///< deleter function for lib::Handle
ProcessImpl::terminate (DummyPlayer::ProcessImplementationLink* process)
{
if (process)
delete process;
}
/**
* activate a forwarding smart-Handle
* to be used by client code for communication with the play process implementation.
* The handle manages the lifecycle of the interface / play process connection.
* This virtual function is used by the interface proxy to connect the client side
* and the actual play process, after creating the latter through the interface system.
*/
DummyPlayer::Process
ProcessImpl::createHandle()
{
DummyPlayer::Process handle;
handle.activate(this, &terminate); // note the deleter function...
return handle;
DummyPlayer::ProcessImplementationLink *const implementationLink = this;
handle.activate(implementationLink, &terminate);
return handle; // note the deleter function...
}
@ -344,7 +352,7 @@ namespace proc {
{
REQUIRE (isActive());
ASSERT (imageGen_);
if (play_)
display_(imageGen_->next());
else
@ -361,13 +369,7 @@ namespace proc {
namespace lumiera { /* === Forwarding function(s) on the Process handle === */
void DummyPlayer::Process::play(bool yes) { impl().doPlay(yes); }
namespace lumiera {
/** @internal intended for use by main(). */
lumiera::Subsys&

View file

@ -31,7 +31,7 @@
** This service is the implementation of a layer separation facade interface. Clients should use
** proc::play::DummyPlayer#facade to access this service. This header defines the interface used
** to \em provide this service, not to access it.
**
**
** @see lumiera::DummyPlayer
** @see gui::PlaybackController usage example
*/
@ -78,7 +78,7 @@ namespace proc {
* ProcessImpl instance and have to manage the lifecycle manually.
*/
class ProcessImpl
: public lumiera_playprocess,
: public lumiera::DummyPlayer::ProcessImplementationLink,
boost::noncopyable
{
uint fps_;
@ -109,7 +109,7 @@ namespace proc {
/* Lifecycle */
DummyPlayer::Process createHandle();
static void terminate(ProcessImpl* process);
static void terminate(DummyPlayer::ProcessImplementationLink*);
private:
void doFrame (); ///< periodically invoked while playing
@ -164,3 +164,4 @@ namespace proc {
} // namespace proc
#endif