From: Ryan Lortie Date: Fri, 16 Oct 2009 10:19:06 +0000 (+0200) Subject: Bug 158725 - free linked list with data X-Git-Tag: 2.27.2~27 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7c184df292f7552423fa7931c843b2f1949c1455;p=platform%2Fupstream%2Fglib.git 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. --- diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index c547c8c1d..eefb3915a 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -1992,6 +1992,7 @@ g_list_remove_link g_list_delete_link g_list_remove_all g_list_free +g_list_free_full 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 diff --git a/glib/glib.symbols b/glib/glib.symbols index d0b3fa94c..c4211872c 100644 --- a/glib/glib.symbols +++ b/glib/glib.symbols @@ -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 diff --git a/glib/glist.c b/glib/glist.c index c8f743463..6664964b7 100644 --- a/glib/glist.c +++ b/glib/glist.c @@ -172,7 +172,8 @@ g_list_alloc (void) * * * 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. * */ 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 diff --git a/glib/glist.h b/glib/glist.h index e74ed96f1..275005c79 100644 --- a/glib/glist.h +++ b/glib/glist.h @@ -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, diff --git a/glib/gslist.c b/glib/gslist.c index dfbd35440..f6581a8fa 100644 --- a/glib/gslist.c +++ b/glib/gslist.c @@ -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 diff --git a/glib/gslist.h b/glib/gslist.h index 8b01faf5c..3731ba97d 100644 --- a/glib/gslist.h +++ b/glib/gslist.h @@ -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, diff --git a/glib/tests/list.c b/glib/tests/list.c index 05bc8e4b4..084f7ead5 100644 --- a/glib/tests/list.c +++ b/glib/tests/list.c @@ -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 (); }