diff --git a/core/container/priority_queue/doc.odin b/core/container/priority_queue/doc.odin new file mode 100644 index 000000000..e499afac9 --- /dev/null +++ b/core/container/priority_queue/doc.odin @@ -0,0 +1,50 @@ +// A priority queue data structure. +package container_priority_queue + +/* +import "base:runtime" +import pq "core:container/priority_queue" + +main :: proc() { + Printer_Job :: struct { + user_id: u64, + weight: enum u8 {Highest, High, Normal, Low, Idle}, + } + + q: pq.Priority_Queue(Printer_Job) + pq.init( + pq = &q, + less = proc(a, b: Printer_Job) -> bool { + // Jobs will be sorted in order of increasing weight + return a.weight < b.weight + }, + swap = pq.default_swap_proc(Printer_Job), + ) + defer pq.destroy(&q) + + // Add jobs with random weights + for _ in 0..<100 { + job: Printer_Job = --- + assert(runtime.random_generator_read_ptr(context.random_generator, &job, size_of(job))) + pq.push(&q, job) + } + + last: Printer_Job + for pq.len(q) > 0 { + // Drain jobs + v := pq.pop(&q) + assert(v.weight >= last.weight) + last = v + } + + // Queue empty? + assert(pq.len(q) == 0) + + // Add one more job + pq.push(&q, Printer_Job{user_id = 42, weight = .Idle}) + + // Cancel all jobs + pq.clear(&q) + assert(pq.len(q) == 0) +} +*/ \ No newline at end of file diff --git a/core/container/priority_queue/priority_queue.odin b/core/container/priority_queue/priority_queue.odin index c9ef807c5..d83750673 100644 --- a/core/container/priority_queue/priority_queue.odin +++ b/core/container/priority_queue/priority_queue.odin @@ -1,9 +1,11 @@ -// A priority queue data structure. package container_priority_queue import "base:builtin" import "base:runtime" +// Priority Queue. +// +// Important: Must be `init`ialized with `less` and `swap` procedures before use. See `doc.odin` for an example. Priority_Queue :: struct($T: typeid) { queue: [dynamic]T, diff --git a/tests/core/container/test_core_priority_queue.odin b/tests/core/container/test_core_priority_queue.odin new file mode 100644 index 000000000..417056d48 --- /dev/null +++ b/tests/core/container/test_core_priority_queue.odin @@ -0,0 +1,113 @@ +package test_core_container + +import "base:runtime" +import pq "core:container/priority_queue" +import "core:math/rand" +import "core:testing" + +@test +test_priority_queue :: proc(t: ^testing.T) { + q: pq.Priority_Queue(int) + pq.init(&q, proc(a, b: int) -> bool { + return a < b + }, pq.default_swap_proc(int)) + defer pq.destroy(&q) + + assert(pq.cap(q) == pq.DEFAULT_CAPACITY) + + pq.push(&q, 42) + assert(pq.len(q) == 1) + assert(pq.peek(q) == 42) + + v := pq.pop(&q) + assert(v == 42) + assert(pq.len(q) == 0) + + ok: bool + v, ok = pq.peek_safe(q) + assert(v == 0 && ok == false) + + v, ok = pq.pop_safe(&q) + assert(v == 0 && ok == false) + + N :: 15 + for _ in 0.. 0 { + v = pq.pop(&q) + assert(v >= last) + last = v + } + + vals := []int{6, 15, 3, 9, 12} + for _v in vals { + pq.push(&q, _v) + } + // Break ordering and fix it + q.queue[3] = 42 + pq.fix(&q, 3) + + last = 0 + for pq.len(q) > 0 { + v = pq.pop(&q) + assert(v >= last) + last = v + } + + assert(pq.len(q) == 0) + + for _v in vals { + pq.push(&q, _v) + } + + // Break ordering again, but this time delete that index + q.queue[3] = 42 + v, ok = pq.remove(&q, 3) + assert(v == 42 && ok == true) + + last = 0 + for pq.len(q) > 0 { + v = pq.pop(&q) + assert(v >= last && v != 42) + last = v + } +} + +@(test) +test_pq_init_from_dynamic_array :: proc(t: ^testing.T) { + N :: 50_000 + + arr := make_dynamic_array_len_cap([dynamic]u64, N, N, context.allocator) + assert(runtime.random_generator_read_ptr(context.random_generator, raw_data(arr), N * size_of(u64))) + + q: pq.Priority_Queue(u64) + pq.init_from_dynamic_array( + pq = &q, + queue = arr, + less = proc(a, b: u64) -> bool { return a < b }, + swap = pq.default_swap_proc(u64), + ) + defer pq.destroy(&q) + + assert(pq.len(q) == N) + + last: u64 + for pq.len(q) > 0 { + v := pq.pop(&q) + assert(v >= last) + last = v + } + + assert(pq.len(q) == 0) + assert(pq.cap(q) == N) + + pq.reserve(&q, N + 12) + assert(pq.cap(q) == N + 12) + +} \ No newline at end of file diff --git a/tests/core/container/test_core_xar.odin b/tests/core/container/test_core_xar.odin index a58b369df..ee9318097 100644 --- a/tests/core/container/test_core_xar.odin +++ b/tests/core/container/test_core_xar.odin @@ -3,13 +3,13 @@ package test_core_container import "core:container/xar" import "core:testing" -Value :: struct { - v: int, - p: ^int, -} - @test test_xar_pointer_stability :: proc(t: ^testing.T) { + Value :: struct { + v: int, + p: ^int, + } + x: xar.Array(int, 4) defer xar.destroy(&x)