Demote the Play-Facade to a in-language (C++) Interface to get rid of InterfaceFacadeLink

I am fully aware this change has some far reaching ramifications.
Effectively I am hereby abandoning the goal of a highly modularised Lumiera,
where every major component is mapped over the Interface-System. This was
always a goal I accepted only reluctantly, and my now years of experience
confirm my reservation: it will cost us lots of efforts just for the
sake of being "sexy".
This commit is contained in:
Fischlurch 2018-04-03 02:14:45 +02:00
parent 9f3c127240
commit 4e0d99e928
8 changed files with 40 additions and 166 deletions

View file

@ -1,124 +0,0 @@
/*
INTERFACE-FACADE-LINK - a switchable link from interface to service implementation
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 interface-facade-link.hpp
** Opening, accessing and closing the service access through a facade interface.
** Client code is assumed to access an application level service through an facade
** interface, while the actual implementation object remains an opaque internal detail.
** Moreover, services may come up and shut down, so the implementation might change
** during the Lifecycle. The facility defined here in this header provides a basic
** implementation for this access mechanism, but without any adaptation, binding
** or plugin access layer. It works only under the assumption that both the
** interface and the actual service implementation coexist in the same
** executable and are written in C++, so any invocation of an
** interface method boils down to a language-level call.
**
** Usually, client code doesn't need to include this header. Clients are assumed
** to use the facade interface of the service in question. This facade interface
** contains a static member of type \c lumiera::facade::Accessor<I> (where I is
** the type of the facade interface). The Accessor baseclass is defined in
** interfaceproxy.hpp and typically included through the facade header.
**
** @note there is a way more elaborate implementation of the same mechanism
** for use with the Lumiera Interface/Plugin system.
**
** @see interfaceproxy.hpp description of the more general use case
** @see PlayService example for the simple use case
*/
#ifndef LUMIERA_FACADE_INTERFACE_FACADE_LINK_H
#define LUMIERA_FACADE_INTERFACE_FACADE_LINK_H
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#include "lib/meta/util.hpp"
#include "include/interfaceproxy.hpp"
#include "lib/symbol.hpp"
namespace lumiera {
namespace facade {
using lib::Literal;
/********************************************************************//**
* simple access-frontend to the implementation of a service (C++ only).
* Usually, an instance of Accessor is placed as static member right into
* the facade interface used to access the service. This implementation
* of the access mechanism handles the simple case that both the facade
* and the service implementation are written in C++ and calls happen
* within the main executable as direct language calls, without an
* binding layer and without involving the Interface/Plugin system.
*
* Typically, the InterfaceFacadeLink becomes a member of the service
* implementation class and is directly tied into the constructor of
* the latter. Being a subclass of lumiera::facade::Accessor, it is
* allowed to "open" the facade access just by setting the static
* protected pointer Accessor::implProxy_
*/
template<class FA>
class InterfaceFacadeLink
: protected Accessor<FA>
, util::NonCopyable
{
string displayName_;
void
__checkLifecycle ()
{
if (Accessor<FA>::implProxy_)
throw error::State("Attempt to open an already opened Facade interface."
, error::LERR_(LIFECYCLE));
}
public:
InterfaceFacadeLink(FA& serviceImpl, Literal interfaceName_for_Log=0)
: displayName_(interfaceName_for_Log? string(interfaceName_for_Log)
: util::typeStr<FA>())
{
__checkLifecycle();
Accessor<FA>::implProxy_ = &serviceImpl;
INFO (interface, "interface %s opened", displayName_.c_str());
}
~InterfaceFacadeLink()
{
INFO (interface, "closing interface %s...", displayName_.c_str());
Accessor<FA>::implProxy_ = 0;
}
};
/** storage for the static access pointer */
template<class FA>
FA* Accessor<FA>::implProxy_;
}} // namespace lumiera::facade
#endif

View file

@ -21,8 +21,13 @@
*/
/** @file play-facade.h
/** @file play-facade.hpp
** Public access point to the _playback service_ provided by the »play-out subsystem«
** @todo in theory this could be an external interface mapped via Lumiera's interface system.
** This would be much work however, and not serve any tangible goal in the current stage
** of development (2018). I take this as just another confirmation that turning everything
** into a plug-in does not quality as good architecture: if you want to do it right, it
** creates a lot of additional cost. And to do it just superficially would be like cheating.
*/
@ -31,15 +36,11 @@
#ifdef __cplusplus /* ============== C++ Interface ================= */
//#include "include/interfaceproxy.hpp"
#include "lib/depend.hpp"
#include "lib/handle.hpp"
#include "lib/iter-source.hpp" ////////////////////TICKET #493 : only using the IterSource base interface here
#include "lib/time/control.hpp"
#include "lib/time/timevalue.hpp"
#include "include/interfaceproxy.hpp"
#include "proc/mobject/model-port.hpp"
#include "proc/mobject/output-designation.hpp"
#include "proc/mobject/session/clip.hpp"
@ -83,7 +84,7 @@ namespace lumiera {
public:
/** get an implementation instance of this service */
static lumiera::facade::Accessor<Play> facade;
static lib::Depend<Play> facade;
/**
@ -153,19 +154,4 @@ namespace lumiera {
} // namespace lumiera
extern "C" {
#endif /* =========================== CL Interface ===================== */
// #include "common/interface.h"
////////////////////////////////////TODO define a C binding for the Interface system here
#ifdef __cplusplus
}
#endif
#endif
#endif /*PROC_INTERFACE_PLAY_H*/

View file

