src/{fsm,widget}/*, include/fsm.h: reworked logging memory management and encapsulated calls

This commit fixes issues with memory management in the logging code of the FSM. It also
optimizes operations by restricting char* pointers, allowing the compiler knowing that they
do not overlap. Finally, it encapsulates calls to fsm_add_log in a macro that allows to
automatically get file and function names.

Signed-off-by: Adrien 'neox' Bourmault <neox@a-lec.org>
This commit is contained in:
Adrien Bourmault 2024-11-22 17:07:22 +01:00
parent 502fc8939f
commit 30f844370c
8 changed files with 75 additions and 86 deletions

View file

@ -176,10 +176,10 @@ enum fsm_enum_log_source {
//-----------------------------------------------------------------------------
#define FILE_SOURCE_NAME_SIZE 40
#define FUNCTION_SOURCE_NAME_SIZE 40
#define STRING_VALUE_SIZE 60
#define LOG_MAX_LENGTH 255 /**< arbitrary */
#define FUNCTION_SOURCE_NAME_SIZE 30
#define STRING_VALUE_SIZE 50
#define LOG_MAX_LENGTH \
FILE_SOURCE_NAME_SIZE+FUNCTION_SOURCE_NAME_SIZE+STRING_VALUE_SIZE
/**
* A log unit must include the followings:
@ -190,9 +190,9 @@ struct fsm_log_unit_t
{
long yy_dd_mm; /**< * date of the event reported in the log */
long usec; /**< * with microseconds precision */
char *file_source; /**< * emitter file */
char *function_source; /**< * emitter function */
char *string_value; /**< * any event descriptors */
char *restrict file_source; /**< * emitter file */
char *restrict function_source; /**< * emitter function */
char *restrict string_value; /**< * any event descriptors */
struct fsm_log_unit_t *prev; /**< * chained list */
struct fsm_log_unit_t *next; /**< * chained list */
};
@ -226,26 +226,25 @@ void fsm_clear_log (struct fsm_log_t *);
void fsm_clear_log_unit(struct fsm_log_unit_t *);
void fsm_add_log_event (struct fsm_log_t *gg_logs,
const char *file_source,
const char *function_source,
const char *string_value);
const char *restrict file_source,
const char *restrict function_source,
const char *restrict string_value);
int fsm_get_log_length(struct fsm_log_t *);
void fsm_seek_log (struct fsm_log_t *gg_logs,
long usec,
char *file_source,
char *function_source,
char *string_value);
long fsm_remove_log (struct fsm_log_t *gg_logs,
char *file_source,
char *function_source,
char *string_value);
const char *restrict file_source,
const char *restrict function_source,
const char *restrict string_value);
long fsm_remove_log (struct fsm_log_t *);
void fsm_add_log (int severity,
int source,
const char *file_source,
const char *function_source,
const char *string_value);
const char *restrict file_source,
const char *restrict function_source,
const char *restrict string_value);
#define FSM_ADD_LOG(severity,string_value) \
fsm_add_log(severity,__FILE__,__func__,string_value)
void fsm_relay_init_log();
void fsm_relay_close_log();

View file

