Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional priority queue related APIs #1067

Merged
merged 10 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions include/aws/common/priority_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -175,6 +181,24 @@ size_t aws_priority_queue_size(const struct aws_priority_queue *queue);
AWS_COMMON_API
size_t aws_priority_queue_capacity(const struct aws_priority_queue *queue);

/**
* Initializes a queue node to a default value that indicates the node is not in the queue.
*
* @param node priority queue node to initialize with a default value
*/
AWS_COMMON_API
void aws_priority_queue_node_init(struct aws_priority_queue_node *node);

/**
* Checks if a priority queue node is currently in a priority queue.
*
* @param node priority queue node to check usage for
*
* @return true if the node is in a queue, false otherwise
*/
AWS_COMMON_API
bool aws_priority_queue_node_is_in_queue(const struct aws_priority_queue_node *node);

AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL

Expand Down
24 changes: 24 additions & 0 deletions source/priority_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,27 @@ size_t aws_priority_queue_size(const struct aws_priority_queue *queue) {
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;
}

bool aws_priority_queue_node_is_in_queue(const struct aws_priority_queue_node *node) {
return node->current_index != SIZE_MAX;
}
4 changes: 2 additions & 2 deletions source/task_scheduler.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void aws_task_scheduler_schedule_now(struct aws_task_scheduler *scheduler, struc
(void *)task,
task->type_tag);

task->priority_queue_node.current_index = SIZE_MAX;
aws_priority_queue_node_init(&task->priority_queue_node);
aws_linked_list_node_reset(&task->node);
task->timestamp = 0;

Expand All @@ -161,7 +161,7 @@ void aws_task_scheduler_schedule_future(

task->timestamp = time_to_run;

task->priority_queue_node.current_index = SIZE_MAX;
aws_priority_queue_node_init(&task->priority_queue_node);
aws_linked_list_node_reset(&task->node);
int err = aws_priority_queue_push_ref(&scheduler->timed_queue, &task, &task->priority_queue_node);
if (AWS_UNLIKELY(err)) {
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
36 changes: 36 additions & 0 deletions tests/priority_queue_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,10 +451,46 @@ static int s_test_remove_interior_sift_down(struct aws_allocator *allocator, voi
return 0;
}

#define BACKPOINTER_CLEAR_NODE_COUNT 16

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));

struct aws_priority_queue_node queue_nodes[BACKPOINTER_CLEAR_NODE_COUNT];

for (size_t i = 0; i < BACKPOINTER_CLEAR_NODE_COUNT; ++i) {
aws_priority_queue_node_init(&queue_nodes[i]);
}

for (int i = 0; i < BACKPOINTER_CLEAR_NODE_COUNT; i++) {
aws_priority_queue_push_ref(&queue, &i, &queue_nodes[i]);
}

for (size_t i = 0; i < BACKPOINTER_CLEAR_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 < BACKPOINTER_CLEAR_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);
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);