Free up memory used by GtkSatMap

The map and satellite object data were leaking on destruction of
GtkSatMap. This happens every time the enclosing module is configured.
This commit is contained in:
Tim Brooks 2020-05-24 22:45:10 +01:00 committed by Alexandru Csete
parent c3ab2f7d04
commit fc63e99104
2 changed files with 160 additions and 26 deletions

View file

@ -61,6 +61,7 @@ static void size_allocate_cb(GtkWidget * widget,
static void update_map_size(GtkSatMap * satmap);
static void update_sat(gpointer key, gpointer value, gpointer data);
static void plot_sat(gpointer key, gpointer value, gpointer data);
static void free_sat_obj(gpointer key, gpointer value, gpointer data);
static void lonlat_to_xy(GtkSatMap * m, gdouble lon, gdouble lat,
gfloat * x, gfloat * y);
static void xy_to_lonlat(GtkSatMap * m, gfloat x, gfloat y, gfloat * lon,
@ -184,8 +185,98 @@ static void gtk_sat_map_init(GtkSatMap * satmap,
static void gtk_sat_map_destroy(GtkWidget * widget)
{
gtk_sat_map_store_showtracks(GTK_SAT_MAP(widget));
gtk_sat_map_store_hidecovs(GTK_SAT_MAP(widget));
GtkSatMap *satmap = GTK_SAT_MAP(widget);
GooCanvasItemModel *root;
gint idx;
guint i;
/* check widget isn't already destroyed */
if (satmap->obj) {
/* save config */
gtk_sat_map_store_showtracks(GTK_SAT_MAP(widget));
gtk_sat_map_store_hidecovs(GTK_SAT_MAP(widget));
/* sat objects need a reference to the widget to free all alocations */
g_hash_table_foreach(satmap->obj, free_sat_obj, satmap);
g_hash_table_destroy(satmap->obj);
satmap->obj = NULL;
/* these objects destruct themselves cleanly */
g_object_unref(satmap->origmap);
satmap->origmap = NULL;
g_hash_table_destroy(satmap->showtracks);
satmap->showtracks = NULL;
g_hash_table_destroy(satmap->hidecovs);
satmap->hidecovs = NULL;
root = goo_canvas_get_root_item_model(GOO_CANVAS(satmap->canvas));
idx = goo_canvas_item_model_find_child(root, satmap->qthmark);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->qthmark = NULL;
idx = goo_canvas_item_model_find_child(root, satmap->qthlabel);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->qthlabel = NULL;
idx = goo_canvas_item_model_find_child(root, satmap->locnam);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->locnam = NULL;
idx = goo_canvas_item_model_find_child(root, satmap->curs);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->curs = NULL;
idx = goo_canvas_item_model_find_child(root, satmap->next);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->next = NULL;
idx = goo_canvas_item_model_find_child(root, satmap->sel);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->sel = NULL;
idx = goo_canvas_item_model_find_child(root, satmap->terminator);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->terminator = NULL;
for (i = 0; i < 5; i++)
{
idx = goo_canvas_item_model_find_child(root, satmap->gridh[i]);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->gridh[i] = NULL;
idx = goo_canvas_item_model_find_child(root, satmap->gridhlab[i]);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->gridhlab[i] = NULL;
}
for (i = 0; i < 11; i++)
{
idx = goo_canvas_item_model_find_child(root, satmap->gridv[i]);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->gridv[i] = NULL;
idx = goo_canvas_item_model_find_child(root, satmap->gridvlab[i]);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->gridvlab[i] = NULL;
}
idx = goo_canvas_item_model_find_child(root, satmap->map);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
satmap->map = NULL;
}
(*GTK_WIDGET_CLASS(parent_class)->destroy) (widget);
}
@ -202,7 +293,7 @@ GtkWidget *gtk_sat_map_new(GKeyFile * cfgdata, GHashTable * sats,
satmap->sats = sats;
satmap->qth = qth;
satmap->obj = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
satmap->obj = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
satmap->refresh = mod_cfg_get_int(cfgdata,
MOD_CFG_MAP_SECTION,
@ -293,6 +384,7 @@ static GooCanvasItemModel *create_canvas_model(GtkSatMap * satmap)
gfloat x, y;
guint32 col;
satmap->terminator = NULL;
root = goo_canvas_group_model_new(NULL, NULL);
/* map dimensions */
@ -1733,6 +1825,8 @@ static void plot_sat(gpointer key, gpointer value, gpointer data)
obj->istarget = FALSE;
obj->oldrcnum = 0;
obj->newrcnum = 0;
obj->range2 = NULL;
obj->catnum = sat->tle.catnr;
obj->track_data.latlon = NULL;
obj->track_data.lines = NULL;
obj->track_orbit = 0;
@ -1874,6 +1968,67 @@ static void plot_sat(gpointer key, gpointer value, gpointer data)
g_hash_table_insert(satmap->obj, catnum, obj);
}
/**
* Free a satellite object.
*
* @param key The hash table key.
* @param value Pointer to the satellite.
* @param data Pointer to the GtkSatMap widget.
*
* This function removes the canvas objects allocated by `plot_sat`. It needs
* access the the GtkSatMap widget to remove the elements from the canvas and
* to pass on to `ground_track_delete`. The function must be called as a
* g_hash_table_foreach callback in order to pass in the GtkSatMap.
*/
static void free_sat_obj(gpointer key, gpointer value, gpointer data)
{
sat_map_obj_t *obj = SAT_MAP_OBJ(value);
sat_t *sat = NULL;
GtkSatMap *satmap = GTK_SAT_MAP(data);
GooCanvasItemModel *root;
gint idx;
(void)key;
root = goo_canvas_get_root_item_model(GOO_CANVAS(satmap->canvas));
idx = goo_canvas_item_model_find_child(root, obj->marker);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);;
obj->marker = NULL;
idx = goo_canvas_item_model_find_child(root, obj->shadowm);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);;
obj->shadowm = NULL;
idx = goo_canvas_item_model_find_child(root, obj->label);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
obj->label = NULL;
idx = goo_canvas_item_model_find_child(root, obj->shadowl);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
obj->shadowl = NULL;
idx = goo_canvas_item_model_find_child(root, obj->range1);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
obj->range1 = NULL;
idx = goo_canvas_item_model_find_child(root, obj->range2);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
obj->range2 = NULL;
if (obj->showtrack)
{
sat = SAT(g_hash_table_lookup(satmap->sats, &obj->catnr));
ground_track_delete(satmap, sat, satmap->qth, obj, TRUE);
}
}
/** Update a given satellite. */
static void update_sat(gpointer key, gpointer value, gpointer data)
{
@ -1914,29 +2069,7 @@ static void update_sat(gpointer key, gpointer value, gpointer data)
/* get rid of a decayed satellite */
if (decayed(sat) && obj != NULL)
{
idx = goo_canvas_item_model_find_child(root, obj->marker);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);;
idx = goo_canvas_item_model_find_child(root, obj->shadowm);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);;
idx = goo_canvas_item_model_find_child(root, obj->label);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
idx = goo_canvas_item_model_find_child(root, obj->shadowl);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
idx = goo_canvas_item_model_find_child(root, obj->range1);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
idx = goo_canvas_item_model_find_child(root, obj->range2);
if (idx != -1)
goo_canvas_item_model_remove_child(root, idx);
g_hash_table_remove(satmap->obj, catnum);
if (obj->showtrack)
ground_track_update(satmap, sat, satmap->qth, obj, TRUE);
g_free(obj);
free_sat_obj(NULL, obj, satmap);
g_hash_table_remove(satmap->obj, catnum);
return;
}

View file

@ -65,6 +65,7 @@ typedef struct {
/* book keeping */
guint oldrcnum; /*!< Number of RC parts in prev. cycle. */
guint newrcnum; /*!< Number of RC parts in this cycle. */
gint catnum; /*!< Catalogue number of satellite. */
ground_track_t track_data; /*!< Ground track data. */
long track_orbit; /*!< Orbit when the ground track has been updated. */