File: ro.h

package info (click to toggle)
libigloo 0.9.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,968 kB
  • sloc: ansic: 5,476; sh: 4,996; makefile: 62
file content (331 lines) | stat: -rw-r--r-- 16,349 bytes parent folder | download | duplicates (3)
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_ */