add xzarray_t for replacement of zarray_t finally

This commit is contained in:
Rongsong Shen 2026-02-20 11:25:42 +08:00
parent ce69347581
commit f582742e77
5 changed files with 465 additions and 101 deletions

View file

@ -1,7 +1,10 @@
#include <errno.h>
#include <rtti.h>
#include <stdlib.h>
#include <string.h>
#include "bitset.h"
#include "mylock.h"
#include "utils.h"
#include "zarray.h"
@ -323,8 +326,7 @@ int zarray_get_ex(zarray_t* array, int count, int* idxs, void** data)
if (idx >= array->caps) {
data[i] = NULL;
}
else {
} else {
data[i] = array->data[idx];
}
}
@ -347,3 +349,323 @@ void* zarray_get(zarray_t* array, int idx)
return datas[0];
}
typedef struct {
mylock_t lock;
} xzarray_private_t;
typedef struct {
unsigned int inuse : 1;
void* data;
} xzarray_item_t;
typedef struct {
int count;
size_t caps;
size_t delta;
int pos;
xzarray_item_t* data;
destroy_fn_t killer;
} xzarray_t;
static size_t xzarray_datasize(va_list ap)
{
size_t sz = sizeof(xzarray_t);
return sz;
}
static int xzarray_init(meta_obj_t* obj, va_list ap)
{
xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj);
xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj);
size_t delta = va_arg(ap, size_t);
destroy_fn_t killer = va_arg(ap, destroy_fn_t);
if (delta < 1) {
return -EINVAL;
}
a->count = 0;
a->caps = 0;
a->delta = delta;
a->data = NULL;
a->pos = 0;
a->killer = killer;
mylock_init(&(priv->lock));
return 1;
}
static void xzarray_destroy(meta_obj_t* obj)
{
xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj);
xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj);
int i;
for (i = 0; i < a->caps; i++) {
if (a->data[i].inuse) {
if (a->killer != NULL) {
a->killer(a->data[i].data);
}
}
}
FREEUP(a->data);
mylock_fini(&(priv->lock));
}
static int xzarray_ensure_items(xzarray_t* array, int mincap)
{
int nc, i;
void* p;
if (mincap < array->caps) {
return 1;
}
nc = mincap;
if (nc < array->caps + array->delta) {
nc = array->caps + array->delta;
}
p = (xzarray_item_t*)realloc(array->data, nc * sizeof(xzarray_item_t));
if (p == NULL) {
return -ENOMEM;
}
array->data = p;
for (i = array->caps; i < nc; i++) {
array->data[i].inuse = 0;
array->data[i].data = NULL;
}
/* this will make we can get next free
* location quickly
*/
array->pos = array->caps;
array->caps = nc;
return 1;
}
static int xzarray_store(meta_obj_t* obj, void* data)
{
xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj);
xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj);
int rc = 0;
mylock_lock(&(priv->lock));
rc = xzarray_ensure_items(a, a->count + 1);
if (rc >= 0) {
int idx, i;
rc = -ENOMEM;
idx = a->pos;
for (i = 0; i < a->caps; i++) {
if (a->data[idx].inuse == 0) {
a->data[idx].inuse = 1;
a->data[idx].data = data;
a->count++;
rc = idx;
}
idx++;
if (idx >= a->caps) {
idx = 0;
}
}
if (rc >= 0) {
a->pos = (rc + 1) % a->caps;
}
}
mylock_unlock(&(priv->lock));
return rc;
}
static int xzarray_get_vec(meta_obj_t* obj, int count, int* idxs, void** data)
{
xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj);
xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj);
int i;
int rc = 0;
if ((count <= 0) || (idxs == NULL) || (data == NULL)) {
return -EINVAL;
}
mylock_lock(&(priv->lock));
for (i = 0; i < count; i++) {
int idx = idxs[i];
if ((idx >= a->caps) || (a->data[idx].inuse == 0)) {
rc = -ENOENT;
break;
}
}
if (rc == 0) {
for (i = 0; i < count; i++) {
int idx = idxs[i];
data[i] = a->data[idx].data;
}
}
mylock_unlock(&(priv->lock));
return rc;
}
static int xzarray_get(meta_obj_t* obj, int idx, void** data)
{
int idxs[] = { idx };
return xzarray_get_vec(obj, 1, (int*)&idxs[0], data);
}
static int xzarray_put_vec(meta_obj_t* obj, int count, int* idxs, void** data)
{
xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj);
xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj);
int i, rc, maxid;
if ((count < 1) || (idxs == NULL) || (data == NULL)) {
return -EINVAL;
}
mylock_lock(&(priv->lock));
maxid = 0;
rc = 0;
for (i = 0; i < count; i++) {
if (idxs[i] < 0) {
rc = -EINVAL;
break;
}
if (maxid < idxs[i]) {
maxid = idxs[i];
}
}
if (rc >= 0) {
rc = xzarray_ensure_items(a, maxid + 1);
}
if (rc >= 0) {
for (i = 0; i < count; i++) {
int idx = idxs[i];
if (a->data[idx].inuse == 1) {
if (a->killer != NULL) {
a->killer(a->data[idx].data);
}
}
a->data[idx].data = data[i];
a->data[idx].inuse = 1;
}
}
mylock_unlock(&(priv->lock));
return rc;
}
static int xzarray_put(meta_obj_t* obj, int idx, void* data)
{
int idxs[] = { idx };
void* datas[] = { data };
return xzarray_put_vec(obj, 1, &(idxs[0]), &(datas[0]));
}
static int xzarray_clear(meta_obj_t* obj, int idx)
{
xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, obj);
xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(obj);
int rc = -EINVAL;
mylock_lock(&(priv->lock));
if (idx < a->caps) {
rc = 0;
if (a->data[idx].inuse) {
if (a->killer != NULL) {
a->killer(a->data[idx].data);
}
}
a->data[idx].inuse = 0;
a->data[idx].data = NULL;
a->pos = idx; /* we can find the available idx next time */
}
mylock_unlock(&(priv->lock));
return rc;
}
static int xzarray_make_iter(iterator_t* iter, va_list ap)
{
xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(iter->obj);
mylock_lock(&(priv->lock));
iter->data = (void*)(long)0;
return RTTI_ITER_OK;
}
static int xzarray_iter_next(iterator_t* iter, void** data)
{
xzarray_t* a = RTTI_OBJ_TO_DATA(xzarray_t, iter->obj);
int i;
for (i = (int)(long)iter->data; i < a->caps; i++) {
if (a->data[i].inuse) {
*data = a->data[i].data;
iter->data = (void*)(long)(i + 1);
return RTTI_ITER_OK;
}
}
return RTTI_ITER_NO_DATA;
}
static int xzarray_iter_reset(iterator_t* iter)
{
iter->data = (void*)(long)0;
return RTTI_ITER_OK;
}
static void xzarray_iter_destroy(iterator_t* iter)
{
xzarray_private_t* priv = (xzarray_private_t*)RTTI_OBJ_TO_PRIV(iter->obj);
mylock_unlock(&(priv->lock));
return;
}
typeinfo_t xzarray_type = {
.name = "xzarray",
.privateSize = sizeof(xzarray_private_t),
.dataSize = (datasize_fn_t)xzarray_datasize,
.init = (obj_init_fn_t)xzarray_init,
.destroy = (obj_destroy_fn_t)xzarray_destroy,
.interfaces
= { .varray = &(intf_varray_t) { .vstore = (vstore_fn_t)xzarray_store,
.vget = (vget_fn_t)xzarray_get,
.vget_vec = (vget_vec_fn_t)xzarray_get_vec,
.vput = (vput_fn_t)xzarray_put,
.vput_vec = (vput_vec_fn_t)xzarray_put_vec,
.vclear = (vclear_fn_t)xzarray_clear },
.iter
= &(intf_iterator_t) { .make = (iter_make_fn_t)xzarray_make_iter,
.next = (iter_next_fn_t)xzarray_iter_next,
.reset = (iter_reset_fn_t)xzarray_iter_reset,
.destroy
= (iter_destroy_fn_t)xzarray_iter_destroy } }
};