From: Sebastian Harl Date: Mon, 21 Apr 2014 16:52:48 +0000 (+0200) Subject: utils llist: Added sdb_llist_clear(). X-Git-Tag: sysdb-0.1.0~110 X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=commitdiff_plain;h=ed920688e7cdc9fd497044379c8d14da0dfaebeb utils llist: Added sdb_llist_clear(). This function clears the list by removing all elements and releasing the included objects. It's similar to destroy() but does not actually release the list object itself. --- diff --git a/src/include/utils/llist.h b/src/include/utils/llist.h index f557c9d..28816a6 100644 --- a/src/include/utils/llist.h +++ b/src/include/utils/llist.h @@ -56,6 +56,14 @@ sdb_llist_create(void); void sdb_llist_destroy(sdb_llist_t *list); +/* + * sdb_llist_clear: + * Remove all elements from the list, releasing the included objects + * (decrement the ref-count). + */ +void +sdb_llist_clear(sdb_llist_t *list); + /* * sdb_llist_clone: * Clone an existing list. The objects stored in the list will not be copied diff --git a/src/utils/llist.c b/src/utils/llist.c index e042c99..f9bf722 100644 --- a/src/utils/llist.c +++ b/src/utils/llist.c @@ -69,6 +69,26 @@ struct sdb_llist_iter { * private helper functions */ +static void +llist_clear(sdb_llist_t *list) +{ + sdb_llist_elem_t *elem; + + assert(list); + elem = list->head; + while (elem) { + sdb_llist_elem_t *tmp = elem->next; + + sdb_object_deref(elem->obj); + free(elem); + + elem = tmp; + } + + list->head = list->tail = NULL; + list->length = 0; +} /* llist_clear */ + /* Insert a new element after 'elem'. If 'elem' is NULL, insert at the head of * the list. */ static int @@ -213,31 +233,27 @@ sdb_llist_clone(sdb_llist_t *list) void sdb_llist_destroy(sdb_llist_t *list) { - sdb_llist_elem_t *elem; - if (! list) return; pthread_rwlock_wrlock(&list->lock); - - elem = list->head; - while (elem) { - sdb_llist_elem_t *tmp = elem->next; - - sdb_object_deref(elem->obj); - free(elem); - - elem = tmp; - } - - list->head = list->tail = NULL; - list->length = 0; - + llist_clear(list); pthread_rwlock_unlock(&list->lock); pthread_rwlock_destroy(&list->lock); free(list); } /* sdb_llist_destroy */ +void +sdb_llist_clear(sdb_llist_t *list) +{ + if (! list) + return; + + pthread_rwlock_wrlock(&list->lock); + llist_clear(list); + pthread_rwlock_unlock(&list->lock); +} /* sdb_llist_clear */ + int sdb_llist_append(sdb_llist_t *list, sdb_object_t *obj) { diff --git a/t/utils/llist_test.c b/t/utils/llist_test.c index e8d366c..cc9954d 100644 --- a/t/utils/llist_test.c +++ b/t/utils/llist_test.c @@ -115,6 +115,25 @@ START_TEST(test_destroy) } END_TEST +START_TEST(test_clear) +{ + size_t i; + populate(); + sdb_llist_clear(list); + + for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { + fail_unless(golden_data[i].ref_cnt == 1, + "sdb_llist_clear() did not deref element %s", + golden_data[i].name); + } + + i = sdb_llist_len(list); + fail_unless(i == 0, + "sdb_llist_clear() left %zu elements in the list; " + "expected: 0", i); +} +END_TEST + START_TEST(test_append) { size_t i; @@ -361,6 +380,7 @@ util_llist_suite(void) tcase_add_checked_fixture(tc, setup, teardown); tcase_add_test(tc, test_clone); tcase_add_test(tc, test_destroy); + tcase_add_test(tc, test_clear); tcase_add_test(tc, test_append); tcase_add_test(tc, test_insert); tcase_add_test(tc, test_validate_insert);