1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
|
/* Copyright (C) 2018 Marvin Scholz <epirat07@gmail.com>
* Copyright (C) 2018-2020 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef _LIBIGLOO__RO_H_
#define _LIBIGLOO__RO_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <pthread.h>
#include <stdbool.h>
#include <stdarg.h>
#include <igloo/config.h>
#include <igloo/types.h>
#include <igloo/feature.h>
#include <igloo/rwlock.h>
igloo_FEATURE_FORWARD(igloo_ro_feature_ownlock);
/* Type used for callback called then the object is actually freed
* That is once all references to it are gone.
*
* This function must not try to deallocate or alter self.
*
* The callback is called with the object in write lock.
*/
typedef void (*igloo_ro_free_t)(igloo_ro_t self);
/* Type used for callback called then the object is created
* using the generic igloo_ro_new().
*
* Additional parameters passed to igloo_ro_new() are passed
* in the list ap. All limitations of <stdarg.h> apply.
*
* This function must return igloo_ERROR_NONE in case of success and
* the corresponding error in case of error.
* In case of error igloo_ro_unref() is called internally to clear the object.
*/
typedef igloo_error_t (*igloo_ro_new_t)(igloo_ro_t self, const igloo_ro_type_t *type, va_list ap);
/* Type used for callback called when error value is requested from an object.
*
* The callback is called with the object in read lock.
*/
typedef igloo_error_t (*igloo_ro_get_error_t)(igloo_ro_t self, igloo_error_t *result);
/* Type used to store flags for stringify operation. */
typedef uint_least32_t igloo_ro_sy_t;
/* No stringify flags set. Usefull for variable initialization. */
#define igloo_RO_SY_NONE ((igloo_ro_sy_t)0x0000)
/* Stringify using defaults. */
#define igloo_RO_SY_DEFAULT ((igloo_ro_sy_t)0x1000)
/* Allow to stringify the object itself, do not touch the content. */
#define igloo_RO_SY_OBJECT ((igloo_ro_sy_t)0x0001)
/* Allow to stringify the object's content. */
#define igloo_RO_SY_CONTENT ((igloo_ro_sy_t)0x0002)
/* Allow to stringify the object in a way useful for debugging. */
#define igloo_RO_SY_DEBUG ((igloo_ro_sy_t)0x0004)
/* Type used for callback called when the object needs to be converted to a string.
*
* This is used mostly for debugging or preseting the object to the user.
* The callback is not expected to return a string that can be used to reconstruct the object.
*
* The callback is called with the object in write lock for mutable objects and
* in read lock for immutable objects.
*/
typedef igloo_error_t (*igloo_ro_stringify_t)(igloo_ro_t self, char **result, igloo_ro_sy_t flags);
/* Type used for callback called when the object is queried for it's features.
*
* The callback only needs to check for it's own layer. All parent types are also queried.
*
* The callback is called with the object in read lock.
*/
typedef igloo_error_t (*igloo_ro_can_t)(igloo_ro_t self, bool *result, igloo_feature_t *feature);
/* ---[ PRIVATE ]--- */
/*
* Those declarations are defined here as they must be known to the compiler.
* Nobody should ever try to access them directly.
*/
typedef void (*igloo_ro_raw_func_ptr_t)(void);
struct igloo_ro_type_tag {
/* Control structure */
igloo_control_t control;
/* Total length of the objects to be created */
size_t type_length;
/* Name of type */
const char * type_name;
/* Parent type */
const igloo_ro_type_t * type_parent;
/* Features supported by this type */
const igloo_feature_t *** type_features;
size_t type_features_length; // in elements
/* Type flags
* WARNING: This is not really a pointer. It is only a pointer
* to keep the data structure as-is before the next SONAME change.
*
* REWRITE BEFORE RELEASE 1.0.0: Change from pointer to integer type.
*/
const void * type_flags;
/* STILL UNUSED: Type description */
const char * type_description;
const char * type_uuid;
const char * type_application; // report XML
const void * type_reserved_ptr_0;
const void * type_reserved_ptr_1;
const void * type_reserved_ptr_2;
/* Callback to be called on final free() */
igloo_ro_free_t type_freecb;
/* Callback to be called by igloo_ro_new() */
igloo_ro_new_t type_newcb;
/* Callbacks */
igloo_ro_get_error_t type_get_errorcb;
igloo_ro_stringify_t type_stringifycb;
igloo_ro_can_t type_cancb;
/* STILL UNUSED: for possible future use */
igloo_ro_raw_func_ptr_t type_clonecb;
igloo_ro_raw_func_ptr_t type_convertcb;
igloo_ro_raw_func_ptr_t type_get_interfacecb;
igloo_ro_raw_func_ptr_t type_comparecb;
igloo_ro_raw_func_ptr_t type_sendto;
igloo_ro_raw_func_ptr_t type_recvfrom;
igloo_ro_raw_func_ptr_t type_test;
igloo_ro_raw_func_ptr_t type_reserved_func_0;
igloo_ro_raw_func_ptr_t type_reserved_func_1;
igloo_ro_raw_func_ptr_t type_reserved_func_2;
igloo_ro_raw_func_ptr_t type_reserved_func_3;
} igloo_ATTR_T_ALIGNED(8);
struct igloo_ro_stub_tag {
/* Type of the object */
const igloo_ro_type_t * type;
/* Reference counters */
uint32_t refc;
uint32_t wrefc;
/* object group */
igloo_ro_object_group_t * group;
} igloo_ATTR_T_ALIGNED(8);
struct igloo_ro_tiny_tag {
igloo_ro_stub_t stub;
};
struct igloo_ro_full_tag {
igloo_ro_stub_t stub;
/* lock for igloo_ro_*() */
igloo_rwlock_t lock;
};
igloo_error_t igloo_ro_new__return_zero(igloo_ro_t self, const igloo_ro_type_t *type, va_list ap);
igloo_ro_t igloo_RO_TO_TYPE_raw(igloo_ro_t object, const igloo_ro_type_t *type) igloo_ATTR_F_HOT;
bool igloo_RO_IS_VALID_raw(igloo_ro_t object, const igloo_ro_type_t *type) igloo_ATTR_F_HOT;
bool igloo_RO_HAS_TYPE_raw(igloo_ro_t object, const igloo_ro_type_t *type) igloo_ATTR_F_HOT igloo_ATTR_F_PURE;
igloo_error_t igloo_ro_ref_raw(igloo_ro_t self, igloo_ro_t *out, const igloo_ro_type_t *type);
igloo_error_t igloo_ro_unref_raw(igloo_ro_t *self);
igloo_error_t igloo_ro_weak_ref_raw(igloo_ro_t self, igloo_ro_t *out, const igloo_ro_type_t *type);
igloo_error_t igloo_ro_weak_unref_raw(igloo_ro_t *self);
igloo_error_t igloo_ro_ref_replace_raw(igloo_ro_t self, igloo_ro_t *out, const igloo_ro_type_t *type);
igloo_error_t igloo_ro_weak_ref_replace_raw(igloo_ro_t self, igloo_ro_t *out, const igloo_ro_type_t *type);
igloo_error_t igloo_ro_new__raw(igloo_ro_t *out, const igloo_ro_type_t *type, igloo_ro_t group);
igloo_error_t igloo_ro_new__simple(igloo_ro_t *out, const igloo_ro_type_t *type, igloo_ro_t group, ...);
void igloo_ro_locked_start(igloo_ro_t self, const igloo_ro_type_t *type, bool writelock);
void igloo_ro_locked_end(igloo_ro_t self, const igloo_ro_type_t *type);
igloo_error_t igloo_ro_get_error_raw(igloo_ro_t self, igloo_error_t *result, const igloo_ro_type_t *type);
igloo_error_t igloo_ro_stringify_raw(igloo_ro_t self, char **result, igloo_ro_sy_t flags, const igloo_ro_type_t *type);
bool igloo_ro_can_raw(igloo_ro_t self, igloo_feature_t *feature, const igloo_ro_type_t *type);
/* ---[ END PRIVATE ]--- */
#ifdef igloo_ATTR_T_TRANSPARENT_UNION
#define igloo_RO__GETSTUB(x) (((igloo_ro_t)(x)).subtype__igloo_ro_stub_t)
#define igloo_RO_NULL ((igloo_ro_t)(igloo_ro_stub_t*)NULL)
#define igloo_ro_is_null(x) (igloo_RO__GETSTUB((x)) == NULL)
#define igloo_ro_to_type(x,type) (((igloo_ro_t)igloo_RO_TO_TYPE_raw((x), igloo_RO_GET_TYPE_BY_SYMBOL(type))).subtype__ ## type)
#else
#define igloo_RO__GETSTUB(x) ((igloo_ro_stub_t*)(x))
#define igloo_RO_NULL NULL
#define igloo_ro_is_null(x) ((x) == NULL)
#define igloo_ro_to_type(x,type) ((type*)igloo_RO_TO_TYPE_raw((x), igloo_RO_GET_TYPE_BY_SYMBOL(type)))
#endif
#define igloo_RO_GET_TYPE(x) (igloo_RO__GETSTUB((x)) == NULL ? NULL : igloo_RO__GETSTUB((x))->type)
#define igloo_RO_GET_TYPENAME(x) (igloo_RO_GET_TYPE((x)) == NULL ? NULL : igloo_RO_GET_TYPE((x))->type_name)
#define igloo_ro_is_valid(x,type) igloo_RO_IS_VALID_raw((x), igloo_RO_GET_TYPE_BY_SYMBOL(type))
#define igloo_ro_has_type(x,type) igloo_RO_HAS_TYPE_raw((x), (type))
#define igloo_ro_is_same(a,b) (igloo_RO__GETSTUB((a)) == igloo_RO__GETSTUB((b)))
/* Create a new object.
*
* Parameters:
* out
* The a pointer to the address object to create.
* type
* The type of new object to create.
* group
* The object group to make this object part of.
* If the passed object is a instance the default group for the instance is used.
* If any other object is used the new object will join the same group as that object.
*/
#ifdef igloo_HAVE_STATEMENT_EXPRESSIONS
#define igloo_ro_new_raw(out, type, group) igloo_ro_new__raw(({type ** igloo_tmp_arg = (out); (void)igloo_tmp_arg; (igloo_ro_t*)(out);}), igloo_RO_GET_OWN_TYPE_BY_SYMBOL(type), (group))
#define igloo_ro_new(out, type, group, ...) igloo_ro_new__simple(({type ** igloo_tmp_arg = (out); (void)igloo_tmp_arg; (igloo_ro_t*)(out);}), igloo_RO_GET_TYPE_BY_SYMBOL(type), (group), ## __VA_ARGS__)
#else
#define igloo_ro_new_raw(out, type, group) igloo_ro_new__raw((igloo_ro_t*)(type**)(out), igloo_RO_GET_OWN_TYPE_BY_SYMBOL(type), (group))
#define igloo_ro_new(out, type, group, ...) igloo_ro_new__simple((igloo_ro_t*)(type**)(out), igloo_RO_GET_TYPE_BY_SYMBOL(type), (group), ## __VA_ARGS__)
#endif
/* This gets a new reference (via out) for the given object (self) */
#ifdef igloo_HAVE_STATEMENT_EXPRESSIONS
#define igloo_ro_ref(self, out, type) ({type ** igloo_tmp_arg = (out); const igloo_error_t igloo_tmp_error = igloo_ro_ref_raw((self), (igloo_ro_t*)igloo_tmp_arg, igloo_RO_GET_TYPE_BY_SYMBOL(type)); igloo_tmp_error;})
#define igloo_ro_ref_replace(self, out, type) ({type ** igloo_tmp_arg = (out); const igloo_error_t igloo_tmp_error = igloo_ro_ref_replace_raw((self), (igloo_ro_t*)igloo_tmp_arg, igloo_RO_GET_TYPE_BY_SYMBOL(type)); igloo_tmp_error;})
#else
#define igloo_ro_ref(self, out, type) igloo_ro_ref_raw((self), (igloo_ro_t*)(type**)(out), igloo_RO_GET_TYPE_BY_SYMBOL(type))
#define igloo_ro_ref_replace(self, out, type) igloo_ro_ref_replace_raw((self), (igloo_ro_t*)(type**)(out), igloo_RO_GET_TYPE_BY_SYMBOL(type))
#endif
#define igloo_ro_ref_transparent(self, out) igloo_ro_ref_raw((self), (out), igloo_RO_GET_TYPE_BY_SYMBOL(igloo_ro_t))
#define igloo_ro_ref_replace_transparent(self, out) igloo_ro_ref_replace_raw((self), (out), igloo_RO_GET_TYPE_BY_SYMBOL(igloo_ro_t))
/* This clears a reference to the object.
* If the object's reference counter reaches zero the object is freed.
*/
#ifdef igloo_HAVE_STATEMENT_EXPRESSIONS
#define igloo_ro_unref(self) igloo_ro_unref_raw(({igloo_ro_t igloo_tmp_arg = (igloo_ro_t)*(self); (void)igloo_tmp_arg; (igloo_ro_t*)(self);}))
#else
#define igloo_ro_unref(self) igloo_ro_unref_raw((igloo_ro_t*)(self))
#endif
/* This is the same as igloo_ro_ref() and igloo_ro_unref() but increases/decreases the weak reference counter. */
#define igloo_ro_weak_ref_transparent(self, out) igloo_ro_weak_ref_raw((self), (out), igloo_RO_GET_TYPE_BY_SYMBOL(igloo_ro_t))
#define igloo_ro_weak_ref_replace_transparent(self, out) igloo_ro_weak_ref_replace_raw((self), (out), igloo_RO_GET_TYPE_BY_SYMBOL(igloo_ro_t))
#ifdef igloo_HAVE_STATEMENT_EXPRESSIONS
#define igloo_ro_weak_ref(self, out, type) ({type ** igloo_tmp_arg = (out); const igloo_error_t igloo_tmp_error = igloo_ro_weak_ref_raw((self), (igloo_ro_t*)igloo_tmp_arg, igloo_RO_GET_TYPE_BY_SYMBOL(type)); igloo_tmp_error;})
#define igloo_ro_weak_ref_replace(self, out, type) ({type ** igloo_tmp_arg = (out); const igloo_error_t igloo_tmp_error = igloo_ro_weak_ref_replace_raw((self), (igloo_ro_t*)igloo_tmp_arg, (igloo_RO_GET_TYPE_BY_SYMBOL(type)); igloo_tmp_error;})
#define igloo_ro_weak_unref(self) igloo_ro_weak_unref_raw(({igloo_ro_t igloo_tmp_arg = (igloo_ro_t)*(self); (void)igloo_tmp_arg; (igloo_ro_t*)(self);}))
#else
#define igloo_ro_weak_ref(self, out, type) igloo_ro_weak_ref_raw((self), (igloo_ro_t*)(type**)(out), igloo_RO_GET_TYPE_BY_SYMBOL(type))
#define igloo_ro_weak_ref_replace(self, out, type) igloo_ro_weak_ref_replace_raw((self), (igloo_ro_t*)(type**)(out), igloo_RO_GET_TYPE_BY_SYMBOL(type))
#define igloo_ro_weak_unref(self) igloo_ro_weak_unref_raw((igloo_ro_t*)(self))
#endif
/* Locked section */
#ifdef igloo_HAVE_STATEMENT_EXPRESSIONS
#define igloo_ro_locked_raw(self, type, code, writelock) ({type * igloo_tmp_arg = (self); (void)igloo_tmp_arg;}); igloo_ro_locked_start((self), igloo_RO_GET_OWN_TYPE_BY_SYMBOL(type), (writelock)); do { code; } while (false); igloo_ro_locked_end((self), igloo_RO_GET_OWN_TYPE_BY_SYMBOL(type))
#else
#define igloo_ro_locked_raw(self, type, code, writelock) igloo_ro_locked_start((self), igloo_RO_GET_OWN_TYPE_BY_SYMBOL(type), (writelock)); do { code; } while (false); igloo_ro_locked_end((self), igloo_RO_GET_OWN_TYPE_BY_SYMBOL(type))
#endif
#define igloo_ro_rlocked(self, type, code) igloo_ro_locked_raw((self), type, code, false)
#define igloo_ro_wlocked(self, type, code) igloo_ro_locked_raw((self), type, code, true)
/* This gets a reference to the object's instance object. */
igloo_error_t igloo_ro_get_instance(igloo_ro_t self, igloo_ro_t *instance) igloo_ATTR_F_WARN_UNUSED_RESULT;
/* This gets a reference to the object's object group object. */
igloo_error_t igloo_ro_get_object_group(igloo_ro_t self, igloo_ro_object_group_t **object_group) igloo_ATTR_F_WARN_UNUSED_RESULT;
/* Get error value from a object.
*
* Parameters:
* self
* The Object to request error value from.
* result
* Pointer to the location the error value should be stored.
* The value is only written if igloo_ERROR_NONE is returned.
* Returns:
* The result of the query.
*/
#define igloo_ro_get_error(self, result) igloo_ro_get_error_raw(self, result, igloo_RO_GET_TYPE(self))
#define igloo_ro_get_error_parent(self, result, type) igloo_ro_get_error_raw(self, result, igloo_RO_GET_OWN_TYPE_BY_SYMBOL(type))
/* Convert a object to a string.
* This is used for debugging and presenting to the user.
*
* The resulting string can not be used to recreate the object.
*
* Parameters:
* self
* The object to convert to a string.
* result
* A string as allocated using malloc(3). The caller must call free(3).
* flags
* Flags used to select options to the conversion.
* Should normally be igloo_RO_SY_DEFAULT.
* Returns:
* Error code for this call.
*/
#define igloo_ro_stringify(self, result, flags) igloo_ro_stringify_raw((self), (result), (flags), igloo_RO_GET_TYPE((self)))
#define igloo_ro_stringify_parent(self, result, flags, type) igloo_ro_stringify_raw((self), (result), (flags), igloo_RO_GET_OWN_TYPE_BY_SYMBOL(type))
/* Checks if a object supports a specific feature.
*
* Parameters:
* self
* The object to check.
* feature
* The feature to test for.
* Returns:
* Whether the feature is supported or false if self is igloo_RO_NULL, or feature is NULL.
*/
#define igloo_ro_can(self, feature) igloo_ro_can_raw((self), (feature), igloo_RO_GET_TYPE((self)))
#define igloo_ro_can_parent(self, feature, type) igloo_ro_can_raw((self), (feature), igloo_RO_GET_OWN_TYPE_BY_SYMBOL(type))
#ifdef __cplusplus
}
#endif
#endif /* ! _LIBIGLOO__RO_H_ */
|