diff --git a/src/libigloo.c b/src/libigloo.c index 04ca615..1e3e955 100644 --- a/src/libigloo.c +++ b/src/libigloo.c @@ -28,6 +28,7 @@ typedef struct igloo_instance_tag igloo_instance_t; #define igloo_RO_PRIVATETYPES igloo_RO_TYPE(igloo_instance_t) #include "../include/igloo/ro.h" +#include "../include/igloo/error.h" #include "private.h" struct igloo_instance_tag { @@ -35,9 +36,18 @@ struct igloo_instance_tag { }; static size_t igloo_initialize__refc; +static igloo_ro_t default_instance = igloo_RO_NULL; + static void igloo_initialize__free(igloo_ro_t self) { + + if (igloo_RO_IS_SAME(default_instance, self)) { + /* This is hacky, but needed to avoid free-before-unlock. */ + igloo_RO__GETBASE(default_instance)->wrefc--; + default_instance = igloo_RO_NULL; + } + igloo_initialize__refc--; if (igloo_initialize__refc) return; @@ -75,5 +85,22 @@ igloo_ro_t igloo_initialize(void) igloo_initialize__refc++; + if (igloo_RO_IS_NULL(default_instance)) { + if (igloo_ro_weak_ref(ret) == igloo_ERROR_NONE) { + default_instance = (igloo_ro_t)ret; + } + } + return (igloo_ro_t)ret; } + +igloo_ro_t igloo_get_default_instance(void) +{ + if (igloo_RO_IS_NULL(default_instance)) + return igloo_RO_NULL; + + if (igloo_ro_ref(default_instance) != igloo_ERROR_NONE) + return igloo_RO_NULL; + + return default_instance; +} diff --git a/src/private.h b/src/private.h index eb6ebad..7b312e2 100644 --- a/src/private.h +++ b/src/private.h @@ -38,7 +38,8 @@ void igloo_log_shutdown(void); /* Instance type internal forwarding */ const igloo_ro_type_t **igloo_instance_type; -#define igloo_IS_INSTANCE(x) (igloo_RO_GET_TYPE((x)) == *igloo_instance_type) +#define igloo_IS_INSTANCE(x) (igloo_RO_GET_TYPE((x)) == *igloo_instance_type) +#define igloo_IS_INSTANCE_TYPE(x) ((x) == *igloo_instance_type) /* Basic interface */ #define igloo_interface_base(type) \ @@ -67,4 +68,6 @@ size_t igloo_private__vsnprintf_Hstrlen(const char *str, int is_alt, int allow_s void igloo_private__vsnprintf(char *str, size_t size, const char *format, va_list ap); void igloo_private__snprintf(char *str, size_t size, const char *format, ...); +igloo_ro_t igloo_get_default_instance(void); + #endif diff --git a/src/ro.c b/src/ro.c index d74b244..cfd407a 100644 --- a/src/ro.c +++ b/src/ro.c @@ -113,6 +113,9 @@ igloo_ro_t igloo_ro_new__raw(const igloo_ro_type_t *type, const char *name, } base->instance = instance; + } else { + if (!igloo_IS_INSTANCE_TYPE(type)) + base->instance = igloo_get_default_instance(); } return (igloo_ro_t)base;