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
|
||||
* 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
|
||||
* 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
|
||||
|
|
@ -77,7 +77,7 @@ namespace backend {
|
|||
* must join to prevent pulling away member variables the thread function will
|
||||
* 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.
|
||||
* Error states or caught exceptions can be propagated through the lumiera_error
|
||||
* 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
|
||||
* shutdown of the whole application.
|
||||
*
|
||||
* \par synchronisation barriers
|
||||
* # synchronisation barriers
|
||||
* Lumiera threads provide a low-level synchronisation mechanism, which is used
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -115,6 +115,14 @@ namespace gui {
|
|||
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
|
||||
triggerShutdown () noexcept override
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#include "lib/error.hpp"
|
||||
#include "include/logging.h"
|
||||
//#include "lib/idi/entry-id.hpp"
|
||||
#include "gui/notification-service.hpp"
|
||||
#include "gui/ctrl/bus-term.hpp"
|
||||
#include "gui/ctrl/nexus.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
|
@ -89,6 +90,7 @@ namespace ctrl{
|
|||
{
|
||||
|
||||
Nexus uiBusBackbone_;
|
||||
NotificationService activateNotificationService_;
|
||||
|
||||
virtual void
|
||||
act (GenNode const& command)
|
||||
|
|
@ -109,6 +111,7 @@ namespace ctrl{
|
|||
CoreService (ID identity =lib::idi::EntryID<CoreService>())
|
||||
: BusTerm(identity, uiBusBackbone_)
|
||||
, uiBusBackbone_{*this}
|
||||
, activateNotificationService_() // opens the GuiNotification facade interface
|
||||
{
|
||||
INFO (gui, "UI-Backbone operative.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,15 +30,16 @@
|
|||
** 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().
|
||||
**
|
||||
** After successfully loading this module, a call to #kickOff is expected to be
|
||||
** issued, passing a termination signal (callback) to be executed when the GUI
|
||||
** terminates. The \c kickOff() call remains blocked within the main GTK event loop;
|
||||
** thus typically this call should be issued within a separate dedicated GUI thread.
|
||||
** Especially, the gui::GuiRunner will ensure this to happen.
|
||||
** After successfully loading this module, a call to GuiFacade::launchUI is expected to
|
||||
** happen, passing a termination signal (callback) to be executed when the GUI terminates.
|
||||
** The implementation of GuiFacade in the GuiRunner in fact issues this call from the ctor
|
||||
** body, while the interface is opened via an InstanceHandle member. The `launchUI()` call
|
||||
** 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
|
||||
** especially the [UI-Bus](\ref ui-bus.hpp) is started see \ref GtkLumiera::run.
|
||||
** This entails also to open the primary "business" interface(s) of the GUI
|
||||
** (currently as of 1/16 this is the interface gui::GuiNotification.)
|
||||
**
|
||||
** Prior to entering the GTK event loop, all primary "business" interface of the GUI
|
||||
** will be opened (currently as of 1/09 this is the interface gui::GuiNotification.)
|
||||
**
|
||||
** @see lumiera::AppState
|
||||
** @see gui::GuiFacade
|
||||
** @see guifacade.cpp
|
||||
|
|
@ -54,7 +55,6 @@
|
|||
|
||||
#include "lib/error.hpp"
|
||||
#include "gui/guifacade.hpp"
|
||||
#include "gui/notification-service.hpp"
|
||||
#include "gui/display-service.hpp"
|
||||
#include "common/subsys.hpp"
|
||||
#include "backend/thread-wrapper.hpp"
|
||||
|
|
@ -85,17 +85,18 @@ namespace gui {
|
|||
/**************************************************************************//**
|
||||
* 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.
|
||||
* @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
|
||||
{
|
||||
string error_;
|
||||
Subsys::SigTerm& reportOnTermination_;
|
||||
NotificationService activateNotificationService_;
|
||||
DisplayService activateDisplayService_;
|
||||
DisplayService activateDisplayService_; ///////////////////////////TICKET #82 will go away once we have a real OutputSlot offered by the UI
|
||||
|
||||
GuiLifecycle (Subsys::SigTerm& terminationHandler)
|
||||
: reportOnTermination_(terminationHandler)
|
||||
, activateNotificationService_() // opens the GuiNotification facade interface
|
||||
, activateDisplayService_() // opens the gui::Display facade interface
|
||||
{ }
|
||||
|
||||
|
|
|
|||
|
|
@ -153,6 +153,57 @@
|
|||
</body>
|
||||
</html>
|
||||
</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 CREATED="1481320772830" ID="ID_1607125695" MODIFIED="1481320786893">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
|
|||
Loading…
Reference in a new issue