--- libelwix/src/ring.c 2026/02/10 15:49:08 1.4.4.1 +++ libelwix/src/ring.c 2026/02/11 13:36:09 1.6 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: ring.c,v 1.4.4.1 2026/02/10 15:49:08 misho Exp $ +* $Id: ring.c,v 1.6 2026/02/11 13:36:09 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -284,6 +284,7 @@ lrb_purge(lrbuf_t *lrb) atomic_store_explicit((atomic_int*) &lrb->lrb_head, 0, memory_order_relaxed); atomic_store_explicit((atomic_int*) &lrb->lrb_tail, 0, memory_order_relaxed); + atomic_store_explicit((atomic_int*) &lrb->lrb_full, 0, memory_order_relaxed); } /* @@ -298,8 +299,9 @@ lrb_isempty(lrbuf_t *lrb) if (!lrb) return -1; - return (atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_acquire) == - atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire)); + return (!atomic_load_explicit((atomic_int*) &lrb->lrb_full, memory_order_acquire) && + (atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_acquire) == + atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire))); } /* @@ -318,15 +320,39 @@ lrb_isfull(lrbuf_t *lrb) if (!lrb->lrb_size) return 1; - t = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire); - h = atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_relaxed) + 1; - if (h >= lrb->lrb_size) - h ^= h; + if (!atomic_load_explicit((atomic_int*) &lrb->lrb_full, memory_order_acquire)) + return 0; + t = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire); + h = atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_acquire); return (h == t); } /* + * lrb_getw() - Get address for write + * + * @lrb = Linear ring buffer + * @len = Return available buffer length for write + * return: NULL error or !=NULL pointer for write + * remark: After use of lrb_getw() and write to pointer. + * You should update ring buffer with lrb_enqueue(,NULL,wrote_len,) + */ +void * +lrb_getw(lrbuf_t *lrb, size_t *len) +{ + int h; + + if (!lrb || !lrb->lrb_data || !lrb->lrb_size) + return NULL; + + h = atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_relaxed); + if (len) + *len = lrb->lrb_size - h; + + return (lrb->lrb_data + h); +} + +/* * lrb_enqueue() - Enqueue data to buffer * * @lrb = Linear ring buffer @@ -338,7 +364,7 @@ lrb_isfull(lrbuf_t *lrb) int lrb_enqueue(lrbuf_t *lrb, void *data, size_t len, int lost) { - int h, t, n, t2, unused, drop = 0; + int h, t = 0, n, t2 = 0, unused, drop = 0; if (!lrb || !lrb->lrb_data) return -1; @@ -362,15 +388,19 @@ lrb_enqueue(lrbuf_t *lrb, void *data, size_t len, int h = atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_relaxed); n = lrb->lrb_size - h; if (len < n) { - memcpy(lrb->lrb_data + h, data, len); + if (data) + memcpy(lrb->lrb_data + h, data, len); n = h + len; } else { - memcpy(lrb->lrb_data + h, data, n); - memcpy(lrb->lrb_data, data + n, len - n); + if (data) { + memcpy(lrb->lrb_data + h, data, n); + memcpy(lrb->lrb_data, data + n, len - n); + } n = len - n; } - atomic_store_explicit((atomic_int*) &lrb->lrb_head, n, memory_order_release); + h = n; + atomic_store_explicit((atomic_int*) &lrb->lrb_head, h, memory_order_release); if (drop > 0) while (42) { n = t; @@ -380,10 +410,37 @@ lrb_enqueue(lrbuf_t *lrb, void *data, size_t len, int t = n; t2 = (t + drop) % lrb->lrb_size; } + else + t2 = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire); + atomic_store_explicit((atomic_int*) &lrb->lrb_full, (h == t2), memory_order_release); return 0; } /* + * lrb_getr() - Get address for read + * + * @lrb = Linear ring buffer + * @len = Return available data length for read + * return: NULL error or !=NULL pointer for read + * remark: After use of lrb_getr() and read from pointer. + * You could update ring buffer with lrb_dequeue(,NULL,read_len) + */ +void * +lrb_getr(lrbuf_t *lrb, size_t *len) +{ + int t; + + if (!lrb || !lrb->lrb_data || !lrb->lrb_size) + return NULL; + + t = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire); + if (len) + lrb_queued(lrb, *len); + + return (lrb->lrb_data + t); +} + +/* * lrb_dequeue() - Dequeue data from buffer * * @lrb = Linear ring buffer @@ -394,7 +451,7 @@ lrb_enqueue(lrbuf_t *lrb, void *data, size_t len, int int lrb_dequeue(lrbuf_t *lrb, void *data, size_t len) { - int h, t, t2, n, l; + int h, t, t2, n, l, f; if (!lrb) return -1; @@ -406,12 +463,16 @@ lrb_dequeue(lrbuf_t *lrb, void *data, size_t len) while (42) { t = atomic_load_explicit((atomic_int*) &lrb->lrb_tail, memory_order_acquire); h = atomic_load_explicit((atomic_int*) &lrb->lrb_head, memory_order_acquire); + f = atomic_load_explicit((atomic_int*) &lrb->lrb_full, memory_order_acquire); l = h - t; if (l < 0) l += lrb->lrb_size; - if (!l) - return 0; + if (!l) { + if (!f) + return 0; + l = lrb->lrb_size; + } if (l > len) l = len; @@ -430,8 +491,10 @@ lrb_dequeue(lrbuf_t *lrb, void *data, size_t len) n = t; if (atomic_compare_exchange_weak_explicit((atomic_int*) &lrb->lrb_tail, - &n, t2, memory_order_release, memory_order_relaxed)) + &n, t2, memory_order_release, memory_order_relaxed)) { + atomic_store_explicit((atomic_int*) &lrb->lrb_full, 0, memory_order_release); return l; + } } return 0;