1
0
mirror of https://git.code.sf.net/p/fuse-emulator/fuse synced 2026-01-27 01:41:34 +03:00
Files
fuse/infrastructure/startup_manager.c
Sergio Baldoví 09ed7068e7 Fix printf() conversion specifier
Array length is of type guint.
2018-06-27 22:49:04 +02:00

184 lines
4.8 KiB
C

/* startup_manager.c: handle Fuse's startup routines
Copyright (c) 2016 Philip Kendall
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author contact information:
E-mail: philip-fuse@shadowmagic.org.uk
*/
#include <config.h>
#ifdef HAVE_LIB_GLIB
#include <glib.h>
#endif /* #ifdef HAVE_LIB_GLIB */
#include <libspectrum.h>
#include "startup_manager.h"
#include "ui/ui.h"
typedef struct registered_module_t {
startup_manager_module module;
GArray *dependencies;
startup_manager_init_fn init_fn;
void *init_context;
startup_manager_end_fn end_fn;
} registered_module_t;
static GArray *registered_modules;
static GArray *end_functions;
void
startup_manager_init( void )
{
registered_modules =
g_array_new( FALSE, FALSE, sizeof( registered_module_t ) );
end_functions =
g_array_new( FALSE, FALSE, sizeof( startup_manager_end_fn ) );
}
void
startup_manager_end( void )
{
g_array_free( registered_modules, TRUE );
registered_modules = NULL;
g_array_free( end_functions, TRUE );
end_functions = NULL;
}
void
startup_manager_register(
startup_manager_module module, startup_manager_module *dependencies,
size_t dependency_count, startup_manager_init_fn init_fn,
void *init_context, startup_manager_end_fn end_fn )
{
registered_module_t registered_module;
registered_module.module = module;
registered_module.dependencies =
g_array_sized_new( FALSE, FALSE, sizeof( startup_manager_module ),
dependency_count );
g_array_append_vals( registered_module.dependencies, dependencies,
dependency_count );
registered_module.init_fn = init_fn;
registered_module.init_context = init_context;
registered_module.end_fn = end_fn;
g_array_append_val( registered_modules, registered_module );
}
void
startup_manager_register_no_dependencies(
startup_manager_module module, startup_manager_init_fn init_fn,
void *init_context, startup_manager_end_fn end_fn )
{
startup_manager_register( module, NULL, 0, init_fn, init_context, end_fn );
}
static void
remove_dependency( startup_manager_module module )
{
guint i, j;
for( i = 0; i < registered_modules->len; i++ ) {
registered_module_t *registered_module =
&g_array_index( registered_modules, registered_module_t, i );
GArray *dependencies = registered_module->dependencies;
for( j = 0; j < dependencies->len; j++ ) {
startup_manager_module dependency =
g_array_index( dependencies, startup_manager_module, j );
if( dependency == module ) {
g_array_remove_index_fast( dependencies, j );
break;
}
}
}
}
int
startup_manager_run( void )
{
int progress_made;
guint i;
int error;
/* Loop until we can't make any more progress; this will either be because
we've called every function (good!) or because there's a logical error
in the dependency graph (bad!) */
do {
i = 0;
progress_made = 0;
while( i < registered_modules->len ) {
registered_module_t *registered_module =
&g_array_index( registered_modules, registered_module_t, i );
if( registered_module->dependencies->len == 0 ) {
if( registered_module->init_fn ) {
error = registered_module->init_fn(
registered_module->init_context
);
if( error ) return error;
}
if( registered_module->end_fn )
g_array_append_val( end_functions, registered_module->end_fn );
remove_dependency( registered_module->module );
g_array_free( registered_module->dependencies, TRUE );
g_array_remove_index_fast( registered_modules, i );
progress_made = 1;
} else {
i++;
}
}
} while( progress_made && registered_modules->len );
/* If there are still any modules left to be called, then that's bad */
if( registered_modules->len ) {
ui_error( UI_ERROR_ERROR, "%u startup modules could not be called",
registered_modules->len );
return 1;
}
return 0;
}
void
startup_manager_run_end( void )
{
guint i;
for( i = end_functions->len; i-- != 0; )
{
startup_manager_end_fn end_fn =
g_array_index( end_functions, startup_manager_end_fn, i );
end_fn();
}
startup_manager_end();
}