From 7e015f9a7fc1c69bf7768410997d0b7bacd0d45d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 23 Feb 2020 22:45:20 +0100 Subject: [PATCH] DOC: detailed start-up sequence of the GUI (closes #1145) This changeset documents the current known state of UI startup into the TiddlyWiki. It summarises all information and notes from various places in my mindmap. Fazit: * largely, the startup sequence is sane * there are some open gaps and possible races -> see #1192 * these are rather hard to fix; maybe it's preferrable to rewrite the subsystem runner #1177 --- wiki/renderengine.html | 58 ++++++++++++-- wiki/thinkPad.ichthyo.mm | 165 +++++++++++++++++++++++++++------------ 2 files changed, 167 insertions(+), 56 deletions(-) diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 6b08d22e6..7625c74b3 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -3485,17 +3485,59 @@ The foundation of population and display of pop-up menues is provided by GTK -- {{red{OMG 11/2018 -- I have no idea where to start here...}}} -
+
Starting up the GUI is optional and is considered part of the Application start/stop and lifecycle.
 * main and {{{lumiera::AppState}}} activate the lifecyle methods on the ~GuiSubsysDescriptor, accessible via the GuiFacade
-* loading a GuiStarterPlugin actually
+** invocation of {{{GuiFacade::start}}}
+** creates {{{unique_ptr<GuiRunner>}}}
+** the ~GuiRunner holds a ~GuiHandle as member, which causes loading and activation of the plug-in
+* loading the {{{gtk_gui.lum}}} plug-in...
 ** loads the GUI (shared lib)
-** creates instances of all the GUI services available through LayerSeparationInterfaces
-*** GuiNotificationFacade
-*** DisplayFacade
-** Finally, the ~GTK-main() is invoked.
-* bring up a network of framework entities known als the GuiTopLevel
-* establish a connection to allow the GUI to be [[populated with content|GuiContentPopulation]]
+** after loading, the sole interface method {{{launchUI()}}} is triggered
+* the GUI plug-in implementation in {{{gtk-lumiera.cpp}}}
+** implements the GUI plug-in interface
+** and the~launchUI-Function ''spawns the GUI thread''.
+* the ~GuiThread ({{{runGUI()}}})...
+** creates the {{{GtkLumiera}}} object, which is the "GUI main"
+** invokes the {{{GtkLumiera::run()}}} function (guarded with appropriate error handlers) &rarr; {{{sigTerm}}} at the end
+*** this first creates the ''~GUI-Backbone''
+**** {{red{TODO 2/2020: unexpected error in ctor might kill the GUI thread, possibly leading to deadlock #1192}}}
+***;~UiBus
+***:the UI-Bus is the communication backbone and hub
+***;~UiManager
+***:responsible for wiring a cohesive GuiTopLevel
+***:*wired with the UI-Bus
+***:*populates the Menu and binds the Actions
+***:*populates the {{{GlobalCtx}}} with...
+***:**{{{UiBus}}}
+***:** {{{UiManager}}}
+***:** {{{WindowLocator}}}
+***:** {{{InteractionDirector}}}
+***:** {{{interact::Wizard}}}
+***;~InteractionDirector
+***:the InteractionDirector acts as top-level controller within the UI -- corresponding to the root context in the session
+***;Application Windows (GTK)
+***:a hierarchy of GTK widgets to implement the actual user interface
+***;Event Loop
+***:this is what makes the UI "live" and responsive
+** activating the Event Loop through {{{UiManager.performMainLoop()}}}
+*** first installs and opens the primary LayerSeparationInterfaces
+**** GuiNotificationFacade (for pushing messages via UI-Bus)
+**** DisplayService (to display rendered content)
+*** then activates the {{{Gio::Application}}} main loop (blocking event loop)
+** establishing the UI-Bus
+*** creates the ''Core Service'' as node attached to the bus<br/>this in turn holds...
+***:the Nexus
+***;this is the communication Hub, and actually every "uplink" into the Bus-term eventually ends here
+***:State Manager
+***;special service to handle "state mark" messages on the bus
+***;this is what essentially creates persistent interface state
+** the InteractionDirector immediately launches a ~Callback-Action into the ~Event-Loop
+*** which, when performed, sends a "population request" command down to the session
+*** the session will response asynchronously by pushing a "population diff" up into the UI-Bus (via Notification façade)
+
+!!!questions of sanity and locking
+The initial start-function of the subsystem is protected by a locking guard. Thus, everything up to and including the launch of the GUI thread is "make it or break it". If the {{{facade}}} smart-ptr is not set, the GUI is considered as not started. Likewise, everything //within the GUI thread// is protected by a top-level error handler, which invokes the termination signal and thus causes application shutdown, whenever the thread exits. There is only one tiny gap in this reasoning: when the overall application shuts down //after// the GUI has been launched, but //before// the GUI was able to open the Notification façade, the GUI will miss the shutdown notification and thus the application will hang with defunct core, but with running and responsive UI. However, the Lumiera thread handling framework implements a dedicated barrier to ensure the started thread has picked up its arguments and is about to enter the thread operation function. This means, the tread launching the GUI thread will block for a short period, and when the thread launching function returns (successfully), we can sure the spawned thread is running and at the begin of its payload function. Now, since opening the facade interfaces happens early in this GUI function, and prior to building up all the GTK widgets, the chances for such a race actually happening are rather remote.
 
 !public services
 The GUI provides a small number of public services, callable through LayerSeparationInterfaces. Besides that, the main purpose of the GUI of course is user interaction. Effectively the behaviour of the whole system is driven by GUI events to a large extent. These events are executed within the event handling thread (~GTK-main-Thread) and may in turn invoke services of the lower layers, again through the respective LayerSeparationInterfaces.
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index ef7fddfb9..5769147db 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -1,7 +1,8 @@
 
 
-
+
 
+
 
 
 
@@ -59,24 +60,26 @@
 
 
 
-
-
+
+
 
 
 
-
+
 
   
     
   
   
     

- TODO: Infos zusammentragen und dokumentieren + TODO: Infos zusammentragen und dokumentieren

-
+ + +
- + @@ -403,7 +406,7 @@ - + @@ -418,12 +421,22 @@ - + + + + + + + + + + + @@ -503,7 +516,7 @@ - + @@ -581,7 +594,7 @@ - + @@ -628,6 +641,22 @@ + + + + + + + + + + + + + + + + @@ -1071,9 +1100,9 @@ - + - + @@ -4155,7 +4184,7 @@ - + @@ -4266,8 +4295,8 @@ - - + + @@ -4388,7 +4417,7 @@ - + @@ -4499,9 +4528,9 @@ - + - + @@ -4584,7 +4613,7 @@ - + @@ -4795,8 +4824,9 @@ - + + @@ -4911,8 +4941,10 @@ - + + + @@ -4948,7 +4980,7 @@ - + @@ -4959,20 +4991,26 @@

- + + + + + - + +

- vertagt; Ticket #1058 + letztlich verworfen; siehe Ticket #1058

-
- + +
+
@@ -5045,7 +5083,7 @@
- + @@ -5075,7 +5113,7 @@ - + @@ -6101,8 +6139,8 @@ - - + + @@ -19104,9 +19142,13 @@ - + + + + + @@ -21960,6 +22002,10 @@ + + + + @@ -27302,9 +27348,9 @@ - + - + @@ -27427,10 +27473,29 @@ - + + + + + + + +
    +
  • + InteractionDirector::populateContent_afterStart() +
  • +
  • + meta-cmd.cpp +
  • +
+ + +
+ +
@@ -31618,8 +31683,7 @@ »Tangible« : Basis

- - + @@ -32434,8 +32498,8 @@ - - + + @@ -33429,7 +33493,7 @@ - + @@ -41445,8 +41509,7 @@ es ist wohl nicht ein spezieller Diff. Es tritt sogar auf, wenn man zweimal den gleichen Diff schickt

- - +
@@ -44620,8 +44683,8 @@ - - + + @@ -44631,6 +44694,9 @@ + + + @@ -54277,7 +54343,7 @@ - + @@ -54291,8 +54357,11 @@ - - + + + + +