1
0
mirror of https://gitlab.xiph.org/xiph/icecast-common.git synced 2024-12-04 14:46:31 -05:00

Feature: Implemented weak refobject references

This commit is contained in:
Philipp Schafft 2018-12-18 20:16:54 +00:00
parent 3028728484
commit a98da37c93
2 changed files with 78 additions and 5 deletions

View File

@ -75,8 +75,9 @@ struct igloo_ro_type_tag {
struct igloo_ro_base_tag {
/* Type of the object */
const igloo_ro_type_t * type;
/* Reference counter */
/* Reference counters */
size_t refc;
size_t wrefc;
/* Mutex for igloo_ro_*(). */
igloo_mutex_t lock;
/* Name of the object. */
@ -101,7 +102,7 @@ int igloo_ro_new__return_zero(igloo_ro_t self, const igloo_ro_type_t *type, va_l
#define igloo_RO_GET_TYPE(x) (igloo_RO__GETBASE((x)) == NULL ? NULL : igloo_RO__GETBASE((x))->type)
#define igloo_RO_GET_TYPENAME(x) (igloo_RO_GET_TYPE((x)) == NULL ? NULL : igloo_RO_GET_TYPE((x))->type_name)
#define igloo_RO_IS_VALID(x,type) (!igloo_RO_IS_NULL((x)) && igloo_RO_GET_TYPE((x)) == (igloo_ro__type__ ## type))
#define igloo_RO_IS_VALID(x,type) (!igloo_RO_IS_NULL((x)) && igloo_RO_GET_TYPE((x)) == (igloo_ro__type__ ## type) && igloo_RO__GETBASE((x))->refc)
#define igloo_RO_HAS_TYPE(x,type) (!igloo_RO_IS_NULL((x)) && igloo_RO_GET_TYPE((x)) == (type))
/* Create a new refobject
@ -124,6 +125,10 @@ int igloo_ro_ref(igloo_ro_t self);
*/
int igloo_ro_unref(igloo_ro_t self);
/* This is the same as igloo_ro_ref() and igloo_ro_unref() but increases/decreases the week refernece counter. */
int igloo_ro_weak_ref(igloo_ro_t self);
int igloo_ro_weak_unref(igloo_ro_t self);
/* This gets the object's name */
const char * igloo_ro_get_name(igloo_ro_t self);

View File

@ -115,12 +115,24 @@ int igloo_ro_ref(igloo_ro_t self)
return -1;
igloo_thread_mutex_lock(&(base->lock));
if (!base->refc) {
igloo_thread_mutex_unlock(&(base->lock));
return -1;
}
base->refc++;
igloo_thread_mutex_unlock(&(base->lock));
return 0;
}
static inline void igloo_ro__destory(igloo_ro_base_t *base)
{
igloo_thread_mutex_unlock(&(base->lock));
igloo_thread_mutex_destroy(&(base->lock));
free(base);
}
int igloo_ro_unref(igloo_ro_t self)
{
igloo_ro_base_t *base = igloo_RO__GETBASE(self);
@ -129,6 +141,12 @@ int igloo_ro_unref(igloo_ro_t self)
return -1;
igloo_thread_mutex_lock(&(base->lock));
if (!base->refc) {
igloo_thread_mutex_unlock(&(base->lock));
return -1;
}
base->refc--;
if (base->refc) {
@ -144,10 +162,47 @@ int igloo_ro_unref(igloo_ro_t self)
if (base->name)
free(base->name);
igloo_thread_mutex_unlock(&(base->lock));
igloo_thread_mutex_destroy(&(base->lock));
if (base->wrefc) {
/* only clear the object */
base->associated = igloo_RO_NULL;
base->name = NULL;
} else {
igloo_ro__destory(base);
}
free(base);
return 0;
}
int igloo_ro_weak_ref(igloo_ro_t self)
{
igloo_ro_base_t *base = igloo_RO__GETBASE(self);
if (!base)
return -1;
igloo_thread_mutex_lock(&(base->lock));
base->wrefc++;
igloo_thread_mutex_unlock(&(base->lock));
return 0;
}
int igloo_ro_weak_unref(igloo_ro_t self)
{
igloo_ro_base_t *base = igloo_RO__GETBASE(self);
if (!base)
return -1;
igloo_thread_mutex_lock(&(base->lock));
base->wrefc--;
if (base->refc || base->wrefc) {
igloo_thread_mutex_unlock(&(base->lock));
return 0;
}
igloo_ro__destory(base);
return 0;
}
@ -161,6 +216,10 @@ const char * igloo_ro_get_name(igloo_ro_t self)
return NULL;
igloo_thread_mutex_lock(&(base->lock));
if (!base->refc) {
igloo_thread_mutex_unlock(&(base->lock));
return NULL;
}
ret = base->name;
igloo_thread_mutex_unlock(&(base->lock));
@ -176,6 +235,10 @@ igloo_ro_t igloo_ro_get_associated(igloo_ro_t self)
return igloo_RO_NULL;
igloo_thread_mutex_lock(&(base->lock));
if (!base->refc) {
igloo_thread_mutex_unlock(&(base->lock));
return igloo_RO_NULL;
}
ret = base->associated;
if (!igloo_RO_IS_NULL(ret)) {
if (igloo_ro_ref(ret) != 0) {
@ -208,6 +271,11 @@ int igloo_ro_set_associated(igloo_ro_t self, igloo_ro_t associated)
}
igloo_thread_mutex_lock(&(base->lock));
if (!base->refc) {
igloo_ro_unref(associated);
igloo_thread_mutex_unlock(&(base->lock));
return -1;
}
old = base->associated;
base->associated = associated;
igloo_thread_mutex_unlock(&(base->lock));