@ -72,7 +72,7 @@ namespace play {
Lock sync(this);
REQUIRE (not shutdown_initiated_);
player_.reset (new PlayService);
player_.createInstance();
return this->isOperational();
}
@ -132,7 +132,7 @@ namespace play {
try
{
TODO ("actually bring down the output generation");
player_.reset(0);
player_.shutdown();
completedSignal(0);
}

View file

@ -37,6 +37,7 @@
#include "lib/error.hpp"
#include "lib/depend.hpp"
#include "lib/depend-inject.hpp"
#include "proc/play/output-manager.hpp"
#include "common/subsys.hpp"
#include "lib/nocopy.hpp"
@ -54,6 +55,7 @@ namespace play {
using std::unique_ptr;
class Play;
class PlayService;
@ -70,9 +72,10 @@ namespace play {
: util::NonCopyable
, public lib::Sync<>
{
typedef lumiera::Subsys::SigTerm SigTerm;
using SigTerm = lumiera::Subsys::SigTerm;
using PlayServiceHandle = lib::DependInject<Play>::ServiceInstance<PlayService>;
unique_ptr<PlayService> player_;
PlayServiceHandle player_;
///////TODO more components and connections to manage here...
bool shutdown_initiated_ = false; /////TODO probably need a way more elaborate lifecylce management

View file

@ -27,7 +27,7 @@
#include "lib/error.hpp"
#include "include/play-facade.h"
#include "include/play-facade.hpp"
#include "proc/play/play-service.hpp"
#include "proc/play/play-process.hpp"
#include "proc/play/render-configurator.hpp"
@ -167,8 +167,7 @@ namespace play {
* this service through the lumiera::Play facade.
*/
PlayService::PlayService()
: facadeAccess_(*this, "Player")
, pTable_(new ProcessTable)
: pTable_(new ProcessTable)
{ }

View file

@ -58,8 +58,7 @@
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#include "include/play-facade.h"
#include "common/interface-facade-link.hpp"
#include "include/play-facade.hpp"
#include <memory>
//#include <string>
@ -102,7 +101,6 @@ namespace play {
: public lumiera::Play
, util::NonCopyable
{
InterfaceFacadeLink<lumiera::Play> facadeAccess_;
std::unique_ptr<ProcessTable> pTable_;

View file

@ -30,7 +30,7 @@
#include "proc/play/dummy-play-connection.hpp"
//#include "proc/engine/buffhandle.hpp"
//#include "proc/engine/testframe.hpp"
#include "include/play-facade.h"
#include "include/play-facade.hpp"
#include "lib/time/control.hpp"

View file

@ -28345,8 +28345,8 @@
<node CREATED="1522635366958" ID="ID_70940233" MODIFIED="1522639464220" TEXT="w&#xe4;re jetzt ebenfalls denkbar">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1522638768719" ID="ID_1027038623" MODIFIED="1522639457609" TEXT="InterfaceFacadeLink">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1522638768719" ID="ID_1027038623" MODIFIED="1522713321459" TEXT="InterfaceFacadeLink">
<icon BUILTIN="button_ok"/>
<node CREATED="1522638777486" ID="ID_1287650379" MODIFIED="1522638916886" TEXT="serivce-Handle"/>
<node CREATED="1522638783717" ID="ID_357133685" MODIFIED="1522638790235" TEXT="umgeht das Interface-system">
<icon BUILTIN="ksmiletris"/>
@ -28354,7 +28354,8 @@
<node CREATED="1522638791268" ID="ID_965518210" MODIFIED="1522638800868" TEXT="tja, lib::Depend macht das jetzt auch">
<icon BUILTIN="ksmiletris"/>
</node>
<node CREATED="1522638812521" ID="ID_893221959" MODIFIED="1522638820556" TEXT="nur ein einziges mal verwendet">
<node CREATED="1522638812521" ID="ID_893221959" MODIFIED="1522712867059" TEXT="nur ein einziges mal verwendet">
<icon BUILTIN="idea"/>
<node CREATED="1522638830367" ID="ID_792298822" MODIFIED="1522638835178" TEXT="PlayService"/>
<node CREATED="1522638837022" ID="ID_362446492" MODIFIED="1522638876050">
<richcontent TYPE="NODE"><html>
@ -28366,8 +28367,7 @@
den habe ich <b>nicht mehr</b>&#160;&#252;ber das Interface-System gemappt
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<richcontent TYPE="NOTE"><html>
<head>
@ -28380,13 +28380,25 @@
Also hat das hier Prototyp-Charakter!
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1522638877744" ID="ID_1175146695" MODIFIED="1522638901259" TEXT="sollte prototypisch-sauber umgestellt werden">
<node CREATED="1522638877744" ID="ID_1175146695" MODIFIED="1522712862995" TEXT="sollte prototypisch-sauber umgestellt werden">
<icon BUILTIN="yes"/>
</node>
</node>
<node COLOR="#338800" CREATED="1522712059423" ID="ID_885178924" MODIFIED="1522713316288" TEXT="komplett auf lib::Depend umstellen">
<icon BUILTIN="yes"/>
<node CREATED="1522712083659" ID="ID_1397345256" MODIFIED="1522712851333" TEXT="das hei&#xdf;t: nicht einmal mehr die Fiktion einer Trennung">
<icon BUILTIN="messagebox_warning"/>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1522712827196" ID="ID_61159385" MODIFIED="1522712843093" TEXT="ein sauber gebautes C++ - Inteface ist Trennung genug">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node COLOR="#338800" CREATED="1522713332342" ID="ID_1078169696" MODIFIED="1522713348764" TEXT="der OutputDirector steuert nun diesen Service">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1522638949038" ID="ID_1756362217" MODIFIED="1522639349336" TEXT="interfaceproxy - Accessor">
<icon BUILTIN="flag-yellow"/>