From a9d391ffbc9f90b957e48a5902f8f8b05a59f1e2 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Fri, 25 May 2018 13:24:03 +0000 Subject: [PATCH] Feature: Added generic reference object --- src/Makefile.am | 2 + src/icecasttypes.h | 16 +++++++ src/refobject.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ src/refobject.h | 32 ++++++++++++++ 4 files changed, 157 insertions(+) create mode 100644 src/refobject.c create mode 100644 src/refobject.h diff --git a/src/Makefile.am b/src/Makefile.am index e2233d72..e3a3d9d8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,6 +29,7 @@ noinst_HEADERS = \ md5.h \ matchfile.h \ tls.h \ + refobject.h \ event.h \ event_log.h \ event_exec.h \ @@ -68,6 +69,7 @@ icecast_SOURCES = \ md5.c \ matchfile.c \ tls.c \ + refobject.c \ format.c \ format_ogg.c \ format_mp3.c \ diff --git a/src/icecasttypes.h b/src/icecasttypes.h index 941c13f7..0474e0f3 100644 --- a/src/icecasttypes.h +++ b/src/icecasttypes.h @@ -9,6 +9,10 @@ #ifndef __ICECASTTYPES_H__ #define __ICECASTTYPES_H__ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "compat.h" /* ---[ client.[ch] ]--- */ @@ -88,4 +92,16 @@ typedef enum { typedef struct _relay_server relay_server; +/* ---[ refobject.[ch] ]--- */ + +typedef struct refobject_base_tag refobject_base_t; + +#ifdef HAVE_TYPE_ATTRIBUTE_TRANSPARENT_UNION +typedef union __attribute__ ((__transparent_union__)) { + refobject_base_t *refobject_base; +} refobject_t; +#else +typedef void * refobject_t; +#endif + #endif diff --git a/src/refobject.c b/src/refobject.c new file mode 100644 index 00000000..12fc7aa7 --- /dev/null +++ b/src/refobject.c @@ -0,0 +1,107 @@ +/* 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 , + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "common/thread/thread.h" + +#include "refobject.h" + +#ifdef HAVE_TYPE_ATTRIBUTE_TRANSPARENT_UNION +#define TO_BASE(x) ((x).refobject_base) +#else +#define TO_BASE(x) ((refobject_base_t*)(x)) +#endif + +refobject_t refobject_new(size_t len, refobject_free freecb, void *userdata) +{ + 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)); + + return (refobject_t)ret; +} + +int refobject_ref(refobject_t self) +{ + if (TO_BASE(self) == NULL) + 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); + + if (base == NULL) + 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); + + thread_mutex_unlock(&(base->lock)); + thread_mutex_destroy(&(base->lock)); + + return 0; +} + +void * refobject_get_userdata(refobject_t self) +{ + void *ret; + + if (TO_BASE(self) == NULL) + 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) +{ + if (TO_BASE(self) == NULL) + return -1; + + thread_mutex_lock(&(TO_BASE(self)->lock)); + TO_BASE(self)->userdata = userdata; + thread_mutex_unlock(&(TO_BASE(self)->lock)); + + return 0; +} diff --git a/src/refobject.h b/src/refobject.h new file mode 100644 index 00000000..4bb66050 --- /dev/null +++ b/src/refobject.h @@ -0,0 +1,32 @@ +/* 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 , + */ + +#ifndef __REFOBJECT_H__ +#define __REFOBJECT_H__ + +#include "common/thread/thread.h" + +#include "icecasttypes.h" +#include "compat.h" + +typedef void (*refobject_free)(refobject_t self, void **userdata); + +struct refobject_base_tag { + size_t refc; + mutex_t lock; + void *userdata; + refobject_free freecb; +}; + +refobject_t refobject_new(size_t len, refobject_free freecb, void *userdata); +int refobject_ref(refobject_t self); +int refobject_unref(refobject_t self); +void * refobject_get_userdata(refobject_t self); +int refobject_set_userdata(refobject_t self, void *userdata); + +#endif