2007-08-14 08:14:21 +02:00
/*
2008-11-30 06:43:51 +01:00
AppState - application initialisation and behaviour
2007-08-14 08:14:21 +02:00
2008-03-10 04:25:03 +01:00
Copyright ( C ) Lumiera . org
2008-04-14 05:15:16 +02:00
2008 , Hermann Vosseler < Ichthyostega @ web . de >
2007-08-14 08:14:21 +02:00
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 0213 9 , USA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-12-02 04:53:30 +01:00
# include "include/error.hpp"
2008-11-30 07:56:00 +01:00
# include "include/lifecycle.h"
2008-11-30 06:43:51 +01:00
# include "lumiera/appstate.hpp"
# include "lib/lifecycleregistry.hpp"
2008-12-02 04:53:30 +01:00
extern " C " {
# include "lumiera/config_interface.h"
# include "lumiera/interface.h"
# include "lumiera/interfaceregistry.h"
# include "lumiera/plugin.h"
}
2007-08-17 00:36:07 +02:00
# include "common/util.hpp"
2008-12-02 07:49:24 +01:00
# include "include/configfacade.hpp" //////////TODO: temp hack to force configfacade.o to be linked in
2007-08-14 08:14:21 +02:00
2007-08-23 17:52:33 +02:00
2007-08-17 00:36:07 +02:00
using util : : isnil ;
2008-04-13 23:54:39 +02:00
using util : : cStr ;
2007-08-14 08:14:21 +02:00
2008-12-02 04:53:30 +01:00
2008-11-30 03:08:48 +01:00
namespace lumiera {
2007-08-14 08:14:21 +02:00
2008-11-30 06:43:51 +01:00
2008-04-14 05:15:16 +02:00
Symbol ON_BASIC_INIT ( " ON_BASIC_INIT " ) ;
Symbol ON_GLOBAL_INIT ( " ON_GLOBAL_INIT " ) ;
Symbol ON_GLOBAL_SHUTDOWN ( " ON_GLOBAL_SHUTDOWN " ) ;
2008-11-30 06:43:51 +01:00
2008-11-30 03:08:48 +01:00
/** perform initialisation triggered on first access.
2008-04-13 23:54:39 +02:00
* Will execute the ON_BASIC_INIT hook , but under typical
* circumstances this is a NOP , because when callbacks are
2008-11-30 06:43:51 +01:00
* added to this hook , the AppState singleton instance has
2008-04-13 23:54:39 +02:00
* already been created . For this reason , there is special
* treatment for the ON_BASIC_INIT in LifecycleHook : : add ,
2008-04-14 05:15:16 +02:00
* causing the provided callbacks to be fired immediately .
* ( btw , this is nothing to be worried of , because from
* client codes POV it just behaves like intended ) .
2007-08-14 08:14:21 +02:00
*/
2008-11-30 06:43:51 +01:00
AppState : : AppState ( )
2008-12-02 04:53:30 +01:00
: lifecycleHooks_ ( new LifecycleRegistry ) ,
parts_ ( 0 )
2007-08-26 19:14:39 +02:00
{
2008-04-13 23:54:39 +02:00
lifecycleHooks_ - > execute ( ON_BASIC_INIT ) ; // note in most cases a NOP
2007-08-26 19:14:39 +02:00
}
2007-08-14 08:14:21 +02:00
2008-11-30 06:43:51 +01:00
AppState : : ~ AppState ( ) { }
AppState &
AppState : : instance ( ) // Meyer's singleton
{
static scoped_ptr < AppState > theApp_ ( 0 ) ;
if ( ! theApp_ ) theApp_ . reset ( new AppState ( ) ) ;
return * theApp_ ;
}
2007-08-23 17:52:33 +02:00
2008-04-13 23:54:39 +02:00
void
2008-11-30 06:43:51 +01:00
AppState : : lifecycle ( Symbol event_label )
2008-04-13 23:54:39 +02:00
{
instance ( ) . lifecycleHooks_ - > execute ( event_label ) ;
}
2008-11-30 06:43:51 +01:00
2008-12-02 04:53:30 +01:00
// ==== implementation startup sequence for main() =======
struct SubsystemRunner
{
Option & opts_ ;
SubsystemRunner ( Option & opts )
: opts_ ( opts )
{ }
} ;
# define _THROW_IF \
if ( lumiera_error_peek ( ) ) \
throw error : : Fatal ( lumiera_error ( ) ) ;
2008-12-01 05:35:19 +01:00
void
2008-12-02 04:53:30 +01:00
AppState : : init ( Option & options )
2008-12-01 05:35:19 +01:00
{
2008-12-02 04:53:30 +01:00
TRACE ( lumiera , " initialising application core... " ) ;
lumiera_interfaceregistry_init ( ) ;
_THROW_IF
TODO ( " use a plugindb instead of loading all plugins at once " ) ;
lumiera_plugin_discover ( lumiera_plugin_load , lumiera_plugin_register ) ;
_THROW_IF
lumiera_config_interface_init ( ) ;
_THROW_IF
AppState : : lifecycle ( ON_GLOBAL_INIT ) ;
_THROW_IF
parts_ . reset ( new SubsystemRunner ( options ) ) ;
TRACE ( lumiera , " Lumiera core started successfully. " ) ;
2008-12-01 05:35:19 +01:00
}
void
AppState : : maybeStart ( lumiera : : Subsys & )
{
UNIMPLEMENTED ( " maybe register and activate the given subsystem " ) ;
}
2008-12-01 08:04:43 +01:00
typedef AppState : : ExitCode ExitCode ;
2008-12-01 05:35:19 +01:00
ExitCode
AppState : : maybeWait ( )
{
UNIMPLEMENTED ( " wait on termination and normal shutdown " ) ;
}
ExitCode
AppState : : abort ( lumiera : : Error & problem )
{
2008-12-02 07:49:24 +01:00
INFO ( operate , " Address of Config Facade = %x " , & lumiera : : Config : : instance ( ) ) ; //////////TODO: a temp hack to force configfacade.cpp to be linked into lumiera.exe
2008-12-01 05:35:19 +01:00
UNIMPLEMENTED ( " clean error shutdown " ) ;
}
ExitCode
AppState : : abort ( )
{
UNIMPLEMENTED ( " emergency shutdown " ) ;
}
2008-11-30 06:43:51 +01:00
2008-04-13 23:54:39 +02:00
// ==== implementation LifecycleHook class =======
typedef LifecycleRegistry : : Hook Callback ;
LifecycleHook : : LifecycleHook ( Symbol eventLabel , Callback callbackFun )
{
2008-11-30 07:56:00 +01:00
add ( eventLabel , callbackFun ) ;
2008-04-13 23:54:39 +02:00
}
2008-11-30 07:56:00 +01:00
void
2008-04-13 23:54:39 +02:00
LifecycleHook : : add ( Symbol eventLabel , Callback callbackFun )
{
2008-11-30 06:43:51 +01:00
bool isNew = AppState : : instance ( ) . lifecycleHooks_ - > enroll ( eventLabel , callbackFun ) ;
2008-04-13 23:54:39 +02:00
2008-04-14 05:15:16 +02:00
if ( isNew & & ! strcmp ( ON_BASIC_INIT , eventLabel ) )
2008-04-13 23:54:39 +02:00
callbackFun ( ) ; // when this code executes,
// then per definition we are already post "basic init"
2008-11-30 06:43:51 +01:00
// (which happens in the AppState ctor); thus fire it immediately
2008-11-30 07:56:00 +01:00
}
void
trigger ( Symbol eventLabel )
{
AppState : : lifecycle ( eventLabel ) ;
2008-04-13 23:54:39 +02:00
}
2008-03-10 06:09:44 +01:00
} // namespace lumiera
2008-04-13 23:54:39 +02:00
2008-11-30 06:43:51 +01:00
extern " C " { /* ==== implementation C interface for lifecycle hooks ======= */
extern const char * lumiera_ON_BASIC_INIT = lumiera : : ON_BASIC_INIT ;
extern const char * lumiera_ON_GLOBAL_INIT = lumiera : : ON_GLOBAL_INIT ;
extern const char * lumiera_ON_GLOBAL_SHUTDOWN = lumiera : : ON_GLOBAL_SHUTDOWN ;
void
lumiera_LifecycleHook_add ( const char * eventLabel , void callbackFun ( void ) )
{
lumiera : : LifecycleHook ( eventLabel , callbackFun ) ;
}
void
lumiera_Lifecycle_trigger ( const char * eventLabel )
{
lumiera : : AppState : : lifecycle ( eventLabel ) ;
}
2008-04-13 23:54:39 +02:00
}