154 lines
9.4 KiB
Text
154 lines
9.4 KiB
Text
|
|
Lumiera: Startup and Shutdown of Subsystems
|
|
===========================================
|
|
|
|
There is now sort-of an "application realm", which doesn't belong strictly to
|
|
one of the Layers. It serves the purpose of pullig up and tearing down the
|
|
application in a controlled fashion. And additionally, it provides the Interface
|
|
and Config core services. Within the application, we find a small number of
|
|
_Subsystems_, which are more or less independent. These subsystems are
|
|
conceptual entities and don't correspond 1:1 to a layer, an interface, a class
|
|
or a plugin. These subsystems are _of no relevance_ outside the mentioned
|
|
"application realm". When the application is in normal operational mode, we have
|
|
the usual components, interfaces, services, aggregated into the three Layers.
|
|
|
|
__Currently I've identified the following subsystems:__
|
|
|
|
- Engine
|
|
- Builder
|
|
- Session
|
|
- Lumiera GUI
|
|
- Script runner
|
|
- Renderfarm node server
|
|
|
|
To deal with those subsystems, I've created an Interface to definesthe
|
|
operations and liabilities of a subsystem. Additionally, I assume that for each
|
|
subsystem there is a _Facade_, which the subsystem is free to implement as it
|
|
sees fit. Typically, this facade will load plugins, register and provide further
|
|
"business interfaces", and especially set up the _Layer separation interfaces_
|
|
which canalise any communication going on between the layers.
|
|
|
|
The code from my "startup" branch has meanwhile been merged to master. Look
|
|
http://git.lumiera.org/gitweb?p=LUMIERA;a=tree;h=a0a0e456a5b149df81b25a08358cd488631639fb;hb=a0a0e456a5b149df81b25a08358cd488631639fb[here]
|
|
for the code mentioned in the following discussion.
|
|
|
|
- +common/subsys.hpp+ contains the mentioned subsystem interface.
|
|
- +lumiera/main.cpp+ uses the subsystem instances provided by the facades, and
|
|
additionally the services of +lumiera::AppState+ (+common/appstate.hpp+)
|
|
- AppState represents the state as relevant for the "application realm", i.e.
|
|
it performs global initialisation and shutdown. See especially +AppState::init()+
|
|
- see +backend/enginefacade.hpp|cpp+ as an (unimplemented) facade skeleton. +backend::EngineFacade::getDescriptor()+
|
|
yields the subsytem interface
|
|
- the GuiFacade is somewhat special, because we want to load the GUI from a
|
|
shared libary. This facade is basically completed and working, but it currently
|
|
just loads a dummy plugin. The implementation of the GuiFacade needs to be in
|
|
core (because it pulls the plugin); that's why I've put it into
|
|
+common/guifacade.cpp+, while the interface is in +gui/guifacade.hpp+ as usual.
|
|
- as an example for a _Layer separation interface_, I've implemented the
|
|
GuiNotificationFacade, which will be used by the lower layers to push
|
|
informations into the gui (and finally to request the GUI to shut down). Layer
|
|
separation interfaces are considered part of the public Lumiera API, thus the
|
|
headers go into +src/include/**+
|
|
* include/guinotification.h (C/C++ combined header) defines an C++ interface (abstract class) and a CLI interface.
|
|
* embedded into the interface is a factory, i.e. by gui::GuiNotification::facade() you get an instance...
|
|
* which actually is a proxy and routes any call through the instance of the
|
|
accompaning CLI interface which is defined within the interface/plugin system
|
|
* this in turn forwards to the implementation class in
|
|
gui/guinotificationfacade.cpp, which is assumed to live within the GUI
|
|
(shared lib)
|
|
|
|
|
|
Parallelism
|
|
-----------
|
|
Actually this system builds on the assumption, that starting each subsystem
|
|
doesn't block the overall start/main/stop thread. I.e. any subsystem is supposed
|
|
to spawn its control/event threads if necessary. Not every subsystem needs to
|
|
spawn threads though (for example, the session doesn't). In the current
|
|
implementation *no spawning of threads happens*. Similarily, I've commented out
|
|
the synchronisation primitives.
|
|
|
|
|
|
Initialisation and Lifecycle
|
|
----------------------------
|
|
Basically, everything workes as discussed last spring in the
|
|
link:{ldoc}/devel/rfc/GlobalInitialization.html[GlobalInitialisation]
|
|
design entry. I've considered to switch to simple functions +pre_init(), init(),
|
|
...+ as proposed by Cehteh, but I'm not happy with this idea, because it creates
|
|
a coupling between anything which needs to be done in a certain initialisation
|
|
function. Actually, I prefer the usual approach of lifecycle events (or signals)
|
|
used in many application frameworks, i.e. the publisher-subscriber model. This
|
|
allows to keep the registration immediately within the implementation of a
|
|
facility, and it allows to add an arbitrary numer of additional lifecycle
|
|
events, like *ON_SESSION_CLOSE*, *ON_BUILD*, *ON_EMERGENCY_EXIT*.
|
|
|
|
Basically we've now the following steps and events happening
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
* *ON_BASIC_INIT* runs "somewhere" in the static initialisation phase before
|
|
main(). To schedule something there, you need to place a statc C++ variable.
|
|
This should be reseverd for very basic initialisation tasks which need to be
|
|
done even prior to any global initialisiation, e.g. the NOBUG_INIT is done this
|
|
way, the config system, maybe setting up a dispatcher table based on (compile
|
|
time) type information (for the rules engine).
|
|
* +AppState::init()+ cares for bringing up the pluginloader and opens the config-interface.
|
|
* ...followed by triggereing *ON_GLOBAL_INIT*
|
|
* +main()+ pulls up the subsystems according to the command line options.
|
|
* within each subsystem, facade interfaces shall be opened with the interface
|
|
system. Any initialisation of components should be tied to them.
|
|
* as a rule and if possible, _any service should be written such as to come up on demand._
|
|
* shutdown or failure of _any given subsystem_ initiates the shutdown sequence
|
|
by requesting all other running subsystems to terminate
|
|
* there is an *ON_GLOBAL_SHUTDOWN* event, which can be used for normal cleanup.
|
|
In case of an emergency exit, this hook may be skipped
|
|
* alternatively, the *ON_EMERGENCY_EXIT* event is triggered. In case of nested
|
|
exceptions, this may happen twice.
|
|
* the AppState destructor tries to bring down the core systems (config-interface and pluginloader).
|
|
|
|
|
|
Demo Run
|
|
--------
|
|
* building with scons (default target) now yields a bin/guistart.so, besides the bin/lumiera exe the scons built created since day one.
|
|
* we need to set the LUMIERA_PLUGIN_PATH from the commandline to point to this bin directory, e.g.
|
|
* +++LUMIERA_PLUGIN_PATH=/home/hiv/devel/lumi/.libs NOBUG_LOG='test:TRACE,lumiera:TRACE,config:TRACE' bin/lumiera 2>&1 | egrep -v '(TODO)|(FIXME)'+++
|
|
------
|
|
00000392: configfacade.cpp:74: INFO: thread_1: Config: Config system ready.
|
|
00000394: main.cpp:55: NOTICE: thread_1: main: *** Lumiera NLE for Linux ***
|
|
00000395: appstate.cpp:114: TRACE: thread_1: init: initialising application core...
|
|
00000405: interface.c:54: TRACE: thread_1: lumiera_interface_open: lumieraorg_interface
|
|
00000406: interface.c:55: WARNING: thread_1: lumiera_interface_open: opening experimental interface: lumieraorg_interface_0_lumieraorg_interface
|
|
00000412: interface.c:168: TRACE: thread_1: lumiera_interface_open_interfacenode: lumieraorg_interface 0 ()
|
|
00000437: config.c:199: NOTICE: thread_1: lumiera_config_get: envvar override for config LUMIERA_PLUGIN_PATH = /home/hiv/devel/lumi/
|
|
00000444: config.c:199: NOTICE: thread_1: lumiera_config_get: envvar override for config LUMIERA_PLUGIN_PATH = /home/hiv/devel/lumi/
|
|
00000467: appstate.cpp:132: TRACE: thread_1: init: Lumiera core started successfully.
|
|
00000469: appstate.cpp:140: TRACE: thread_1: maybeStart: maybe startup Builder...?
|
|
00000472: appstate.cpp:140: TRACE: thread_1: maybeStart: maybe startup Renderfarm node...?
|
|
00000475: appstate.cpp:140: TRACE: thread_1: maybeStart: maybe startup Lumiera GTK GUI...?
|
|
00000476: subsystemrunner.hpp:144: INFO: thread_1: triggerStartup: Starting subsystem "Lumiera GTK GUI"
|
|
00000477: interface.c:54: TRACE: thread_1: lumiera_interface_open: lumieraorg_GuiStarterPlugin
|
|
00000483: interface.c:168: TRACE: thread_1: lumiera_interface_open_interfacenode: lumieraorg_GuiStarterPlugin 0 ()
|
|
*** Ha Ha Ha
|
|
this is the GuiStarterPlugin speaking!
|
|
now, the Lumiera GUI should be spawned....
|
|
but actually nothing happens!!!!!!!!!!!!!!
|
|
00000491: appstate.cpp:140: TRACE: thread_1: maybeStart: maybe startup Script runner...?
|
|
00000494: appstate.cpp:171: NOTICE: thread_1: maybeWait: Shutting down Lumiera...
|
|
00000495: interface.c:230: TRACE: thread_1: lumiera_interface_close:
|
|
00000498: interface.c:258: TRACE: thread_1: lumiera_interfacenode_close: lumieraorg_GuiStarterPlugin 1 ()
|
|
00000634: configfacade.cpp:83: TRACE: thread_1: ~Config: config system closed.
|
|
00000635: appstate.cpp:245: TRACE: thread_1: ~AppState: shutting down basic application layer...
|
|
00000643: interface.c:230: TRACE: thread_1: lumiera_interface_close:
|
|
00000646: interface.c:258: TRACE: thread_1: lumiera_interfacenode_close: lumieraorg_interface 1 ()
|
|
------
|
|
* similarily, running... `lumiera \--help`
|
|
------
|
|
00000392: configfacade.cpp:74: INFO: thread_1: Config: Config system ready.
|
|
00000394: main.cpp:55: NOTICE: thread_1: main: *** Lumiera NLE for Linux ***
|
|
Lumiera, the non linear video editor. Supported parameters:
|
|
-h [ --help ] produce help message
|
|
-f [ --session ] arg session file to load (UNIMPLEMENTED)
|
|
-s [ --script ] arg execute the given LUA script (UNIMPLEMENTED)
|
|
--headless start without GUI
|
|
-p [ --port ] arg open renderfarm node at given port (UNIMPLEMENTED)
|
|
-d [ --define ] arg enter definition into config system (UNIMPLEMENTED)
|
|
------
|
|
|