diff --git a/include/aws/common/priority_queue.h b/include/aws/common/priority_queue.h index b240e19ca..26b35e991 100644 --- a/include/aws/common/priority_queue.h +++ b/include/aws/common/priority_queue.h @@ -162,6 +162,12 @@ int aws_priority_queue_remove(struct aws_priority_queue *queue, void *item, cons AWS_COMMON_API int aws_priority_queue_top(const struct aws_priority_queue *queue, void **item); +/** + * Removes all elements from the queue, but does not free internal memory. + */ +AWS_COMMON_API +void aws_priority_queue_clear(struct aws_priority_queue *queue); + /** * Current number of elements in the queue */ diff --git a/source/priority_queue.c b/source/priority_queue.c index 0c7efa6a7..fcea718bf 100644 --- a/source/priority_queue.c +++ b/source/priority_queue.c @@ -401,6 +401,22 @@ size_t aws_priority_queue_capacity(const struct aws_priority_queue *queue) { return aws_array_list_capacity(&queue->container); } +void aws_priority_queue_clear(struct aws_priority_queue *queue) { + AWS_PRECONDITION(aws_priority_queue_is_valid(queue)); + size_t backpointer_count = aws_array_list_length(&queue->backpointers); + for (size_t i = 0; i < backpointer_count; ++i) { + struct aws_priority_queue_node *node = NULL; + aws_array_list_get_at(&queue->backpointers, &node, i); + if (node != NULL) { + node->current_index = SIZE_MAX; + } + } + + aws_array_list_clear(&queue->backpointers); + aws_array_list_clear(&queue->container); + AWS_PRECONDITION(aws_priority_queue_is_valid(queue)); +} + void aws_priority_queue_node_init(struct aws_priority_queue_node *node) { node->current_index = SIZE_MAX; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index de072868a..623eaf4c9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -94,6 +94,7 @@ add_test_case(priority_queue_remove_root_test) add_test_case(priority_queue_remove_leaf_test) add_test_case(priority_queue_remove_interior_sift_up_test) add_test_case(priority_queue_remove_interior_sift_down_test) +add_test_case(priority_queue_clear_backpointers_test) add_test_case(linked_list_push_back_pop_front) add_test_case(linked_list_push_front_pop_back) diff --git a/tests/priority_queue_test.c b/tests/priority_queue_test.c index 0e1257727..4be9c3ca9 100644 --- a/tests/priority_queue_test.c +++ b/tests/priority_queue_test.c @@ -451,6 +451,40 @@ static int s_test_remove_interior_sift_down(struct aws_allocator *allocator, voi return 0; } +static int s_priority_queue_clear_backpointers_test(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + struct aws_priority_queue queue; + + ASSERT_SUCCESS(aws_priority_queue_init_dynamic(&queue, allocator, 16, sizeof(int), s_compare_ints)); + + const size_t NODE_COUNT = 16; + struct aws_priority_queue_node queue_nodes[NODE_COUNT]; + + for (size_t i = 0; i < NODE_COUNT; ++i) { + aws_priority_queue_node_init(&queue_nodes[i]); + } + + for (int i = 0; i < NODE_COUNT; i++) { + aws_priority_queue_push_ref(&queue, &i, &queue_nodes[i]); + } + + for (size_t i = 0; i < NODE_COUNT; ++i) { + ASSERT_TRUE(aws_priority_queue_node_is_in_queue(&queue_nodes[i])); + } + + aws_priority_queue_clear(&queue); + ASSERT_INT_EQUALS(0, aws_priority_queue_size(&queue)); + + for (size_t i = 0; i < NODE_COUNT; ++i) { + ASSERT_FALSE(aws_priority_queue_node_is_in_queue(&queue_nodes[i])); + } + + aws_priority_queue_clean_up(&queue); + + return 0; +} + AWS_TEST_CASE(priority_queue_remove_interior_sift_down_test, s_test_remove_interior_sift_down); AWS_TEST_CASE(priority_queue_remove_interior_sift_up_test, s_test_remove_interior_sift_up); AWS_TEST_CASE(priority_queue_remove_leaf_test, s_test_remove_leaf); @@ -458,3 +492,4 @@ AWS_TEST_CASE(priority_queue_remove_root_test, s_test_remove_root); AWS_TEST_CASE(priority_queue_push_pop_order_test, s_test_priority_queue_preserves_order); AWS_TEST_CASE(priority_queue_random_values_test, s_test_priority_queue_random_values); AWS_TEST_CASE(priority_queue_size_and_capacity_test, s_test_priority_queue_size_and_capacity); +AWS_TEST_CASE(priority_queue_clear_backpointers_test, s_priority_queue_clear_backpointers_test);