Guistart(#1045): relocate opening of GuiNotification into the CoreServices
up to now this happened from the GuiRunner, which was a rather bad idea - it can throw and thus interfer with the startup process - the GuiNotification can not sensibly be *implemented* just backed by the GuiRunner. While CoreService offers access to the necessary implementation facilities to do so
This commit is contained in:
parent
5e9b3be985
commit
b6e7caf737
5 changed files with 78 additions and 15 deletions
|
|
@ -62,7 +62,7 @@ namespace backend {
|
||||||
* The new thread starts immediately within the ctor; after returning, the new
|
* The new thread starts immediately within the ctor; after returning, the new
|
||||||
* thread has already copied the arguments and indeed actively started to run.
|
* thread has already copied the arguments and indeed actively started to run.
|
||||||
*
|
*
|
||||||
* \par Joining, cancellation and memory management
|
* # Joining, cancellation and memory management
|
||||||
* In the basic version (class Thread), the created thread is completely detached
|
* In the basic version (class Thread), the created thread is completely detached
|
||||||
* and not further controllable. There is no way to find out its execution state,
|
* and not further controllable. There is no way to find out its execution state,
|
||||||
* wait on termination or even cancel it. Client code needs to implement such
|
* wait on termination or even cancel it. Client code needs to implement such
|
||||||
|
|
@ -77,7 +77,7 @@ namespace backend {
|
||||||
* must join to prevent pulling away member variables the thread function will
|
* must join to prevent pulling away member variables the thread function will
|
||||||
* continue to use.
|
* continue to use.
|
||||||
*
|
*
|
||||||
* \par failures in the thread function
|
* # failures in the thread function
|
||||||
* The operation started in the new thread is protected by a top-level catch block.
|
* The operation started in the new thread is protected by a top-level catch block.
|
||||||
* Error states or caught exceptions can be propagated through the lumiera_error
|
* Error states or caught exceptions can be propagated through the lumiera_error
|
||||||
* state flag, when using the \c join() facility. By invoking \join().maybeThrow()
|
* state flag, when using the \c join() facility. By invoking \join().maybeThrow()
|
||||||
|
|
@ -86,7 +86,7 @@ namespace backend {
|
||||||
* async Thread is considered a violation of policy and will result in emergency
|
* async Thread is considered a violation of policy and will result in emergency
|
||||||
* shutdown of the whole application.
|
* shutdown of the whole application.
|
||||||
*
|
*
|
||||||
* \par synchronisation barriers
|
* # synchronisation barriers
|
||||||
* Lumiera threads provide a low-level synchronisation mechanism, which is used
|
* Lumiera threads provide a low-level synchronisation mechanism, which is used
|
||||||
* to secure the hand-over of additional arguments to the thread function. It
|
* to secure the hand-over of additional arguments to the thread function. It
|
||||||
* can be used by client code, but care has to be taken to avoid getting out
|
* can be used by client code, but care has to be taken to avoid getting out
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,14 @@ namespace gui {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @warning there is a possible race here,
|
||||||
|
* when shutdown is triggered before the GUI was able to open the GuiNotification interface.
|
||||||
|
* However, the Lumiera thread handling wrapper/framework ensures that a new thread actually
|
||||||
|
* starts to execute (and picks up the arguments), prior to returning from the thread starting
|
||||||
|
* function. For this reason, it is rather unlikely this race actually happens in practice,
|
||||||
|
* since opening the GuiNotification interface is done early, while starting the UI-Bus.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
triggerShutdown () noexcept override
|
triggerShutdown () noexcept override
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
#include "include/logging.h"
|
#include "include/logging.h"
|
||||||
//#include "lib/idi/entry-id.hpp"
|
//#include "lib/idi/entry-id.hpp"
|
||||||
|
#include "gui/notification-service.hpp"
|
||||||
#include "gui/ctrl/bus-term.hpp"
|
#include "gui/ctrl/bus-term.hpp"
|
||||||
#include "gui/ctrl/nexus.hpp"
|
#include "gui/ctrl/nexus.hpp"
|
||||||
//#include "lib/util.hpp"
|
//#include "lib/util.hpp"
|
||||||
|
|
@ -89,6 +90,7 @@ namespace ctrl{
|
||||||
{
|
{
|
||||||
|
|
||||||
Nexus uiBusBackbone_;
|
Nexus uiBusBackbone_;
|
||||||
|
NotificationService activateNotificationService_;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
act (GenNode const& command)
|
act (GenNode const& command)
|
||||||
|
|
@ -109,6 +111,7 @@ namespace ctrl{
|
||||||
CoreService (ID identity =lib::idi::EntryID<CoreService>())
|
CoreService (ID identity =lib::idi::EntryID<CoreService>())
|
||||||
: BusTerm(identity, uiBusBackbone_)
|
: BusTerm(identity, uiBusBackbone_)
|
||||||
, uiBusBackbone_{*this}
|
, uiBusBackbone_{*this}
|
||||||
|
, activateNotificationService_() // opens the GuiNotification facade interface
|
||||||
{
|
{
|
||||||
INFO (gui, "UI-Backbone operative.");
|
INFO (gui, "UI-Backbone operative.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,14 +30,15 @@
|
||||||
** up the GUI. The loading and shutdown process is carried out by gui::GuiFacade and
|
** up the GUI. The loading and shutdown process is carried out by gui::GuiFacade and
|
||||||
** controlled by lumiera::AppState, which in turn is activated by Lumiera main().
|
** controlled by lumiera::AppState, which in turn is activated by Lumiera main().
|
||||||
**
|
**
|
||||||
** After successfully loading this module, a call to #kickOff is expected to be
|
** After successfully loading this module, a call to GuiFacade::launchUI is expected to
|
||||||
** issued, passing a termination signal (callback) to be executed when the GUI
|
** happen, passing a termination signal (callback) to be executed when the GUI terminates.
|
||||||
** terminates. The \c kickOff() call remains blocked within the main GTK event loop;
|
** The implementation of GuiFacade in the GuiRunner in fact issues this call from the ctor
|
||||||
** thus typically this call should be issued within a separate dedicated GUI thread.
|
** body, while the interface is opened via an InstanceHandle member. The `launchUI()` call
|
||||||
** Especially, the gui::GuiRunner will ensure this to happen.
|
** starts a new thread, which then becomes the UI event thread and remains blocked within
|
||||||
**
|
** the main GTK event loop. Before entering this loop, the CoreService of the GUI and
|
||||||
** Prior to entering the GTK event loop, all primary "business" interface of the GUI
|
** especially the [UI-Bus](\ref ui-bus.hpp) is started see \ref GtkLumiera::run.
|
||||||
** will be opened (currently as of 1/09 this is the interface gui::GuiNotification.)
|
** This entails also to open the primary "business" interface(s) of the GUI
|
||||||
|
** (currently as of 1/16 this is the interface gui::GuiNotification.)
|
||||||
**
|
**
|
||||||
** @see lumiera::AppState
|
** @see lumiera::AppState
|
||||||
** @see gui::GuiFacade
|
** @see gui::GuiFacade
|
||||||
|
|
@ -54,7 +55,6 @@
|
||||||
|
|
||||||
#include "lib/error.hpp"
|
#include "lib/error.hpp"
|
||||||
#include "gui/guifacade.hpp"
|
#include "gui/guifacade.hpp"
|
||||||
#include "gui/notification-service.hpp"
|
|
||||||
#include "gui/display-service.hpp"
|
#include "gui/display-service.hpp"
|
||||||
#include "common/subsys.hpp"
|
#include "common/subsys.hpp"
|
||||||
#include "backend/thread-wrapper.hpp"
|
#include "backend/thread-wrapper.hpp"
|
||||||
|
|
@ -85,17 +85,18 @@ namespace gui {
|
||||||
/**************************************************************************//**
|
/**************************************************************************//**
|
||||||
* Implement the necessary steps for actually making the Lumiera Gui available.
|
* Implement the necessary steps for actually making the Lumiera Gui available.
|
||||||
* Open the business interface(s) and start up the GTK GUI main event loop.
|
* Open the business interface(s) 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 no
|
||||||
|
* open other interfaces here...) ///////////////////////////TICKET #82
|
||||||
*/
|
*/
|
||||||
struct GuiLifecycle
|
struct GuiLifecycle
|
||||||
{
|
{
|
||||||
string error_;
|
string error_;
|
||||||
Subsys::SigTerm& reportOnTermination_;
|
Subsys::SigTerm& reportOnTermination_;
|
||||||
NotificationService activateNotificationService_;
|
DisplayService activateDisplayService_; ///////////////////////////TICKET #82 will go away once we have a real OutputSlot offered by the UI
|
||||||
DisplayService activateDisplayService_;
|
|
||||||
|
|
||||||
GuiLifecycle (Subsys::SigTerm& terminationHandler)
|
GuiLifecycle (Subsys::SigTerm& terminationHandler)
|
||||||
: reportOnTermination_(terminationHandler)
|
: reportOnTermination_(terminationHandler)
|
||||||
, activateNotificationService_() // opens the GuiNotification facade interface
|
|
||||||
, activateDisplayService_() // opens the gui::Display facade interface
|
, activateDisplayService_() // opens the gui::Display facade interface
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,57 @@
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
</richcontent>
|
</richcontent>
|
||||||
|
<node CREATED="1481502320065" ID="ID_1298358905" MODIFIED="1481502325705" TEXT="macht bisher der GuiRunner">
|
||||||
|
<node CREATED="1481502327528" ID="ID_75293128" MODIFIED="1481502442640" TEXT="das ist ohnehin schlecht">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
...weil es dadurch passieren könnte,
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
daß die Konstruktion des GuiRunners schon scheitert, bevor der Rumpf des ctors aufgerufen wird.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In einem solchen Fall wird leider auch der Rumpf des dtors nicht aufgerufen, wodurch das
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Term-Signal nicht ausgesendet würde.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
<icon BUILTIN="idea"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1481502335583" ID="ID_1245191241" MODIFIED="1481502372882" TEXT="Felder im GuiRunner sollten noexcept sein">
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1481502305995" ID="ID_1943234904" MODIFIED="1481502317084" TEXT="in CoreService verschieben"/>
|
||||||
|
<node CREATED="1481502251450" ID="ID_1125529151" MODIFIED="1481502303814" TEXT="möglicher Race">
|
||||||
|
<icon BUILTIN="messagebox_warning"/>
|
||||||
|
</node>
|
||||||
|
<node CREATED="1481502257825" ID="ID_232782099" MODIFIED="1481502300621" TEXT="Gefahr gering">
|
||||||
|
<richcontent TYPE="NOTE"><html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
...weil unser Thread-Framework
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
tatsächlich <i>erzwingt,</i> daß der neue Thrad zu laufen beginnt, bevor die
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
startende Funktion zurückkehrt.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</richcontent>
|
||||||
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1481320772830" ID="ID_1607125695" MODIFIED="1481320786893">
|
<node CREATED="1481320772830" ID="ID_1607125695" MODIFIED="1481320786893">
|
||||||
<richcontent TYPE="NODE"><html>
|
<richcontent TYPE="NODE"><html>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue