myxce/src/lib/objmgr.c

306 lines
5.3 KiB
C

#include <errno.h>
#include <stdlib.h>
#include "htab.h"
#include "objmgr.h"
#include "utils.h"
#include "zarray.h"
static objmgr_t* objmgr_default = NULL;
static void objtype_killer(objtype_t* typeval)
{
if (typeval == NULL) {
return;
}
if (typeval->fn_type_fini == NULL) {
return;
}
typeval->fn_type_fini(typeval);
}
int objmgr_init(objmgr_t* mgr)
{
if (mgr == NULL) {
return -EINVAL;
}
mylock_init(&(mgr->lock));
ht_init(&(mgr->names), 32, string_hash_key);
zarray_init(&(mgr->types), 32, (zarray_item_killer_t)objtype_killer);
return 0;
}
void objmgr_fini(objmgr_t* mgr)
{
if (mgr == NULL) {
return;
}
zarray_fini(&(mgr->types));
ht_fini(&(mgr->names));
mylock_fini(&(mgr->lock));
}
static int objmgr_register_internal(objmgr_t* mgr, objtype_t* type)
{
hent_t* e = NULL;
int idx;
e = ht_get(&(mgr->names), (void*)type->type);
if (e != NULL) {
return e->data;
}
e = ht_add(&(mgr->names), (void*)type->type);
if (e == NULL) {
return -ENOMEM;
}
idx = zarray_store(&(mgr->types), type);
if (idx < 0) {
ht_del(&(mgr->names), (void*)type->type);
return idx;
}
e->data = idx;
return idx;
}
int obj_init(objmgr_t* mgr, objtype_t* type, int32_t exdata, myobj_t* obj)
{
obj->type = type;
obj->nref = 1;
obj->nread = 0;
obj->nwrite = 0;
obj->exdata = exdata;
obj->magic = OBJ_MAGIC;
my_rwlock_init(&(obj->rwlock));
mylock_init(&(obj->lock));
return 1;
}
int objmgr_register(objmgr_t* mgr, objtype_t* type)
{
int rc = 0;
/* clang-format off */
if ((mgr == NULL) ||
(type == NULL) ||
(type->type == NULL) ||
(type->fn_create == NULL)) {
return -EINVAL;
}
/* clang-format on */
mylock_init(&(type->lock));
mylock_lock(&(mgr->lock));
rc = objmgr_register_internal(mgr, type);
mylock_unlock(&(mgr->lock));
return rc;
}
static void* create_obj_ex(objmgr_t* mgr, int type, va_list ap)
{
objtype_t* typeval = NULL;
void* obj;
if ((type < 0) || (type >= mgr->types.caps)) {
SET_ERROR(EINVAL);
return NULL;
}
typeval = (objtype_t*)zarray_get(&(mgr->types), type);
if (typeval == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
obj = typeval->fn_create(mgr, typeval, ap);
return obj;
}
void* create_obj_by_typeid(objmgr_t* mgr, int type, ...)
{
va_list ap;
void* p = NULL;
va_start(ap, type);
p = create_obj_ex(mgr, type, ap);
va_end(ap);
return p;
}
void* create_obj_by_typename(objmgr_t* mgr, char* type, ...)
{
hent_t* e;
va_list ap;
void* p = NULL;
mylock_lock(&(mgr->lock));
e = ht_get(&(mgr->names), (void*)type);
mylock_unlock(&(mgr->lock));
if (e == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
if (e->data < 0) {
SET_ERROR(EINVAL);
return NULL;
}
va_start(ap, type);
p = create_obj_ex(mgr, e->data, ap);
va_end(ap);
return p;
}
int typeid_of_name(objmgr_t* mgr, char* type)
{
hent_t* e;
int typeid;
mylock_lock(&(mgr->lock));
e = ht_get(&(mgr->names), (void*)type);
if (e == NULL) {
typeid = -ENOENT;
} else {
typeid = e->data;
}
mylock_unlock(&(mgr->lock));
return typeid;
}
void* obj_ref(void* obj, int op)
{
myobj_t* myobj;
if (obj == NULL) {
SET_ERROR(EINVAL);
return NULL;
}
myobj = TO_MYOBJ(obj);
if (myobj->magic != OBJ_MAGIC) {
SET_ERROR(EINVAL);
return NULL;
}
switch (op) {
case OBJREF_READ:
my_rwlock_rlock(&(myobj->rwlock));
break;
case OBJREF_UPDATE:
my_rwlock_wlock(&(myobj->rwlock));
break;
default:
break;
}
mylock_lock(&(myobj->lock));
switch (op) {
case OBJREF_READ:
myobj->nread++;
break;
case OBJREF_UPDATE:
myobj->nwrite++;
break;
default:
break;
}
myobj->nref++;
mylock_unlock(&(myobj->lock));
return obj;
}
void obj_deref(void* obj)
{
myobj_t* myobj;
int nc;
objtype_t* typeval;
int release_rwlock = 0;
if (obj == NULL) {
SET_ERROR(EINVAL);
return;
}
myobj = TO_MYOBJ(obj);
if (myobj->magic != OBJ_MAGIC) {
SET_ERROR(EINVAL);
return;
}
/* the object lock should be held */
mylock_lock(&(myobj->lock));
myobj->nref--;
nc = myobj->nref;
if ((myobj->nread > 0) || (myobj->nwrite > 0)) {
release_rwlock = 1;
if (myobj->nread > 0) {
myobj->nread--;
} else {
myobj->nwrite--;
}
}
mylock_unlock(&(myobj->lock));
if (release_rwlock) {
my_rwlock_unlock(&(myobj->rwlock));
}
if (nc > 0) {
return;
}
typeval = myobj->type;
if (typeval == NULL) {
return;
}
if (typeval->fn_fini != NULL) {
typeval->fn_fini(obj);
}
return;
}
objmgr_t* objmgr_get_default() { return objmgr_default; }
int objmgr_set_default(objmgr_t* mgr)
{
objmgr_default = mgr;
return 0;
}
myobj_t* obj_alloc(size_t size)
{
myobj_t* obj;
if (size <= 0) {
SET_ERROR(EINVAL);
return NULL;
}
obj = (myobj_t*)calloc(1, sizeof(*obj) + size);
return obj;
}