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-06-17 03:06:36 -04:00
|
|
|
refobject_t refobject_new(size_t len, refobject_free_t freecb, void *userdata, const char *name, refobject_t associated)
|
2018-05-25 09:24:03 -04:00
|
|
|
{
|
|
|
|
refobject_base_t *ret = NULL;
|
|
|
|
|
|
|
|
if (len < sizeof(refobject_base_t))
|
|
|
|
return (refobject_t)ret;
|
|
|
|
|
|
|
|
ret = calloc(1, len);
|
|
|
|
if (ret == NULL)
|
|
|
|
return (refobject_t)ret;
|
|
|
|
|
|
|
|
ret->refc = 1;
|
|
|
|
ret->freecb = freecb;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (base->freecb)
|
|
|
|
base->freecb(self, &(base->userdata));
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|