diff --git a/src/gui/ctrl/facade.hpp b/src/gui/ctrl/facade.hpp index b380b71bd..6d6093d2d 100644 --- a/src/gui/ctrl/facade.hpp +++ b/src/gui/ctrl/facade.hpp @@ -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::ServiceInstance<>; + using Instance_DisplayService = lib::DependInject::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."); } diff --git a/src/gui/display-service.cpp b/src/gui/display-service.cpp index 7a6e07211..3a84b573a 100644 --- a/src/gui/display-service.cpp +++ b/src/gui/display-service.cpp @@ -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::Accessor InstanceRef; - InstanceRef _instance; ///< a backdoor for the C Language impl to access the actual DisplayService implementation... + lib::Depend _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)); } diff --git a/src/gui/display-service.hpp b/src/gui/display-service.hpp index 9b753c464..c0e168930 100644 --- a/src/gui/display-service.hpp +++ b/src/gui/display-service.hpp @@ -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 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 diff --git a/src/gui/gtk-lumiera.cpp b/src/gui/gtk-lumiera.cpp index ae5cf9390..674ef7f27 100644 --- a/src/gui/gtk-lumiera.cpp +++ b/src/gui/gtk-lumiera.cpp @@ -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) { } diff --git a/src/gui/notification-service.cpp b/src/gui/notification-service.cpp index b0f8d014f..76d47b5a0 100644 --- a/src/gui/notification-service.cpp +++ b/src/gui/notification-service.cpp @@ -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::Accessor InstanceRef; - InstanceRef _instance; ///< a backdoor for the C Language impl to access the actual GuiNotification implementation... + lib::Depend _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 (*element), text); + _instance().markError (reinterpret_cast (*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 (*element), text); + _instance().markNote (reinterpret_cast (*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 (*element), move(*reinterpret_cast (diff))); + _instance().mutate (reinterpret_cast (*element), move(*reinterpret_cast (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{}, 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... diff --git a/src/gui/notification-service.hpp b/src/gui/notification-service.hpp index 355b735cd..93dd82666 100644 --- a/src/gui/notification-service.hpp +++ b/src/gui/notification-service.hpp @@ -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 @@ -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 dispatch_; ctrl::UiManager& uiManager_; @@ -98,15 +88,20 @@ namespace gui { using ServiceInstanceHandle = lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_GuiNotification, 0) , GuiNotification > ; - lib::SingletonRef 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; }; diff --git a/src/lib/singleton-ref.hpp b/src/lib/singleton-ref.hpp deleted file mode 100644 index a828218c5..000000000 --- a/src/lib/singleton-ref.hpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - SINGLETON-REF.hpp - helper template providing singleton-like access for implementation code - - Copyright (C) Lumiera.org - 2008, Hermann Vosseler - - 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 AccessAsReference - : util::NonCopyable - { - TY* obj_; - - typedef AccessAsReference _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 Access = singleton::AccessAsReference - > - struct SingletonRef - : public B - { - - typedef Access Accessor; - Accessor& accessor_; - - SingletonRef(TY * instance, Accessor& acc) - : accessor_(acc) - { - accessor_.open (instance); - } - - ~SingletonRef() - { - accessor_.close (); - } - }; - - - -} // namespace lib -#endif diff --git a/src/proc/play/dummy-player-service.cpp b/src/proc/play/dummy-player-service.cpp index 5b441c683..346f53f62 100644 --- a/src/proc/play/dummy-player-service.cpp +++ b/src/proc/play/dummy-player-service.cpp @@ -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::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 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::Accessor InstanceRef; - - InstanceRef _instance; ///< a backdoor for the C Language impl to access the actual DummyPlayer implementation... + lib::Depend _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 (_instance->start(viewerHandle)); + return static_cast (_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."); + } diff --git a/src/proc/play/dummy-player-service.hpp b/src/proc/play/dummy-player-service.hpp index 65f1121bf..b91b560e1 100644 --- a/src/proc/play/dummy-player-service.hpp +++ b/src/proc/play/dummy-player-service.hpp @@ -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 @@ -138,13 +137,10 @@ namespace proc { typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_DummyPlayer, 0) , DummyPlayer > ServiceInstanceHandle; - - lib::SingletonRef implInstance_; ServiceInstanceHandle serviceInstance_; public: DummyPlayerService(Subsys::SigTerm terminationHandle); - ~DummyPlayerService() { notifyTermination_(&error_); }