1
0
mirror of https://gitlab.xiph.org/xiph/icecast-common.git synced 2024-09-29 04:25:57 -04:00

Merge branch 'update-instance' into libigloo

This commit is contained in:
Philipp Schafft 2019-09-15 15:33:48 +00:00
commit e853a43e34
3 changed files with 235 additions and 8 deletions

View File

@ -48,6 +48,84 @@ extern "C" {
*/
igloo_ro_t igloo_initialize(void);
/* Get per-instance error value
*
* Parameters:
* self
* An instance or any object that knows an instance.
* result
* Pointer to where to store the result.
* Returns:
* igloo_ERROR_NONE if successful or error code otherwise.
*/
igloo_error_t igloo_instance_get_error(igloo_ro_t self, igloo_error_t *result);
/* Set per-instance error value
*
* Parameters:
* self
* An instance or any object that knows an instance.
* error
* The new error value.
* Returns:
* igloo_ERROR_NONE if successful or error code otherwise.
*/
igloo_error_t igloo_instance_set_error(igloo_ro_t self, igloo_error_t error);
/* Set per-instance logger
*
* Note: The instance will only hold a weak reference. So the caller must
* ensure that there will be a strong reference somewhere else. Otherwise
* the logger will be released.
*
* Parameters:
* self
* An instance or any object that knows an instance.
* logger
* The logger to use.
* Returns:
* igloo_ERROR_NONE if successful or error code otherwise.
*/
igloo_error_t igloo_instance_set_logger(igloo_ro_t self, igloo_objecthandler_t *logger);
/* Get per-instance logger
*
* Parameters:
* self
* An instance or any object that knows an instance.
* Returns:
* A strong reference to a logger or igloo_RO_NULL.
*/
igloo_objecthandler_t * igloo_instance_get_logger(igloo_ro_t self);
/* Log a message with per-instance logger
*
* Note: This is much faster than using igloo_instance_get_logger() and
* using it's return value for single log messages. If you want to push many
* messages use igloo_instance_get_logger() and igloo_list_forward().
*
* Parameters:
* self
* An instance or any object that knows an instance.
* msg
* The message to log.
* Returns:
* igloo_ERROR_NONE if successful or error code otherwise.
*/
igloo_error_t igloo_instance_log(igloo_ro_t self, igloo_ro_t msg);
/* Validate an instance.
*
* Note: This is very useful when a instance is passed from a user to a library.
*
* Parameters:
* self
* An instance to validate.
* Returns:
* igloo_ERROR_NONE if self is a valid instance, or error code otherwise.
*/
igloo_error_t igloo_instance_validate_raw(igloo_ro_t self);
#define igloo_instance_validate(x) igloo_instance_validate_raw((x))
#ifdef __cplusplus
}
#endif

View File

