--- libelwix/inc/elwix/aring.h 2025/09/30 11:38:28 1.4 +++ libelwix/inc/elwix/aring.h 2026/02/18 11:41:47 1.9 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: aring.h,v 1.4 2025/09/30 11:38:28 misho Exp $ +* $Id: aring.h,v 1.9 2026/02/18 11:41:47 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -12,7 +12,7 @@ terms: All of the documentation and software included in the ELWIX and AITNET Releases is copyrighted by ELWIX - Sofia/Bulgaria -Copyright 2004 - 2025 +Copyright 2004 - 2026 by Michael Pounov . All rights reserved. Redistribution and use in source and binary forms, with or without @@ -51,11 +51,69 @@ SUCH DAMAGE. typedef struct { E_ATOMIC_ALIGN int rb_head; E_ATOMIC_ALIGN int rb_tail; + E_ATOMIC_ALIGN unsigned int rb_full; int rb_bufnum; struct iovec *rb_buffer; } ringbuf_t; +#define rbuf_head(x) atomic_load_explicit((atomic_int*) &(x)->rb_head, memory_order_relaxed) +#define rbuf_tail(x) atomic_load_explicit((atomic_int*) &(x)->rb_tail, memory_order_relaxed) +#define rbuf_hptr(x) ((x)->rb_buffer + rbuf_head((x))) +#define rbuf_tptr(x) ((x)->rb_buffer + rbuf_tail((x))) +#define rbuf_ptr(x, n) ((x)->rb_buffer + ((rbuf_tail((x)) + (n)) % (x)->rb_bufnum)) +#define rbuf_num(x) ((x)->rb_bufnum) +#define rbuf_getb(x) ((x)->rb_buffer) +#define rbuf_get(x, n) *rbuf_ptr((x), (n)) +#define rbuf_isrewind(x) (rbuf_head((x)) < rbuf_tail((x))) +#define rbuf_queued(x, r) do { \ + u_int _h, _t; \ + _t = atomic_load_explicit((atomic_int*) &(x)->rb_tail, memory_order_acquire); \ + _h = atomic_load_explicit((atomic_int*) &(x)->rb_head, memory_order_relaxed); \ + if (_h == _t) \ + (r) = atomic_load_explicit((atomic_int*) &(x)->rb_full, memory_order_acquire) ? \ + (x)->rb_bufnum : 0; \ + else \ + (r) = (_h + (x)->rb_bufnum - _t) % (x)->rb_bufnum; \ + } while (0) +#define rbuf_unused(x, r) do { \ + u_int _r; \ + rbuf_queued((x), _r); \ + (r) = (x)->rb_bufnum - _r; \ + } while (0) +typedef struct { + E_ATOMIC_ALIGN unsigned int lrb_head; + E_ATOMIC_ALIGN unsigned int lrb_tail; + E_ATOMIC_ALIGN unsigned int lrb_full; + int lrb_size; + unsigned char *lrb_data; +} lrbuf_t; +#define lrb_head(x) atomic_load_explicit((atomic_int*) &(x)->lrb_head, memory_order_relaxed) +#define lrb_tail(x) atomic_load_explicit((atomic_int*) &(x)->lrb_tail, memory_order_relaxed) +#define lrb_hptr(x) ((x)->lrb_data + lrb_head((x))) +#define lrb_tptr(x) ((x)->lrb_data + lrb_tail((x))) +#define lrb_ptr(x, n) ((x)->lrb_data + ((lrb_tail((x)) + (n)) % (x)->lrb_size)) +#define lrb_size(x) ((x)->lrb_size) +#define lrb_getb(x) ((x)->lrb_data) +#define lrb_getc(x, n) *lrb_ptr((x), (n)) +#define lrb_isrewind(x) (lrb_head((x)) < lrb_tail((x))) +#define lrb_queued(x, r) do { \ + u_int _h, _t; \ + _t = atomic_load_explicit((atomic_int*) &(x)->lrb_tail, memory_order_acquire); \ + _h = atomic_load_explicit((atomic_int*) &(x)->lrb_head, memory_order_relaxed); \ + if (_h == _t) \ + (r) = atomic_load_explicit((atomic_int*) &(x)->lrb_full, memory_order_acquire) ? \ + (x)->lrb_size : 0; \ + else \ + (r) = (_h + (x)->lrb_size - _t) % (x)->lrb_size; \ + } while (0) +#define lrb_unused(x, r) do { \ + u_int _r; \ + lrb_queued((x), _r); \ + (r) = (x)->lrb_size - _r; \ + } while (0) + + /* * rbuf_init() - Init ring buffer * @@ -99,9 +157,10 @@ int rbuf_isfull(ringbuf_t *rbuf); * @rbuf = Ring buffer * @data = Data * @len = Length + * @lost = Permit to lost data * return: -1 error, 1 can't add data, buffer is full or 0 ok */ -int rbuf_enqueue(ringbuf_t *rbuf, void *data, size_t len); +int rbuf_enqueue(ringbuf_t *rbuf, void *data, size_t len, int lost); /* * rbuf_dequeue() - Dequeue data from buffer * @@ -110,6 +169,83 @@ int rbuf_enqueue(ringbuf_t *rbuf, void *data, size_t l * return: -1 error, 1 buffer is empty or 0 ok */ int rbuf_dequeue(ringbuf_t *rbuf, struct iovec **out); + + +/* + * lrb_init() - Init linear ring buffer + * + * @lrb = Linear ring buffer + * @size = Size of ring buffer + * return: -1 error or 0 ok + */ +int lrb_init(lrbuf_t *lrb, u_int size); +/* + * lrb_free() - Free linear ring buffer + * + * @lrb = Linear ring buffer + * return: none + */ +void lrb_free(lrbuf_t *lrb); +/* + * lrb_purge() - Purge all buffer + * + * @lrb = Linear ring buffer + * return: none + */ +void lrb_purge(lrbuf_t *lrb); +/* + * lrb_isempty() - Check buffer is empty + * + * @lrb = Linear ring buffer + * return: -1 error, 0 it isn't empty + */ +int lrb_isempty(lrbuf_t *lrb); +/* + * lrb_isfull() - Check buffer is full + * + * @lrb = Linear ring buffer + * return: -1 error or 0 it isn't full + */ +int lrb_isfull(lrbuf_t *lrb); +/* + * lrb_enqueue() - Enqueue data to buffer + * + * @lrb = Linear ring buffer + * @data = Data + * @len = Length + * @lost = Permit to lost data + * return: -1 error, 1 buffer is full or 0 ok + */ +int lrb_enqueue(lrbuf_t *lrb, void *data, size_t len, int lost); +/* + * lrb_dequeue() - Dequeue data from buffer + * + * @lrb = Linear ring buffer + * @data = Data, if =NULL, just dequeue data + * @len = Length of data + * return: -1 error, 0 buffer is empty or >0 stored data bytes + */ +int lrb_dequeue(lrbuf_t *lrb, void *data, size_t len); +/* + * 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); +/* + * 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); #endif