refobject.c 3.48 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/* 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>
Philipp Schafft's avatar
Philipp Schafft committed
14
#include <string.h>
15 16 17 18 19

#include "common/thread/thread.h"

#include "refobject.h"

20
#define TO_BASE(x) REFOBJECT_TO_TYPE((x), refobject_base_t *)
21

22
REFOBJECT_DEFINE_TYPE(refobject_base_t);
23 24 25 26 27 28 29 30

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)
31 32 33
{
    refobject_base_t *ret = NULL;

34
    if (!check_type(type))
35 36
        return (refobject_t)ret;

37
    ret = calloc(1, type->type_length);
38 39 40
    if (ret == NULL)
        return (refobject_t)ret;

41
    ret->type = type;
42 43 44 45 46
    ret->refc = 1;
    ret->userdata = userdata;

    thread_mutex_create(&(ret->lock));

47 48 49 50
    if (name) {
        ret->name = strdup(name);
        if (!ret->name) {
            refobject_unref(ret);
51
            return REFOBJECT_NULL;
52 53 54
        }
    }

55 56
    if (!REFOBJECT_IS_NULL(associated)) {
        if (refobject_ref(associated) != 0) {
57
            refobject_unref(ret);
58
            return REFOBJECT_NULL;
59 60
        }

61
        ret->associated = associated;
62 63
    }

64 65 66 67 68
    return (refobject_t)ret;
}

int             refobject_ref(refobject_t self)
{
69
    if (REFOBJECT_IS_NULL(self))
70 71 72 73 74 75 76 77 78 79 80 81 82
        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);

83
    if (REFOBJECT_IS_NULL(self))
84 85 86 87 88 89 90 91 92
        return -1;

    thread_mutex_lock(&(base->lock));
    base->refc--;
    if (base->refc) {
        thread_mutex_unlock(&(base->lock));
        return 0;
    }

93 94
    if (base->type->type_freecb)
        base->type->type_freecb(self, &(base->userdata));
95 96 97 98

    if (base->userdata)
        free(base->userdata);

99 100 101
    if (base->name)
        free(base->name);

102 103 104
    thread_mutex_unlock(&(base->lock));
    thread_mutex_destroy(&(base->lock));

105 106
    free(base);

107 108 109 110 111 112 113
    return 0;
}

void *          refobject_get_userdata(refobject_t self)
{
    void *ret;

114
    if (REFOBJECT_IS_NULL(self))
115 116 117 118 119 120 121 122 123 124 125
        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)
{
126
    if (REFOBJECT_IS_NULL(self))
127 128 129 130 131 132 133 134
        return -1;

    thread_mutex_lock(&(TO_BASE(self)->lock));
    TO_BASE(self)->userdata = userdata;
    thread_mutex_unlock(&(TO_BASE(self)->lock));

    return 0;
}
135 136 137 138 139

const char *    refobject_get_name(refobject_t self)
{
    const char *ret;

140
    if (REFOBJECT_IS_NULL(self))
141 142 143 144 145 146 147 148 149
        return NULL;

    thread_mutex_lock(&(TO_BASE(self)->lock));
    ret = TO_BASE(self)->name;
    thread_mutex_unlock(&(TO_BASE(self)->lock));

    return ret;
}

150
refobject_t     refobject_get_associated(refobject_t self)
151 152 153
{
    refobject_t ret;

154 155
    if (REFOBJECT_IS_NULL(self))
        return REFOBJECT_NULL;
156 157

    thread_mutex_lock(&(TO_BASE(self)->lock));
158
    ret = TO_BASE(self)->associated;
159 160 161 162
    thread_mutex_unlock(&(TO_BASE(self)->lock));

    return ret;
}