summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 08f22af)
raw | patch | inline | side by side (parent: 08f22af)
author | Sebastian Harl <sh@tokkee.org> | |
Fri, 25 Oct 2013 15:23:32 +0000 (17:23 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Fri, 25 Oct 2013 15:23:32 +0000 (17:23 +0200) |
This function may be used to remove the current (the one returned by the last
sdb_llist_iter_get_next() call) iterator value from the list.
Note, that this function is not safe if another iterator is used in parallel
at the same time.
sdb_llist_iter_get_next() call) iterator value from the list.
Note, that this function is not safe if another iterator is used in parallel
at the same time.
src/include/utils/llist.h | patch | blob | history | |
src/utils/llist.c | patch | blob | history | |
t/utils/llist_test.c | patch | blob | history |
index 104c9e45ab94c2e08a8aca2feb5e84ba57a2e1db..2742139f17db051d12b36c279889ff0c0bbfb48f 100644 (file)
sdb_object_t *
sdb_llist_shift(sdb_llist_t *list);
-/* sdb_llist_get_iter, sdb_llist_iter_has_next, sdb_llist_iter_get_next:
+/*
+ * sdb_llist_get_iter, sdb_llist_iter_has_next, sdb_llist_iter_get_next:
* Iterate through the list, element by element.
*
* sdb_llist_iter_get_next returns NULL if there is no next element.
sdb_object_t *
sdb_llist_iter_get_next(sdb_llist_iter_t *iter);
+/*
+ * sdb_llist_iter_remove_current:
+ * Remove the current object from the list, that is, the object which was
+ * returned by the last call to sdb_llist_iter_get_next().
+ *
+ * This operation is not safe if another iterator is in use at the same time.
+ *
+ * Returns:
+ * - 0 on success
+ * - a negative value else
+ */
+int
+sdb_llist_iter_remove_current(sdb_llist_iter_t *iter);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/src/utils/llist.c b/src/utils/llist.c
index 0af9c8cb11bec4346b96c557275b4a813ccfd618..0a4665d09296c2387bcf1f369f81f5e751c20fa4 100644 (file)
--- a/src/utils/llist.c
+++ b/src/utils/llist.c
return obj;
} /* sdb_llist_iter_get_next */
+int
+sdb_llist_iter_remove_current(sdb_llist_iter_t *iter)
+{
+ sdb_llist_elem_t *elem;
+
+ if ((! iter) || (! iter->list))
+ return -1;
+
+ pthread_rwlock_wrlock(&iter->list->lock);
+
+ if (! iter->elem) /* reached end of list */
+ elem = iter->list->tail;
+ else
+ elem = iter->elem->prev;
+ if (elem)
+ sdb_llist_remove_elem(iter->list, elem);
+
+ pthread_rwlock_unlock(&iter->list->lock);
+
+ if (! elem)
+ return -1;
+ return 0;
+} /* sdb_llist_iter_remove */
+
/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
diff --git a/t/utils/llist_test.c b/t/utils/llist_test.c
index 638d2fbdbeef1affe64e15753a7e6ca08cd7633e..ede8200a42a325d3f22707eb001febdc8ac9b51e 100644 (file)
--- a/t/utils/llist_test.c
+++ b/t/utils/llist_test.c
}
END_TEST
+START_TEST(test_sdb_llist_iter_remove)
+{
+ sdb_llist_iter_t *iter;
+ sdb_object_t *check;
+ size_t i;
+
+ populate();
+
+ iter = sdb_llist_get_iter(list);
+ fail_unless(iter != NULL,
+ "sdb_llist_get_iter() did not return an iterator");
+
+ i = 0;
+ while (sdb_llist_iter_has_next(iter)) {
+ check = sdb_llist_iter_get_next(iter);
+ fail_unless(check == &golden_data[i],
+ "sdb_llist_iter_get_next() = %p; expected: %p",
+ check, &golden_data[i]);
+
+ sdb_llist_iter_remove_current(iter);
+ ++i;
+ }
+ sdb_llist_iter_destroy(iter);
+
+ fail_unless(i == (size_t)SDB_STATIC_ARRAY_LEN(golden_data),
+ "iterated for %zu steps; expected: %i",
+ i, SDB_STATIC_ARRAY_LEN(golden_data));
+
+ /* all elements should be removed */
+ check = sdb_llist_shift(list);
+ fail_unless(check == NULL,
+ "sdb_llist_shift() = %p; expected: NULL", check);
+}
+END_TEST
+
Suite *
util_llist_suite(void)
{
tcase_add_test(tc, test_sdb_llist_search);
tcase_add_test(tc, test_sdb_llist_shift);
tcase_add_test(tc, test_sdb_llist_iter);
+ tcase_add_test(tc, test_sdb_llist_iter_remove);
suite_add_tcase(s, tc);
return s;