@ -29,18 +29,31 @@ typedef struct igloo_instance_tag igloo_instance_t;
#include "../include/igloo/ro.h"
#include "../include/igloo/error.h"
#include "../include/igloo/objecthandler.h"
#include "private.h"
struct igloo_instance_tag {
igloo_ro_base_t __base;
igloo_mutex_t lock;
igloo_error_t error;
igloo_objecthandler_t *logger;
};
static size_t igloo_initialize__refc;
static igloo_ro_t default_instance = igloo_RO_NULL;
static void igloo_initialize__free(igloo_ro_t self);
igloo_RO_PRIVATE_TYPE(igloo_instance_t,
igloo_RO_TYPEDECL_FREE(igloo_initialize__free)
);
/* Internal forwarding */
const igloo_ro_type_t **igloo_instance_type = &igloo_ro__type__igloo_instance_t;
static void igloo_initialize__free(igloo_ro_t self)
{
igloo_instance_t *instance = igloo_RO_TO_TYPE(self, igloo_instance_t);
if (igloo_RO_IS_SAME(default_instance, self)) {
/* This is hacky, but needed to avoid free-before-unlock. */
@ -48,6 +61,12 @@ static void igloo_initialize__free(igloo_ro_t self)
default_instance = igloo_RO_NULL;
}
igloo_thread_mutex_lock(&(instance->lock));
igloo_ro_weak_unref(instance->logger);
igloo_thread_mutex_unlock(&(instance->lock));
igloo_thread_mutex_destroy(&(instance->lock));
igloo_initialize__refc--;
if (igloo_initialize__refc)
return;
@ -58,13 +77,6 @@ static void igloo_initialize__free(igloo_ro_t self)
igloo_log_shutdown();
}
igloo_RO_PRIVATE_TYPE(igloo_instance_t,
igloo_RO_TYPEDECL_FREE(igloo_initialize__free)
);
/* Internal forwarding */
const igloo_ro_type_t **igloo_instance_type = &igloo_ro__type__igloo_instance_t;
igloo_ro_t igloo_initialize(void)
{
igloo_instance_t *ret;
@ -83,6 +95,8 @@ igloo_ro_t igloo_initialize(void)
if (!ret)
return igloo_RO_NULL;
igloo_thread_mutex_create(&(ret->lock));
igloo_initialize__refc++;
if (igloo_RO_IS_NULL(default_instance)) {
@ -104,3 +118,135 @@ igloo_ro_t igloo_get_default_instance(void)
return default_instance;
}
static igloo_instance_t * igloo_instance_get_instance(igloo_ro_t self)
{
igloo_instance_t *instance;
if (igloo_RO_IS_NULL(self))
self = default_instance;
instance = igloo_RO_TO_TYPE(igloo_ro_get_instance(self), igloo_instance_t);
return instance;
}
igloo_error_t igloo_instance_get_error(igloo_ro_t self, igloo_error_t *result)
{
igloo_instance_t *instance = igloo_instance_get_instance(self);
if (!instance)
return igloo_ERROR_GENERIC;
igloo_thread_mutex_lock(&(instance->lock));
if (result)
*result = instance->error;
igloo_thread_mutex_unlock(&(instance->lock));
igloo_ro_unref(instance);
return igloo_ERROR_NONE;
}
igloo_error_t igloo_instance_set_error(igloo_ro_t self, igloo_error_t error)
{
igloo_instance_t *instance = igloo_instance_get_instance(self);
if (!instance)
return igloo_ERROR_GENERIC;
igloo_thread_mutex_lock(&(instance->lock));
instance->error = error;
igloo_thread_mutex_unlock(&(instance->lock));
igloo_ro_unref(instance);
return igloo_ERROR_NONE;
}
igloo_error_t igloo_instance_set_logger(igloo_ro_t self, igloo_objecthandler_t *logger)
{
igloo_instance_t *instance;
igloo_error_t ret;
if (!igloo_RO_IS_NULL(logger) && !igloo_RO_IS_VALID(logger, igloo_objecthandler_t))
return igloo_ERROR_GENERIC;
instance = igloo_instance_get_instance(self);
if (!instance)
return igloo_ERROR_GENERIC;
if (!igloo_RO_IS_NULL(logger)) {
ret = igloo_ro_weak_ref(logger);
if (ret != igloo_ERROR_NONE) {
igloo_ro_unref(instance);
return ret;
}
}
igloo_thread_mutex_lock(&(instance->lock));
igloo_ro_weak_unref(instance->logger);
instance->logger = logger;
igloo_thread_mutex_unlock(&(instance->lock));
igloo_ro_unref(instance);
return igloo_ERROR_NONE;
}
igloo_objecthandler_t * igloo_instance_get_logger(igloo_ro_t self)
{
igloo_instance_t *instance = igloo_instance_get_instance(self);
igloo_objecthandler_t *ret = NULL;
if (!instance)
return NULL;
igloo_thread_mutex_lock(&(instance->lock));
if (igloo_ro_ref(instance->logger) == igloo_ERROR_NONE) {
ret = instance->logger;
}
igloo_thread_mutex_unlock(&(instance->lock));
igloo_ro_unref(instance);
return ret;
}
igloo_error_t igloo_instance_log(igloo_ro_t self, igloo_ro_t msg)
{
igloo_instance_t *instance = igloo_instance_get_instance(self);
igloo_error_t ret;
if (!instance)
return igloo_ERROR_FAULT;
igloo_thread_mutex_lock(&(instance->lock));
switch (igloo_objecthandler_handle(instance->logger, msg)) {
case igloo_FILTER_RESULT_PASS:
ret = igloo_ERROR_NONE;
break;
case igloo_FILTER_RESULT_DROP:
ret = igloo_ERROR_GENERIC;
break;
case igloo_FILTER_RESULT_ERROR:
default:
ret = igloo_ERROR_GENERIC;
break;
}
igloo_thread_mutex_unlock(&(instance->lock));
igloo_ro_unref(instance);
return ret;
}
igloo_error_t igloo_instance_validate_raw(igloo_ro_t self)
{
if (igloo_RO_IS_VALID(self, igloo_instance_t)) {
return igloo_ERROR_NONE;
} else {
return igloo_ERROR_GENERIC;
}
}

View File

@ -351,14 +351,17 @@ igloo_ro_t igloo_ro_get_instance(igloo_ro_t self)
} else {
ret = base->instance;
}
igloo_thread_mutex_unlock(&(base->lock));
/* We do this after unlock to avoid dead locks.
* This is valid as we have at least a weak ref to the target
*/
if (!igloo_RO_IS_NULL(ret)) {
if (igloo_ro_ref(ret) != igloo_ERROR_NONE) {
igloo_thread_mutex_unlock(&(base->lock));
return igloo_RO_NULL;
}
}
igloo_thread_mutex_unlock(&(base->lock));
return ret;
}