2018-05-25 09:24:03 -04:00
|
|
|
/* Icecast
|
|
|
|
*
|
|
|
|
* This program is distributed under the GNU General Public License, version 2.
|
|
|
|
* A copy of this license is included with this source.
|
|
|
|
*
|
|
|
|
* Copyright 2018, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2018-05-28 05:14:07 -04:00
|
|
|
#include <string.h>
|
2018-05-25 09:24:03 -04:00
|
|
|
|
|
|
|
#include "common/thread/thread.h"
|
|
|
|
|
|
|
|
#include "refobject.h"
|
|
|
|
|
2018-06-06 10:38:24 -04:00
|
|
|
#define TO_BASE(x) REFOBJECT_TO_TYPE((x), refobject_base_t *)
|
2018-05-25 09:24:03 -04:00
|
|
|
|
2018-10-10 10:42:37 -04:00
|
|
|
int refobject_new__return_zero(refobject_t self, const refobject_type_t *type, va_list ap)
|
2018-10-10 10:27:07 -04:00
|
|
|
{
|
|
|
|
(void)self, (void)type, (void)ap;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
REFOBJECT_DEFINE_TYPE(refobject_base_t,
|
2018-10-10 10:42:37 -04:00
|
|
|
REFOBJECT_DEFINE_TYPE_NEW_NOOP()
|
2018-10-10 10:27:07 -04:00
|
|
|
);
|
2018-10-10 07:15:39 -04:00
|
|
|
|
|
|
|
static inline int check_type(const refobject_type_t *type)
|
|
|
|
{
|
|
|
|
return type->control_length == sizeof(refobject_type_t) && type->control_version == REFOBJECT_CONTROL_VERSION &&
|
|
|
|
type->type_length >= sizeof(refobject_base_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
refobject_t refobject_new__real(const refobject_type_t *type, void *userdata, const char *name, refobject_t associated)
|
2018-05-25 09:24:03 -04:00
|
|
|
{
|
|
|
|
refobject_base_t *ret = NULL;
|
|
|
|
|
2018-10-10 07:15:39 -04:00
|
|
|
if (!check_type(type))
|
2018-05-25 09:24:03 -04:00
|
|
|
return (refobject_t)ret;
|
|
|
|
|
2018-10-10 07:15:39 -04:00
|
|
|
ret = calloc(1, type->type_length);
|
2018-05-25 09:24:03 -04:00
|
|
|
if (ret == NULL)
|
|
|
|
return (refobject_t)ret;
|
|
|
|
|
2018-10-10 07:15:39 -04:00
|
|
|
ret->type = type;
|
2018-05-25 09:24:03 -04:00
|
|
|
ret->refc = 1;
|
|
|
|
ret->userdata = userdata;
|
|
|
|
|
|
|
|
thread_mutex_create(&(ret->lock));
|
|
|
|
|
2018-05-25 10:45:08 -04:00
|
|
|
if (name) {
|
|
|
|
ret->name = strdup(name);
|
|
|
|
if (!ret->name) {
|
|
|
|
refobject_unref(ret);
|
2018-06-06 10:38:24 -04:00
|
|
|
return REFOBJECT_NULL;
|
2018-05-25 10:45:08 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-17 03:06:36 -04:00
|
|
|
if (!REFOBJECT_IS_NULL(associated)) {
|
|
|
|
if (refobject_ref(associated) != 0) {
|
2018-05-25 10:45:08 -04:00
|
|
|
refobject_unref(ret);
|
2018-06-06 10:38:24 -04:00
|
|
|
return REFOBJECT_NULL;
|
2018-05-25 10:45:08 -04:00
|
|
|
}
|
|
|
|
|
2018-06-17 03:06:36 -04:00
|
|
|
ret->associated = associated;
|
2018-05-25 10:45:08 -04:00
|
|
|
}
|
|
|
|
|
2018-05-25 09:24:03 -04:00
|
|
|
return (refobject_t)ret;
|
|
|
|
}
|
|
|
|
|
2018-10-10 10:27:07 -04:00
|
|
|
refobject_t refobject_new__simple(const refobject_type_t *type, void *userdata, const char *name, refobject_t associated, ...)
|
|
|
|
{
|
|
|
|
refobject_t ret;
|
|
|
|
int res;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
if (!check_type(type))
|
|
|
|
return REFOBJECT_NULL;
|
|
|
|
|
|
|
|
if (!type->type_newcb)
|
|
|
|
return REFOBJECT_NULL;
|
|
|
|
|
|
|
|
ret = refobject_new__real(type, userdata, name, associated);
|
|
|
|
if (REFOBJECT_IS_NULL(ret))
|
|
|
|
return REFOBJECT_NULL;
|
|
|
|
|
|
|
|
va_start(ap, associated);
|
|
|
|
res = type->type_newcb(ret, type, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (res != 0) {
|
|
|
|
refobject_unref(ret);
|
|
|
|
return REFOBJECT_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-05-25 09:24:03 -04:00
|
|
|
int refobject_ref(refobject_t self)
|
|
|
|
{
|
2018-06-06 10:38:24 -04:00
|
|
|
if (REFOBJECT_IS_NULL(self))
|
2018-05-25 09:24:03 -04:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
thread_mutex_lock(&(TO_BASE(self)->lock));
|
|
|
|
TO_BASE(self)->refc++;
|
|
|
|
thread_mutex_unlock(&(TO_BASE(self)->lock));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int refobject_unref(refobject_t self)
|
|
|
|
{
|
|
|
|
register refobject_base_t *base = TO_BASE(self);
|
|
|
|
|
2018-06-06 10:38:24 -04:00
|
|
|
if (REFOBJECT_IS_NULL(self))
|
2018-05-25 09:24:03 -04:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
thread_mutex_lock(&(base->lock));
|
|
|
|
base->refc--;
|
|
|
|
if (base->refc) {
|
|
|
|
thread_mutex_unlock(&(base->lock));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-10-10 07:15:39 -04:00
|
|
|
if (base->type->type_freecb)
|
|
|
|
base->type->type_freecb(self, &(base->userdata));
|
2018-05-25 09:24:03 -04:00
|
|
|
|
|
|
|
if (base->userdata)
|
|
|
|
free(base->userdata);
|
|
|
|
|
2018-05-25 10:45:08 -04:00
|
|
|
if (base->name)
|
|
|
|
free(base->name);
|
|
|
|
|
2018-05-25 09:24:03 -04:00
|
|
|
thread_mutex_unlock(&(base->lock));
|
|
|
|
thread_mutex_destroy(&(base->lock));
|
|
|
|
|
2018-06-06 06:49:01 -04:00
|
|
|
free(base);
|
|
|
|
|
2018-05-25 09:24:03 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void * refobject_get_userdata(refobject_t self)
|
|
|
|
{
|
|
|
|
void *ret;
|
|
|
|
|
2018-06-06 10:38:24 -04:00
|
|
|
if (REFOBJECT_IS_NULL(self))
|
2018-05-25 09:24:03 -04:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
thread_mutex_lock(&(TO_BASE(self)->lock));
|
|
|
|
ret = TO_BASE(self)->userdata;
|
|
|
|
thread_mutex_unlock(&(TO_BASE(self)->lock));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int refobject_set_userdata(refobject_t self, void *userdata)
|
|
|
|
{
|
2018-06-06 10:38:24 -04:00
|
|
|
if (REFOBJECT_IS_NULL(self))
|
2018-05-25 09:24:03 -04:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
thread_mutex_lock(&(TO_BASE(self)->lock));
|
|
|
|
TO_BASE(self)->userdata = userdata;
|
|
|
|
thread_mutex_unlock(&(TO_BASE(self)->lock));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2018-05-25 10:45:08 -04:00
|
|
|
|
|
|
|
const char * refobject_get_name(refobject_t self)
|
|
|
|
{
|
|
|
|
const char *ret;
|
|
|
|
|
2018-06-06 10:38:24 -04:00
|
|
|
if (REFOBJECT_IS_NULL(self))
|
2018-05-25 10:45:08 -04:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
thread_mutex_lock(&(TO_BASE(self)->lock));
|
|
|
|
ret = TO_BASE(self)->name;
|
|
|
|
thread_mutex_unlock(&(TO_BASE(self)->lock));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-06-17 03:06:36 -04:00
|
|
|
refobject_t refobject_get_associated(refobject_t self)
|
2018-05-25 10:45:08 -04:00
|
|
|
{
|
|
|
|
refobject_t ret;
|
|
|
|
|
2018-06-06 10:38:24 -04:00
|
|
|
if (REFOBJECT_IS_NULL(self))
|
|
|
|
return REFOBJECT_NULL;
|
2018-05-25 10:45:08 -04:00
|
|
|
|
|
|
|
thread_mutex_lock(&(TO_BASE(self)->lock));
|
2018-06-17 03:06:36 -04:00
|
|
|
ret = TO_BASE(self)->associated;
|
2018-05-25 10:45:08 -04:00
|
|
|
thread_mutex_unlock(&(TO_BASE(self)->lock));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|