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:
parent
29ee5131f4
commit
6fe8e970cb
9 changed files with 53 additions and 200 deletions
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{ }
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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_); }
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue