Switch further Service implementations and obsolete SingletonRef alltogether

SingletonRef was only invented because lib::Depend (or lib::Singleton at that time)
offered only on-demand initialisation, but could not attach to an external service.
But this is required for calling out at the implementation side of a
Lumiera Interface into the actual service implementation.

The recently created DependInject::ServiceInstance now fulfils this task way better
and is seamlessly integrated into the lib::Depend front-end
This commit is contained in:
Fischlurch 2018-04-02 05:00:01 +02:00
parent 29ee5131f4
commit 6fe8e970cb
9 changed files with 53 additions and 200 deletions

View file

@ -43,6 +43,8 @@
#define GUI_CTRL_FACADE_H
#include "gui/notification-service.hpp"
#include "gui/display-service.hpp"
#include "lib/depend-inject.hpp"
#include "lib/nocopy.hpp"
@ -61,7 +63,11 @@ namespace ctrl {
class Facade
: util::NonCopyable
{
NotificationService notificationService_;
using Instance_Notification = lib::DependInject<NotificationService>::ServiceInstance<>;
using Instance_DisplayService = lib::DependInject<DisplayService>::ServiceInstance<>;
Instance_Notification notificationService_;
Instance_DisplayService displayService_; ///////////////////////////////////////////////////////TICKET #82 obsolete and will go away once we have a real OutputSlot offered by the UI
public:
@ -69,7 +75,8 @@ namespace ctrl {
* Activate all external UI facade interfaces.
*/
Facade (UiBus& bus, UiManager& manager)
: notificationService_(bus.getAccessPoint(), manager) // opens the GuiNotificationService instance
: notificationService_{bus.getAccessPoint(), manager} // opens the GuiNotificationService instance
, displayService_{} // opens the DisplayService instance ////////TICKET #82 obsolete
{
INFO (gui, "UI-Facade Interfaces activated.");
}

View file

@ -33,6 +33,7 @@
#include "gui/display-service.hpp"
#include "lib/depend.hpp"
extern "C" {
#include "common/interface-descriptor.h"
@ -120,9 +121,8 @@ namespace gui {
using lumiera::facade::LUMIERA_ERROR_FACADE_LIFECYCLE;
typedef lib::SingletonRef<DisplayService>::Accessor InstanceRef;
InstanceRef _instance; ///< a backdoor for the C Language impl to access the actual DisplayService implementation...
lib::Depend<DisplayService> _instance; ///< a backdoor for the C Language impl to access the actual SessionCommand implementation...
@ -143,7 +143,7 @@ namespace gui {
REQUIRE (slotHandle);
try
{
_instance->allocate (slotHandle,true);
_instance().allocate (slotHandle,true);
}
catch (lumiera::Error&){ /* error state remains set */ }
}
@ -158,7 +158,7 @@ namespace gui {
}
REQUIRE (slotHandle);
_instance->allocate (slotHandle,false);
_instance().allocate (slotHandle,false);
}
)
, LUMIERA_INTERFACE_INLINE (put,
@ -168,7 +168,7 @@ namespace gui {
REQUIRE (_instance && !lumiera_error_peek());
REQUIRE (slotHandle);
DisplayerSlot& slot = _instance->resolve (slotHandle);
DisplayerSlot& slot = _instance().resolve (slotHandle);
slot.put (frame);
}
)
@ -183,19 +183,18 @@ namespace gui {
DisplayService::DisplayService()
: error_("")
, implInstance_(this,_instance)
: error_{}
, serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_Display, 0, lumieraorg_DisplayService))
{
INFO (progress, "Display Facade opened.");
}
{
INFO (progress, "Display Facade opened.");
}
LumieraDisplaySlot
DisplayService::setUp (FrameDestination const& outputDestination)
{
DisplayerTab& slots (_instance->slots_);
DisplayerTab& slots (_instance().slots_);
return &slots.manage (new DisplayerSlot (outputDestination));
}

View file

@ -52,7 +52,6 @@
#include "include/display-facade.h"
#include "common/instancehandle.hpp"
#include "lib/singleton-ref.hpp"
#include "lib/scoped-ptrvect.hpp"
#include "include/logging.h"
#include "lib/nocopy.hpp"
@ -140,17 +139,12 @@ namespace gui {
typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_Display, 0)
, lumiera::Display
> ServiceInstanceHandle;
lib::SingletonRef<DisplayService> implInstance_;
ServiceInstanceHandle serviceInstance_;
public:
DisplayService();
~DisplayService() {
INFO (proc_dbg, "Display service dying...");
}
~DisplayService() { INFO (proc_dbg, "Display service dying..."); }
/** open a new display, sending frames to the given output destination

View file

@ -52,7 +52,6 @@
#include "gui/ui-bus.hpp"
#include "gui/guifacade.hpp"
#include "gui/ctrl/ui-manager.hpp"
#include "gui/display-service.hpp"
#include "backend/thread-wrapper.hpp"
#include "common/subsys.hpp"
#include "lib/nocopy.hpp"
@ -84,22 +83,19 @@ namespace gui {
/**************************************************************************//**
* Implement the necessary steps for actually making the Lumiera Gui available.
* Establish the UI backbone services and start up the GTK GUI main event loop.
* @todo to ensure invocation of the termination signal, any members
* should be failsafe on initialisation (that means, we must not
* open other interfaces here...) ///////////////////////////TICKET #82
* @warning to ensure reliable invocation of the termination signal,
* any members should be failsafe on initialisation
*/
class GtkLumiera
: util::NonCopyable
{
UiBus uiBus_;
UiManager uiManager_;
DisplayService activateDisplayService_; ///////////////////////////TICKET #82 will go away once we have a real OutputSlot offered by the UI
public:
GtkLumiera ()
: uiBus_{}
, uiManager_{uiBus_}
, activateDisplayService_() ///////////////////////////TICKET #82 obsolete (and incurs a race)
{ }

View file

@ -51,6 +51,7 @@
#include "lib/diff/mutation-message.hpp"
#include "lib/diff/gen-node.hpp"
#include "include/logging.h"
#include "lib/depend.hpp"
#include "lib/util.hpp"
extern "C" {
@ -209,9 +210,8 @@ namespace gui {
using lumiera::facade::LUMIERA_ERROR_FACADE_LIFECYCLE;
typedef lib::SingletonRef<GuiNotification>::Accessor InstanceRef;
InstanceRef _instance; ///< a backdoor for the C Language impl to access the actual GuiNotification implementation...
lib::Depend<NotificationService> _instance; ///< a backdoor for the C Language impl to access the actual SessionCommand implementation...
@ -225,7 +225,7 @@ namespace gui {
{
if (!_instance) lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, text);
else
_instance->displayInfo (NotifyLevel(severity), text);
_instance().displayInfo (NotifyLevel(severity), text);
}
)
, LUMIERA_INTERFACE_INLINE (markError,
@ -233,7 +233,7 @@ namespace gui {
{
if (!_instance) lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, text);
else
_instance->markError (reinterpret_cast<ID> (*element), text);
_instance().markError (reinterpret_cast<ID> (*element), text);
}
)
, LUMIERA_INTERFACE_INLINE (markNote,
@ -241,7 +241,7 @@ namespace gui {
{
if (!_instance) lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, text);
else
_instance->markNote (reinterpret_cast<ID> (*element), text);
_instance().markNote (reinterpret_cast<ID> (*element), text);
}
)
, LUMIERA_INTERFACE_INLINE (mutate,
@ -249,7 +249,7 @@ namespace gui {
{
if (!_instance) lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, "passing diff message");
else
_instance->mutate (reinterpret_cast<ID> (*element), move(*reinterpret_cast<MutationMessage*> (diff)));
_instance().mutate (reinterpret_cast<ID> (*element), move(*reinterpret_cast<MutationMessage*> (diff)));
}
)
, LUMIERA_INTERFACE_INLINE (triggerGuiShutdown,
@ -257,7 +257,7 @@ namespace gui {
{
if (!_instance) lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, cause);
else
_instance->triggerGuiShutdown (cause);
_instance().triggerGuiShutdown (cause);
}
)
);
@ -281,11 +281,10 @@ namespace gui {
: BusTerm{lib::idi::EntryID<NotificationService>{}, upLink}
, dispatch_{new UiDispatcher{[this](string msg){ displayInfo (NOTE_ERROR, msg); }}}
, uiManager_{uiManager}
, implInstance_(this,_instance)
, serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_GuiNotification, 0,lumieraorg_GuiNotificationService))
{
INFO (gui, "GuiNotification Facade opened.");
}
{
INFO (gui, "GuiNotification Facade opened.");
}
NotificationService::~NotificationService() { } // emit dtors of embedded objects here...

View file

@ -42,7 +42,6 @@
#include "include/gui-notification-facade.h"
#include "common/instancehandle.hpp"
#include "gui/ctrl/bus-term.hpp"
#include "lib/singleton-ref.hpp"
#include <memory>
@ -78,15 +77,6 @@ namespace gui {
, public ctrl::BusTerm
{
/* === Implementation of the Facade Interface === */
void displayInfo (NotifyLevel,string const& text) override;
void markError (ID uiElement, string const& text) override;
void markNote (ID uiElement, string const& text) override;
void mutate (ID uiElement, MutationMessage&&) override;
void triggerGuiShutdown (string const& cause) override;
private:
std::unique_ptr<ctrl::UiDispatcher> dispatch_;
ctrl::UiManager& uiManager_;
@ -98,15 +88,20 @@ namespace gui {
using ServiceInstanceHandle = lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_GuiNotification, 0)
, GuiNotification
> ;
lib::SingletonRef<GuiNotification> implInstance_;
ServiceInstanceHandle serviceInstance_;
public:
~NotificationService();
NotificationService (ctrl::BusTerm& upLink, ctrl::UiManager& uiManager);
/* === Implementation of the Facade Interface === */
void displayInfo (NotifyLevel,string const& text) override;
void markError (ID uiElement, string const& text) override;
void markNote (ID uiElement, string const& text) override;
void mutate (ID uiElement, MutationMessage&&) override;
void triggerGuiShutdown (string const& cause) override;
};

View file

@ -1,133 +0,0 @@
/*
SINGLETON-REF.hpp - helper template providing singleton-like access for implementation code
Copyright (C) Lumiera.org
2008, 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 singleton-ref.hpp
** Helper for singleton-kind access without managing object creation and lifecycle.
** A typical usage scenario is when implementing C Language Interfaces without any
** canonical access to some "this" pointer. In this case
** - an instance of the \c Access policy class is created "somewhere" (usually as
** global variable). Calls from within the C code would enter through this accessor.
** - when the actual service implementation class comes up, it creates an SingletonRef
** instance and thereby wires the (already existing) accessor up with \c *this
** - when the service goes down, access is closed automatically and reliably.
** Client code (from within C) should check the accessor (by \c bool check)
** prior to any access, because accessing a closed connection will throw
** (that's unfortunate, but at least throwing is better than segfaulting)
**
** @see gui::NotificationService usage example
*/
#ifndef LIB_SINGLETON_REF_H
#define LIB_SINGLETON_REF_H
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
namespace lib {
namespace singleton {
/***********************************//**
* Detail/Policy class specifying
* how the SingletonRef can be accessed
*/
template<class TY>
class AccessAsReference
: util::NonCopyable
{
TY* obj_;
typedef AccessAsReference<TY> _ThisType;
public:
void
open (TY* instance)
{
ASSERT (!obj_, "Lifecycle error");
obj_ = instance;
}
void
close ()
{
ASSERT (obj_, "Lifecycle error");
obj_ = nullptr;
}
TY*
operator-> () const
{
if (!isValid())
throw lumiera::error::State("Target currently not available.");
return obj_;
}
explicit operator bool() const { return obj_; }
bool isValid() const { return obj_; }
};
} // namespace Singleton
/*********************************************************//**
* Helper template providing singleton access without managing
* object creation and lifecycle. Just the access to the
* implementation instance is handled: on creation, access is
* enabled, and disabled on destruction. Client code is assumed
* to invoke through the Access (template template param),
* handed in as ctor parameter.
* @param TY the actual type to be made accessible
* @param B a base class to inherit from; defaults to noncopyable
* @param Accessor how to implement the static instance access
*/
template< class TY
, class B = util::NonCopyable
, template<class> class Access = singleton::AccessAsReference
>
struct SingletonRef
: public B
{
typedef Access<TY> Accessor;
Accessor& accessor_;
SingletonRef(TY * instance, Accessor& acc)
: accessor_(acc)
{
accessor_.open (instance);
}
~SingletonRef()
{
accessor_.close ();
}
};
} // namespace lib
#endif

View file

@ -29,6 +29,7 @@
#include "proc/play/dummy-player-service.hpp"
#include "proc/engine/worker/dummy-image-generator.hpp"
#include "proc/engine/worker/tick-service.hpp"
#include "lib/depend-inject.hpp"
#include "lib/depend.hpp"
extern "C" {
@ -58,6 +59,12 @@ namespace proc {
class DummyPlayerSubsysDescriptor
: public Subsys
{
using ServiceHandle = lib::DependInject<DummyPlayerService>::ServiceInstance<>;
/** manages the actual (single) instance of the player service impl */
ServiceHandle thePlayer_;
operator string () const { return "Dummy-Player"; }
@ -72,18 +79,14 @@ namespace proc {
{
ASSERT (!thePlayer_);
thePlayer_.reset (new DummyPlayerService (terminationHandle));
thePlayer_.createInstance (terminationHandle);
return true;
}
/** manages the actual (single) instance of the player service impl */
std::unique_ptr<DummyPlayerService> thePlayer_;
void
triggerShutdown () noexcept override
{
thePlayer_.reset(0);
thePlayer_.shutdown();
// note: shutdown of the DummyPlayerService instance may block
// for a short period, until termination of all tick services
}
@ -174,9 +177,7 @@ namespace proc {
using lumiera::facade::LUMIERA_ERROR_FACADE_LIFECYCLE;
typedef lib::SingletonRef<DummyPlayerService>::Accessor InstanceRef;
InstanceRef _instance; ///< a backdoor for the C Language impl to access the actual DummyPlayer implementation...
lib::Depend<DummyPlayerService> _instance; ///< a backdoor for the C Language impl to access the actual SessionCommand implementation...
typedef ProcessImpl* ProcP;
@ -195,7 +196,7 @@ namespace proc {
return 0;
}
return static_cast<LumieraPlayProcess> (_instance->start(viewerHandle));
return static_cast<LumieraPlayProcess> (_instance().start(viewerHandle));
}
)
, LUMIERA_INTERFACE_INLINE (togglePlay,
@ -241,11 +242,10 @@ namespace proc {
DummyPlayerService::DummyPlayerService (Subsys::SigTerm terminationHandle)
: error_("")
, notifyTermination_(terminationHandle)
, implInstance_(this,_instance)
, serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_DummyPlayer, 0, lumieraorg_DummyPlayerService))
{
INFO (progress, "DummyPlayer Facade opened.");
}
{
INFO (progress, "DummyPlayer Facade opened.");
}

View file

@ -44,7 +44,6 @@
#include "include/dummy-player-facade.h"
#include "include/display-facade.h"
#include "common/instancehandle.hpp"
#include "lib/singleton-ref.hpp"
#include "lib/nocopy.hpp"
#include <memory>
@ -138,13 +137,10 @@ namespace proc {
typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_DummyPlayer, 0)
, DummyPlayer
> ServiceInstanceHandle;
lib::SingletonRef<DummyPlayerService> implInstance_;
ServiceInstanceHandle serviceInstance_;
public:
DummyPlayerService(Subsys::SigTerm terminationHandle);
~DummyPlayerService() { notifyTermination_(&error_); }