Files
2026-08-24 10:03:24 +08:00

252 lines
5.2 KiB
C

#include <stdlib.h>
#include <string.h>
#include "dataserver_utils.h"
#include "dataserver_rb.h"
typedef struct {
struct list_head head;
size_t bs;
} ds_rb_bs_t;
static int _ds_rb_init(ds_rb_t *rb)
{
if (rb->lock_g_ptr)
rb->lock_g_ptr(rb->g, 1);
if (!rb->initialized) {
{
pthread_condattr_t cattr;
pthread_condattr_init(&cattr);
pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
pthread_cond_init(&rb->cond, &cattr);
pthread_condattr_destroy(&cattr);
}
pthread_mutex_init(&rb->lock, NULL);
pthread_mutex_lock(&rb->lock);
rb->initialized = 1;
rb->flag = 0;
pthread_mutex_unlock(&rb->lock);
}
if (rb->lock_g_ptr)
rb->lock_g_ptr(rb->g, 0);
return 0;
}
int ds_rb_init(ds_rb_t *rb, size_t size)
{
_ds_rb_init(rb);
pthread_mutex_lock(&rb->lock);
rb->pread = rb->pwrite = 0;
rb->data = (uint8_t*)malloc(size);
if (!rb->data) {
pthread_mutex_unlock(&rb->lock);
return -1;
}
rb->size = size;
INIT_LIST_HEAD(&rb->queue);
pthread_mutex_init(&rb->queue_lock, NULL);
pthread_mutex_unlock(&rb->lock);
return 0;
}
int ds_rb_deinit(ds_rb_t *rb)
{
pthread_mutex_lock(&rb->lock);
if (rb->data) {
free(rb->data);
rb->data = NULL;
rb->pread = rb->pwrite = 0;
rb->size = 0;
rb->flag = 0;
//pthread_cond_destroy(&rb->cond);
{
ds_rb_bs_t *rbs, *tmp;
pthread_mutex_lock(&rb->queue_lock);
list_for_each_entry_safe(rbs, tmp, &rb->queue, head) {
list_del(&rbs->head);
free(rbs);
}
pthread_mutex_unlock(&rb->queue_lock);
//pthread_mutex_destroy(&rb->queue_lock);
}
}
pthread_mutex_unlock(&rb->lock);
//pthread_mutex_destroy(&rb->lock);
return 0;
}
int ds_rb_empty(ds_rb_t *rb)
{
int empty;
pthread_mutex_lock(&rb->lock);
empty = (rb->pread == rb->pwrite)? 1 : 0;
pthread_mutex_unlock(&rb->lock);
return empty;
}
ssize_t ds_rb_free(ds_rb_t *rb)
{
ssize_t free;
pthread_mutex_lock(&rb->lock);
free = rb->pread - rb->pwrite;
if (free <= 0)
free += rb->size;
pthread_mutex_unlock(&rb->lock);
return free - 1;
}
ssize_t ds_rb_avail(ds_rb_t *rb)
{
ssize_t avail;
pthread_mutex_lock(&rb->lock);
avail = rb->pwrite - rb->pread;
if (avail < 0)
avail += rb->size;
pthread_mutex_unlock(&rb->lock);
return avail;
}
ssize_t ds_rb_read(ds_rb_t *rb, uint8_t *buf, size_t len)
{
size_t todo = len;
size_t split;
pthread_mutex_lock(&rb->lock);
if (!rb->data) {
pthread_mutex_unlock(&rb->lock);
return 0;
}
split = ((ssize_t)(rb->pread + len) > rb->size) ? rb->size - rb->pread : 0;
if (split > 0) {
memcpy(buf, rb->data + rb->pread, split);
buf += split;
todo -= split;
rb->pread = 0;
}
memcpy(buf, rb->data + rb->pread, todo);
rb->pread = (rb->pread + todo) % rb->size;
pthread_mutex_unlock(&rb->lock);
return len;
}
ssize_t ds_rb_write(ds_rb_t *rb, const uint8_t *buf, size_t len)
{
size_t todo = len;
size_t split;
pthread_mutex_lock(&rb->lock);
if (!rb->data) {
pthread_mutex_unlock(&rb->lock);
return 0;
}
split = ((ssize_t)(rb->pwrite + len) > rb->size) ? rb->size - rb->pwrite : 0;
if (split > 0) {
memcpy(rb->data + rb->pwrite, buf, split);
buf += split;
todo -= split;
rb->pwrite = 0;
}
memcpy(rb->data + rb->pwrite, buf, todo);
rb->pwrite = (rb->pwrite + todo) % rb->size;
//if (len > 0)
// pthread_cond_signal(&rb->cond);
pthread_mutex_unlock(&rb->lock);
return len;
}
int ds_rb_set_flag(ds_rb_t *rb, int flag)
{
_ds_rb_init(rb);
pthread_mutex_lock(&rb->lock);
rb->flag |= flag;
pthread_cond_signal(&rb->cond);
pthread_mutex_unlock(&rb->lock);
return 0;
}
int ds_rb_get_flag_timeout(ds_rb_t *rb, int timeout_ms)
{
int flag;
struct timespec ts;
_ds_rb_init(rb);
pthread_mutex_lock(&rb->lock);
if (timeout_ms) {
ds_get_timespec_timeout(10, &ts);
pthread_cond_timedwait(&rb->cond, &rb->lock, &ts);
}
flag = rb->flag;
pthread_mutex_unlock(&rb->lock);
return flag;
}
int ds_rb_queue_block(ds_rb_t *rb, size_t bs)
{
ds_rb_bs_t *rbs = (ds_rb_bs_t *)malloc(sizeof(ds_rb_bs_t));
if (!rbs)
return -1;
rbs->bs = bs;
pthread_mutex_lock(&rb->queue_lock);
list_add_tail(&rbs->head, &rb->queue);
pthread_mutex_unlock(&rb->queue_lock);
return 0;
}
int ds_rb_dequeue_block(ds_rb_t *rb, size_t *bs)
{
int ret = 0;
pthread_mutex_lock(&rb->queue_lock);
if (list_empty(&rb->queue)) {
*bs = 0;
ret = -1;
} else {
ds_rb_bs_t *rbs = list_first_entry(&rb->queue, ds_rb_bs_t, head);
*bs = rbs->bs;
list_del(&rbs->head);
free(rbs);
}
pthread_mutex_unlock(&rb->queue_lock);
return ret;
}
int ds_rb_init_lock(ds_rb_t *rb, ds_rb_lock_ptr_t lock_g_ptr, void *g)
{
rb->lock_g_ptr = lock_g_ptr;
rb->g = g;
return 0;
}