@ -144,12 +144,12 @@ void fsm_init()
{
fsm_relay_init_log();
fsm_add_log (INFO, MAIN, "fsm/control", __func__,
FSM_ADD_LOG (INFO,
"👋️ (☕️) Hi everybody ! Here is Gem-Graph.");
fsm_add_log (INFO, FSM, "fsm/control", __func__, "has began ✍️");
FSM_ADD_LOG (INFO, "has began ✍️");
fsm_structures_init();
fsm_add_log (INFO, FSM, "fsm/control", __func__, "has ended 😇️");
FSM_ADD_LOG (INFO, "has ended 😇️");
}
/**
@ -183,11 +183,11 @@ void fsm_init()
*/
void fsm_close()
{
fsm_add_log (INFO, FSM, "fsm/control", __func__, "has began");
FSM_ADD_LOG (INFO, "has began");
fsm_structures_close();
fsm_add_log (INFO, FSM, "fsm/control", __func__, "has ended");
FSM_ADD_LOG (INFO, "has ended");
fsm_add_log (INFO, MAIN, "fsm/control", __func__,
FSM_ADD_LOG (INFO,
"👋️😄️ That'all folks !");
fsm_relay_close_log(); /**< fsm_clear_log(() can't be called from here

View file

@ -46,10 +46,7 @@
*
* @returns the removed event date microseconds
*/
long fsm_remove_log (struct fsm_log_t *gg_logs,
char *file_source,
char *function_source,
char *string_value)
long fsm_remove_log (struct fsm_log_t *gg_logs)
{
// save latest log ref in tmp
struct fsm_log_unit_t *tmp = gg_logs->latest;
@ -97,6 +94,8 @@ int fsm_get_log_length (struct fsm_log_t *gg_logs)
/**
* Seek for an event
*
* XXX absolutely does not work as expected (does not seek anything in fact).
*
* @since 2024-09
*
* @param *gg_logs
@ -107,9 +106,9 @@ int fsm_get_log_length (struct fsm_log_t *gg_logs)
*/
void fsm_seek_log (struct fsm_log_t *gg_logs,
long usec,
char *file_source,
char *function_source,
char *string_value)
const char *restrict file_source,
const char *restrict function_source,
const char *restrict string_value)
{
struct fsm_log_unit_t *a_unit = gg_logs->oldest;
int nb = 0;

View file

@ -93,16 +93,13 @@ static struct fsm_log_t gg_logs = { 0 };
* @see fsm_enum_log_source
*/
void fsm_add_log (int severity,
int source,
const char *file_source,
const char *function_source,
const char *string_value)
const char *restrict file_source,
const char *restrict function_source,
const char *restrict string_value)
{
if
(
severity < TRACE
// && source == RULE_CONDITION
)
if (severity > TRACE)
return;
fsm_add_log_event (&gg_logs, file_source, function_source, string_value);
}

View file

@ -101,9 +101,8 @@ void fsm_clear_log_unit (struct fsm_log_unit_t *unit)
/**
* Adds a log unit (an event) to the log list.
*
* new_unit = malloc (sizeof (fsm_log_unit_struct));
*
* warn: is never free (as new log units are never removed)
* The `restrict` keyword tells the compiler that pointers do not overlap in
* memory, enabling optimizations like vectorization.
*
* @since 2024-09
*
@ -112,27 +111,29 @@ void fsm_clear_log_unit (struct fsm_log_unit_t *unit)
* @param *function_source
* @param *string_value
*/
void fsm_add_log_event (struct fsm_log_t *gg_logs,
const char *file_source,
const char *function_source,
const char *string_value)
void fsm_add_log_event (struct fsm_log_t *restrict gg_logs,
const char *restrict file_source,
const char *restrict function_source,
const char *restrict string_value)
{
struct timeval tv;
gettimeofday (&tv, NULL);
struct fsm_log_unit_t *new_unit = g_malloc0 (sizeof(struct fsm_log_unit_t));
if (! new_unit) exit (EXIT_FAILURE);
if (new_unit == NULL)
g_error("Failed to allocate new_unit");
new_unit->yy_dd_mm = tv.tv_sec;
new_unit->usec = tv.tv_usec;
new_unit->file_source = malloc(FILE_SOURCE_NAME_SIZE * sizeof(char));
new_unit->function_source = malloc(FUNCTION_SOURCE_NAME_SIZE * sizeof(char));
new_unit->string_value = malloc(STRING_VALUE_SIZE * sizeof(char));
new_unit->file_source = g_malloc0 (1 + FILE_SOURCE_NAME_SIZE * sizeof(char));
new_unit->function_source = g_malloc0 (1 + FUNCTION_SOURCE_NAME_SIZE * sizeof(char));
new_unit->string_value = g_malloc0 (1 + STRING_VALUE_SIZE * sizeof(char));
strncpy (new_unit->file_source, file_source, FILE_SOURCE_NAME_SIZE - 1);
strncpy (new_unit->function_source, function_source, FUNCTION_SOURCE_NAME_SIZE - 1);
strncpy (new_unit->string_value, string_value, STRING_VALUE_SIZE - 1);
strncpy (new_unit->file_source, file_source, FILE_SOURCE_NAME_SIZE);
strncpy (new_unit->function_source, function_source, FUNCTION_SOURCE_NAME_SIZE);
strncpy (new_unit->string_value, string_value, STRING_VALUE_SIZE);
/** first time we log something (don't touch new_unit->prev) */
if (gg_logs->oldest == NULL)
@ -163,12 +164,16 @@ void fsm_publish_log (struct fsm_log_t *gg_logs)
struct fsm_log_unit_t *a_unit = gg_logs->oldest;
char *timestamp = g_malloc0 (LOG_MAX_LENGTH * sizeof(char));
int nb = 0;
if (timestamp == NULL)
g_error("Failed to allocate timestamp");
while (a_unit)
{
strftime(timestamp, LOG_MAX_LENGTH * sizeof(char),
"%D %T", localtime(&a_unit->yy_dd_mm));
g_message ("%s + %-6ld %6d %-28s %-32s %-60s",
g_message ("%s + %-6ld %6d %-40s %-30s %-50s",
timestamp,
a_unit->usec,
nb,

View file

@ -65,14 +65,12 @@ int main (int argc, char **argv)
fsm_init();
fsm_add_log (INFO, MAIN, __func__,
"*app = gtk_application_new()",
FSM_ADD_LOG (INFO,
"| 👉️ trigger app initialization");
app = gtk_application_new ("org.gem-graph", G_APPLICATION_DEFAULT_FLAGS);
fsm_add_log (INFO, MAIN, __func__,
"g signal connect (activate)",
FSM_ADD_LOG (INFO,
"| 👉️ windows creation requested");
// g_signal_connect (app, "startup", G_CALLBACK (on_windows_startup), NULL);
@ -80,7 +78,8 @@ int main (int argc, char **argv)
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
fsm_add_log (INFO, MAIN, __func__, "g_object unref (app)", "| 👌️ bye bye app !");
FSM_ADD_LOG (INFO,
"| 👌️ bye bye app !");
fsm_close();

View file

@ -41,7 +41,7 @@
*/
void on_toggle_exec_edit (GtkWidget *toggled_button, gpointer user_data)
{
fsm_add_log (INFO, BUTTON, "signal", __func__,
FSM_ADD_LOG (INFO,
"flip status request + bell 😇️ gdk_display_beep()");
gdk_display_beep (gdk_display_get_default());
@ -59,8 +59,7 @@ void widget_design_main_window (GtkWindow *main_window, GtkApplication *app)
gpointer no_local_data = NULL;
fsm_add_log (INFO, HEADER_BAR_LEFT, "widget/main_window/design",
__func__, "start of design");
FSM_ADD_LOG (INFO, "start of design");
char *title = "E coli (with permission from David S. Goodsell, 2009)";
gtk_header_bar_set_title_widget (GTK_HEADER_BAR (header_bar),
@ -83,6 +82,5 @@ void widget_design_main_window (GtkWindow *main_window, GtkApplication *app)
// g_object_unref (e_coli);
fsm_add_log (INFO, HEADER_BAR_LEFT, "widget/main_window/design",
__func__, "end of design -> present");
FSM_ADD_LOG (INFO, "end of design -> present");
}

View file

@ -58,7 +58,7 @@ static GtkWindow *window;
*/
void on_app_activation (GtkApplication *app)
{
fsm_add_log (INFO, WIDGETS, "widget/manager", __func__, "has began");
FSM_ADD_LOG (INFO, "has began");
// on_windows_activation() is in: widget/manager NOT in: src/signal
// g_application_activate (G_APPLICATION (app)); < how ? > in main is
@ -73,29 +73,23 @@ void on_app_activation (GtkApplication *app)
//g_object_ref_sink(widget); // remove floating reference, and own this object ourselves
//g_object_unref(widget);
//gtk_widget_destroy(widget);
window = GTK_WINDOW (gtk_application_window_new (app));
int window_int_id = gtk_application_window_get_id (GTK_APPLICATION_WINDOW (window));
char window_char_id[40];
sprintf(window_char_id, "%d", window_int_id);
char msg[STRING_VALUE_SIZE+1] = { 0 };
g_signal_connect(window, "close-request", G_CALLBACK (on_window_close_request), (void *)(long long)window_int_id);
snprintf(msg, STRING_VALUE_SIZE, "window_get_id = %d", window_int_id);
FSM_ADD_LOG (INFO, msg);
int destination_string_size = 50 * sizeof(char);
char *temp = g_malloc0 (destination_string_size);
temp = strncat (temp, "window_get_id = ", destination_string_size);
temp = strncat (temp, window_char_id, destination_string_size);
fsm_add_log (INFO, WIDGETS, "widget/manager", __func__, temp);
free(temp);
// Handling window close and passing window id as argument
g_signal_connect(window, "close-request",
G_CALLBACK (on_window_close_request),
(void *)(long long)window_int_id);
widget_design_main_window (window, app);
gtk_window_present (GTK_WINDOW (window));
// g_object_unref (main_window); TODO get the closing signal of the main window
// ------------------------------------------------------------------------
// For the breakdown between pages, see signal > switch_state_rules_data()
@ -117,15 +111,13 @@ void on_app_activation (GtkApplication *app)
g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_b));
g_signal_connect (act_b, "activate", G_CALLBACK (action_b), app2);*/
fsm_add_log (INFO, WIDGETS, "widget/manager", __func__,
"has ended 🧐️ | 👉️ a new session starts");
FSM_ADD_LOG (INFO, "has ended 🧐️ | 👉️ a new session starts");
}
gboolean on_window_close_request (GtkWindow *window, gpointer user_data)
{
fsm_add_log (INFO, WIDGETS, "widget/manager", __func__,
"freeing all ressources !");
FSM_ADD_LOG (INFO, "freeing all ressources !");
// free the only child
gtk_window_set_child (window, NULL); // deleting the child from window