mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-13 07:56:17 +01:00
Bug 158725 - free linked list with data
Add some helpers for freeing a linked list along with its elements by providing a GDestroyNotify to call on each of them. Add a test. Based on a patch from Cosimo Cecchi.
This commit is contained in:
parent
4baad1acbf
commit
7c184df292
@ -1992,6 +1992,7 @@ g_list_remove_link
|
||||
g_list_delete_link
|
||||
g_list_remove_all
|
||||
g_list_free
|
||||
g_list_free_full
|
||||
|
||||
<SUBSECTION>
|
||||
g_list_alloc
|
||||
@ -2048,6 +2049,7 @@ g_slist_remove_link
|
||||
g_slist_delete_link
|
||||
g_slist_remove_all
|
||||
g_slist_free
|
||||
g_slist_free_full
|
||||
g_slist_free_1
|
||||
g_slist_free1
|
||||
|
||||
|
@ -649,6 +649,7 @@ g_list_find_custom
|
||||
g_list_first
|
||||
g_list_foreach
|
||||
g_list_free
|
||||
g_list_free_full
|
||||
g_list_free_1
|
||||
g_list_index
|
||||
g_list_insert
|
||||
@ -1152,6 +1153,7 @@ g_slist_find
|
||||
g_slist_find_custom
|
||||
g_slist_foreach
|
||||
g_slist_free
|
||||
g_slist_free_full
|
||||
g_slist_free_1
|
||||
g_slist_index
|
||||
g_slist_insert
|
||||
|
21
glib/glist.c
21
glib/glist.c
@ -172,7 +172,8 @@ g_list_alloc (void)
|
||||
*
|
||||
* <note><para>
|
||||
* If list elements contain dynamically-allocated memory,
|
||||
* they should be freed first.
|
||||
* you should either use g_list_free_full() or free them manually
|
||||
* first.
|
||||
* </para></note>
|
||||
*/
|
||||
void
|
||||
@ -199,6 +200,24 @@ g_list_free_1 (GList *list)
|
||||
_g_list_free1 (list);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_list_free_full:
|
||||
* @list: a pointer to a #GList
|
||||
* @free_func: the function to be called to free each element's data
|
||||
*
|
||||
* Convenience method, which frees all the memory used by a #GList, and
|
||||
* calls the specified destroy function on every element's data.
|
||||
*
|
||||
* Since: 2.28
|
||||
*/
|
||||
void
|
||||
g_list_free_full (GList *list,
|
||||
GDestroyNotify free_func)
|
||||
{
|
||||
g_list_foreach (list, (GFunc) free_func, NULL);
|
||||
g_list_free (list);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_list_append:
|
||||
* @list: a pointer to a #GList
|
||||
|
@ -50,6 +50,8 @@ GList* g_list_alloc (void) G_GNUC_WARN_UNUSED_RESULT;
|
||||
void g_list_free (GList *list);
|
||||
void g_list_free_1 (GList *list);
|
||||
#define g_list_free1 g_list_free_1
|
||||
void g_list_free_full (GList *list,
|
||||
GDestroyNotify free_func);
|
||||
GList* g_list_append (GList *list,
|
||||
gpointer data) G_GNUC_WARN_UNUSED_RESULT;
|
||||
GList* g_list_prepend (GList *list,
|
||||
|
@ -186,6 +186,24 @@ g_slist_free_1 (GSList *list)
|
||||
_g_slist_free1 (list);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_slist_free_full:
|
||||
* @list: a pointer to a #GSList
|
||||
* @free_func: the function to be called to free each element's data
|
||||
*
|
||||
* Convenience method, which frees all the memory used by a #GSList, and
|
||||
* calls the specified destroy function on every element's data.
|
||||
*
|
||||
* Since: 2.28
|
||||
**/
|
||||
void
|
||||
g_slist_free_full (GSList *list,
|
||||
GDestroyNotify free_func)
|
||||
{
|
||||
g_slist_foreach (list, (GFunc) free_func, NULL);
|
||||
g_slist_free (list);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_slist_append:
|
||||
* @list: a #GSList
|
||||
|
@ -49,6 +49,8 @@ GSList* g_slist_alloc (void) G_GNUC_WARN_UNUSED_RESULT;
|
||||
void g_slist_free (GSList *list);
|
||||
void g_slist_free_1 (GSList *list);
|
||||
#define g_slist_free1 g_slist_free_1
|
||||
void g_slist_free_full (GSList *list,
|
||||
GDestroyNotify free_func);
|
||||
GSList* g_slist_append (GSList *list,
|
||||
gpointer data) G_GNUC_WARN_UNUSED_RESULT;
|
||||
GSList* g_slist_prepend (GSList *list,
|
||||
|
@ -294,6 +294,68 @@ test_list_insert (void)
|
||||
g_list_free (list);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean freed;
|
||||
int x;
|
||||
} ListItem;
|
||||
|
||||
static void
|
||||
free_func (gpointer data)
|
||||
{
|
||||
ListItem *item = data;
|
||||
|
||||
item->freed = TRUE;
|
||||
}
|
||||
|
||||
static ListItem *
|
||||
new_item (int x)
|
||||
{
|
||||
ListItem *item;
|
||||
|
||||
item = g_slice_new (ListItem);
|
||||
item->freed = FALSE;
|
||||
item->x = x;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
static void
|
||||
test_free_full (void)
|
||||
{
|
||||
ListItem *one, *two, *three;
|
||||
GSList *slist = NULL;
|
||||
GList *list = NULL;
|
||||
|
||||
slist = g_slist_prepend (slist, one = new_item (1));
|
||||
slist = g_slist_prepend (slist, two = new_item (2));
|
||||
slist = g_slist_prepend (slist, three = new_item (3));
|
||||
g_assert (!one->freed);
|
||||
g_assert (!two->freed);
|
||||
g_assert (!three->freed);
|
||||
g_slist_free_full (slist, free_func);
|
||||
g_assert (one->freed);
|
||||
g_assert (two->freed);
|
||||
g_assert (three->freed);
|
||||
g_slice_free (ListItem, one);
|
||||
g_slice_free (ListItem, two);
|
||||
g_slice_free (ListItem, three);
|
||||
|
||||
list = g_list_prepend (list, one = new_item (1));
|
||||
list = g_list_prepend (list, two = new_item (2));
|
||||
list = g_list_prepend (list, three = new_item (3));
|
||||
g_assert (!one->freed);
|
||||
g_assert (!two->freed);
|
||||
g_assert (!three->freed);
|
||||
g_list_free_full (list, free_func);
|
||||
g_assert (one->freed);
|
||||
g_assert (two->freed);
|
||||
g_assert (three->freed);
|
||||
g_slice_free (ListItem, one);
|
||||
g_slice_free (ListItem, two);
|
||||
g_slice_free (ListItem, three);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@ -316,6 +378,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/list/remove-all", test_list_remove_all);
|
||||
g_test_add_func ("/list/first-last", test_list_first_last);
|
||||
g_test_add_func ("/list/insert", test_list_insert);
|
||||
g_test_add_func ("/list/free-full", test_free_full);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user