From 1c6958d443354be305066875643f1f3320041033 Mon Sep 17 00:00:00 2001 From: Robin Bergewski Date: Sun, 13 Apr 2025 22:26:07 +0200 Subject: [PATCH] core:sync/chan: maintainance and package clarity this deprecates all procedures around 'Raw_Queue' for it to become package private. --- core/sync/chan/chan.odin | 267 ++++++++++++++++++++------------------- 1 file changed, 134 insertions(+), 133 deletions(-) diff --git a/core/sync/chan/chan.odin b/core/sync/chan/chan.odin index 40e5b7416..eca4c28d7 100644 --- a/core/sync/chan/chan.odin +++ b/core/sync/chan/chan.odin @@ -1037,139 +1037,6 @@ is_closed :: proc "contextless" (c: ^Raw_Chan) -> bool { return bool(c.closed) } - - -/* -`Raw_Queue` is a non-thread-safe queue implementation designed to store messages -of fixed size and alignment. - -Note: For most use cases, it is recommended to use `core:container/queue` instead, -as `Raw_Queue` is used internally by `Raw_Chan` and may not provide the desired -level of convenience for typical applications. -*/ -Raw_Queue :: struct { - data: [^]byte, - len: int, - cap: int, - next: int, - size: int, // element size -} - -/* -Initializes a `Raw_Queue` - -**Inputs** -- `q`: A pointert to the `Raw_Queue` to initialize -- `data`: The pointer to backing slice storing the messages -- `cap`: The capacity of the queue -- `size`: The size of a message - -Example: - - import "core:sync/chan" - - raw_queue_init_example :: proc() { - // use a stack allocated array as backing storage - storage: [100]int - - rq: chan.Raw_Queue - chan.raw_queue_init(&rq, &storage, cap(storage), size_of(int)) - } -*/ -raw_queue_init :: proc "contextless" (q: ^Raw_Queue, data: rawptr, cap: int, size: int) { - q.data = ([^]byte)(data) - q.len = 0 - q.cap = cap - q.next = 0 - q.size = size -} - -/* -Add an element to the queue. - -Note: The message referenced by `data` must match the size -and alignment used when the `Raw_Queue` was initialized. - -**Inputs** -- `q`: A pointert to the `Raw_Queue` -- `data`: The pointer to message to add - -**Returns** -- `true` if the element was added, `false` when the queue is already full - -Example: - - import "core:sync/chan" - - raw_queue_push_example :: proc() { - storage: [100]int - rq: chan.Raw_Queue - chan.raw_queue_init(&rq, &storage, cap(storage), size_of(int)) - - value := 2 - assert(chan.raw_queue_push(&rq, &value), "there was enough space") - } -*/ -@(require_results) -raw_queue_push :: proc "contextless" (q: ^Raw_Queue, data: rawptr) -> bool { - if q.len == q.cap { - return false - } - pos := q.next + q.len - if pos >= q.cap { - pos -= q.cap - } - - val_ptr := q.data[pos*q.size:] - mem.copy(val_ptr, data, q.size) - q.len += 1 - return true -} - -/* -Removes and returns the first element of the queue. - -Note: The returned element is only guaranteed to be valid until the next -`raw_queue_push` operation. Accessing it after that point may result in -undefined behavior. - -**Inputs** -- `c`: A pointer to the `Raw_Queue`. - -**Returns** -- A pointer to the first element in the queue, or `nil` if the queue is empty. - -Example: - - import "core:sync/chan" - - raw_queue_pop_example :: proc() { - storage: [100]int - rq: chan.Raw_Queue - chan.raw_queue_init(&rq, &storage, cap(storage), size_of(int)) - - assert(chan.raw_queue_pop(&rq) == nil, "queue was empty") - - // add an element to the queue - value := 2 - assert(chan.raw_queue_push(&rq, &value), "there was enough space") - - assert((cast(^int)chan.raw_queue_pop(&rq))^ == 2, "retrieved the element") - } -*/ -@(require_results) -raw_queue_pop :: proc "contextless" (q: ^Raw_Queue) -> (data: rawptr) { - if q.len > 0 { - data = q.data[q.next*q.size:] - q.next += 1 - q.len -= 1 - if q.next >= q.cap { - q.next -= q.cap - } - } - return -} - /* Returns whether a message is ready to be read, i.e., if a call to `recv` or `recv_raw` would block @@ -1347,3 +1214,137 @@ select_raw :: proc "odin" (recvs: []^Raw_Chan, sends: []^Raw_Chan, send_msgs: [] } return } + + +/* +`Raw_Queue` is a non-thread-safe queue implementation designed to store messages +of fixed size and alignment. + +Note: For most use cases, it is recommended to use `core:container/queue` instead, +as `Raw_Queue` is used internally by `Raw_Chan` and may not provide the desired +level of convenience for typical applications. +*/ +@(private) +Raw_Queue :: struct { + data: [^]byte, + len: int, + cap: int, + next: int, + size: int, // element size +} + +/* +Initializes a `Raw_Queue` + +**Inputs** +- `q`: A pointert to the `Raw_Queue` to initialize +- `data`: The pointer to backing slice storing the messages +- `cap`: The capacity of the queue +- `size`: The size of a message + +Example: + + import "core:sync/chan" + + raw_queue_init_example :: proc() { + // use a stack allocated array as backing storage + storage: [100]int + + rq: chan.Raw_Queue + chan.raw_queue_init(&rq, &storage, cap(storage), size_of(int)) + } +*/ +@(private) +raw_queue_init :: proc "contextless" (q: ^Raw_Queue, data: rawptr, cap: int, size: int) { + q.data = ([^]byte)(data) + q.len = 0 + q.cap = cap + q.next = 0 + q.size = size +} + +/* +Add an element to the queue. + +Note: The message referenced by `data` must match the size +and alignment used when the `Raw_Queue` was initialized. + +**Inputs** +- `q`: A pointert to the `Raw_Queue` +- `data`: The pointer to message to add + +**Returns** +- `true` if the element was added, `false` when the queue is already full + +Example: + + import "core:sync/chan" + + raw_queue_push_example :: proc() { + storage: [100]int + rq: chan.Raw_Queue + chan.raw_queue_init(&rq, &storage, cap(storage), size_of(int)) + + value := 2 + assert(chan.raw_queue_push(&rq, &value), "there was enough space") + } +*/ +@(private, require_results) +raw_queue_push :: proc "contextless" (q: ^Raw_Queue, data: rawptr) -> bool { + if q.len == q.cap { + return false + } + pos := q.next + q.len + if pos >= q.cap { + pos -= q.cap + } + + val_ptr := q.data[pos*q.size:] + mem.copy(val_ptr, data, q.size) + q.len += 1 + return true +} + +/* +Removes and returns the first element of the queue. + +Note: The returned element is only guaranteed to be valid until the next +`raw_queue_push` operation. Accessing it after that point may result in +undefined behavior. + +**Inputs** +- `c`: A pointer to the `Raw_Queue`. + +**Returns** +- A pointer to the first element in the queue, or `nil` if the queue is empty. + +Example: + + import "core:sync/chan" + + raw_queue_pop_example :: proc() { + storage: [100]int + rq: chan.Raw_Queue + chan.raw_queue_init(&rq, &storage, cap(storage), size_of(int)) + + assert(chan.raw_queue_pop(&rq) == nil, "queue was empty") + + // add an element to the queue + value := 2 + assert(chan.raw_queue_push(&rq, &value), "there was enough space") + + assert((cast(^int)chan.raw_queue_pop(&rq))^ == 2, "retrieved the element") + } +*/ +@(private, require_results) +raw_queue_pop :: proc "contextless" (q: ^Raw_Queue) -> (data: rawptr) { + if q.len > 0 { + data = q.data[q.next*q.size:] + q.next += 1 + q.len -= 1 + if q.next >= q.cap { + q.next -= q.cap + } + } + return +}