#include #include #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; }