bt2c::Logger: remove unused cLevel() method
[babeltrace.git] / src / lib / object.h
CommitLineData
273b65be 1/*
0235b0db
MJ
2 * SPDX-License-Identifier: MIT
3 *
e2f7325d 4 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
83509119 5 * Copyright 2015 Jérémie Galarneau <jeremie.galarneau@efficios.com>
273b65be
JG
6 */
7
0235b0db
MJ
8#ifndef BABELTRACE_OBJECT_INTERNAL_H
9#define BABELTRACE_OBJECT_INTERNAL_H
10
578e048b 11#include "common/assert.h"
312c056a 12#include <stdbool.h>
273b65be 13
3fea54f6
PP
14struct bt_object;
15
16typedef void (*bt_object_release_func)(struct bt_object *);
17typedef void (*bt_object_parent_is_owner_listener_func)(
18 struct bt_object *);
19
20static inline
6871026b 21void bt_object_get_ref_no_null_check(const void *obj);
3fea54f6
PP
22
23static inline
6871026b 24void bt_object_put_ref_no_null_check(const void *obj);
3fea54f6
PP
25
26/*
27 * Babeltrace object base.
28 *
29 * All objects publicly exposed by Babeltrace APIs must contain this
30 * object as their first member.
de3dd40e 31 */
83509119 32struct bt_object {
312c056a 33 /*
3fea54f6
PP
34 * True if this object is shared, that is, it has a reference
35 * count.
312c056a
PP
36 */
37 bool is_shared;
3fea54f6
PP
38
39 /*
40 * Current reference count.
41 */
42 unsigned long long ref_count;
43
44 /*
45 * Release function called when the object's reference count
46 * falls to zero. For an object with a parent, this function is
47 * bt_object_with_parent_release_func(), which calls
48 * `spec_release_func` below if there's no current parent.
49 */
50 bt_object_release_func release_func;
51
52 /*
53 * Specific release function called by
54 * bt_object_with_parent_release_func() or directly by a
55 * parent object.
56 */
57 bt_object_release_func spec_release_func;
58
59 /*
60 * Optional callback for an object with a parent, called by
61 * bt_object_with_parent_release_func() to indicate to the
62 * object that its parent is its owner.
63 */
64 bt_object_parent_is_owner_listener_func
65 parent_is_owner_listener_func;
66
67 /*
68 * Optional parent object.
69 */
70 struct bt_object *parent;
273b65be
JG
71};
72
73static inline
398454ed 74unsigned long long bt_object_get_ref_count(const struct bt_object *c_obj)
7c56f3cc 75{
398454ed
PP
76 struct bt_object *obj = (void *) c_obj;
77
98b15851
PP
78 BT_ASSERT_DBG(obj);
79 BT_ASSERT_DBG(obj->is_shared);
3fea54f6
PP
80 return obj->ref_count;
81}
5d2d9981 82
3fea54f6 83static inline
398454ed 84struct bt_object *bt_object_borrow_parent(const struct bt_object *c_obj)
3fea54f6 85{
398454ed
PP
86 struct bt_object *obj = (void *) c_obj;
87
98b15851
PP
88 BT_ASSERT_DBG(obj);
89 BT_ASSERT_DBG(obj->is_shared);
3fea54f6 90 return obj->parent;
7c56f3cc
MD
91}
92
93static inline
398454ed 94struct bt_object *bt_object_get_parent(const struct bt_object *c_obj)
5d2d9981 95{
398454ed 96 struct bt_object *obj = (void *) c_obj;
3fea54f6
PP
97 struct bt_object *parent = bt_object_borrow_parent(obj);
98
99 if (parent) {
6871026b 100 bt_object_get_ref_no_null_check(parent);
3fea54f6
PP
101 }
102
103 return parent;
104}
105
106static inline
107void bt_object_set_parent(struct bt_object *child, struct bt_object *parent)
108{
98b15851
PP
109 BT_ASSERT_DBG(child);
110 BT_ASSERT_DBG(child->is_shared);
5d2d9981 111
b9e6ec43 112#ifdef BT_LOGT
ef267d12 113 BT_LOGT("Setting object's parent: addr=%p, parent-addr=%p",
3fea54f6 114 child, parent);
0f5e83e5
PP
115#endif
116
3fea54f6
PP
117 /*
118 * It is assumed that a "child" having a parent is publicly
119 * reachable. Therefore, a reference to its parent must be
120 * taken. The reference to the parent will be released once the
121 * object's reference count falls to zero.
122 */
123 if (parent) {
98b15851 124 BT_ASSERT_DBG(!child->parent);
3fea54f6 125 child->parent = parent;
6871026b 126 bt_object_get_ref_no_null_check(parent);
3fea54f6
PP
127 } else {
128 if (child->parent) {
6871026b 129 bt_object_put_ref_no_null_check(child->parent);
3fea54f6
PP
130 }
131
132 child->parent = NULL;
5d2d9981
JG
133 }
134}
135
7c56f3cc 136static inline
3fea54f6
PP
137void bt_object_try_spec_release(struct bt_object *obj)
138{
98b15851
PP
139 BT_ASSERT_DBG(obj);
140 BT_ASSERT_DBG(obj->is_shared);
141 BT_ASSERT_DBG(obj->spec_release_func);
3fea54f6
PP
142
143 if (bt_object_get_ref_count(obj) == 0) {
144 obj->spec_release_func(obj);
145 }
146}
147
148static inline
149void bt_object_with_parent_release_func(struct bt_object *obj)
5d2d9981
JG
150{
151 if (obj->parent) {
3fea54f6
PP
152 /*
153 * Keep our own copy of the parent address because `obj`
154 * could be destroyed in
155 * obj->parent_is_owner_listener_func().
156 */
0f5e83e5
PP
157 struct bt_object *parent = obj->parent;
158
b9e6ec43 159#ifdef BT_LOGT
ef267d12 160 BT_LOGT("Releasing parented object: addr=%p, ref-count=%llu, "
3fea54f6
PP
161 "parent-addr=%p, parent-ref-count=%llu",
162 obj, obj->ref_count,
163 parent, parent->ref_count);
0f5e83e5 164#endif
f167d3c0 165
3fea54f6 166 if (obj->parent_is_owner_listener_func) {
f167d3c0
PP
167 /*
168 * Object has a chance to destroy itself here
169 * under certain conditions and notify its
170 * parent. At this point the parent is
171 * guaranteed to exist because it's not put yet.
172 */
3fea54f6 173 obj->parent_is_owner_listener_func(obj);
f167d3c0
PP
174 }
175
5d2d9981 176 /* The release function will be invoked by the parent. */
6871026b 177 bt_object_put_ref_no_null_check(parent);
5d2d9981 178 } else {
3fea54f6 179 bt_object_try_spec_release(obj);
5d2d9981
JG
180 }
181}
182
183static inline
3fea54f6
PP
184void bt_object_init(struct bt_object *obj, bool is_shared,
185 bt_object_release_func release_func)
5d2d9981 186{
98b15851
PP
187 BT_ASSERT_DBG(obj);
188 BT_ASSERT_DBG(!is_shared || release_func);
3fea54f6
PP
189 obj->is_shared = is_shared;
190 obj->release_func = release_func;
191 obj->parent_is_owner_listener_func = NULL;
192 obj->spec_release_func = NULL;
193 obj->parent = NULL;
194 obj->ref_count = 1;
dc3fffef
PP
195}
196
197static inline
3fea54f6
PP
198void bt_object_init_shared(struct bt_object *obj,
199 bt_object_release_func release_func)
dc3fffef 200{
3fea54f6 201 bt_object_init(obj, true, release_func);
5d2d9981
JG
202}
203
204static inline
3fea54f6 205void bt_object_init_unique(struct bt_object *obj)
273b65be 206{
3fea54f6
PP
207 bt_object_init(obj, false, NULL);
208}
5d2d9981 209
3fea54f6
PP
210static inline
211void bt_object_init_shared_with_parent(struct bt_object *obj,
212 bt_object_release_func spec_release_func)
213{
98b15851
PP
214 BT_ASSERT_DBG(obj);
215 BT_ASSERT_DBG(spec_release_func);
3fea54f6
PP
216 bt_object_init_shared(obj, bt_object_with_parent_release_func);
217 obj->spec_release_func = spec_release_func;
218}
0f5e83e5 219
3fea54f6
PP
220static inline
221void bt_object_set_parent_is_owner_listener_func(struct bt_object *obj,
222 bt_object_parent_is_owner_listener_func func)
223{
98b15851
PP
224 BT_ASSERT_DBG(obj);
225 BT_ASSERT_DBG(obj->is_shared);
226 BT_ASSERT_DBG(obj->spec_release_func);
3fea54f6 227 ((struct bt_object *) obj)->parent_is_owner_listener_func = func;
5d2d9981
JG
228}
229
312c056a 230static inline
398454ed 231void bt_object_inc_ref_count(const struct bt_object *c_obj)
312c056a 232{
398454ed
PP
233 struct bt_object *obj = (void *) c_obj;
234
98b15851
PP
235 BT_ASSERT_DBG(obj);
236 BT_ASSERT_DBG(obj->is_shared);
3fea54f6 237 obj->ref_count++;
98b15851 238 BT_ASSERT_DBG(obj->ref_count != 0);
312c056a
PP
239}
240
6c677fb5 241static inline
6871026b 242void bt_object_get_ref_no_null_check_no_parent_check(const struct bt_object *c_obj)
6c677fb5 243{
398454ed
PP
244 struct bt_object *obj = (void *) c_obj;
245
98b15851
PP
246 BT_ASSERT_DBG(obj);
247 BT_ASSERT_DBG(obj->is_shared);
6c677fb5 248
b9e6ec43 249#ifdef BT_LOGT
ef267d12 250 BT_LOGT("Incrementing object's reference count: %llu -> %llu: "
6c677fb5
PP
251 "addr=%p, cur-count=%llu, new-count=%llu",
252 obj->ref_count, obj->ref_count + 1,
253 obj, obj->ref_count, obj->ref_count + 1);
254#endif
255
256 bt_object_inc_ref_count(obj);
257}
258
5d2d9981 259static inline
6871026b 260void bt_object_get_ref_no_null_check(const void *c_obj)
5d2d9981 261{
398454ed
PP
262 struct bt_object *obj = (void *) c_obj;
263
98b15851
PP
264 BT_ASSERT_DBG(obj);
265 BT_ASSERT_DBG(obj->is_shared);
5d2d9981 266
91d81473 267 if (G_UNLIKELY(obj->parent && bt_object_get_ref_count(obj) == 0)) {
b9e6ec43 268#ifdef BT_LOGT
ef267d12 269 BT_LOGT("Incrementing object's parent's reference count: "
3fea54f6
PP
270 "addr=%p, parent-addr=%p", obj, obj->parent);
271#endif
272
6871026b 273 bt_object_get_ref_no_null_check(obj->parent);
3fea54f6
PP
274 }
275
b9e6ec43 276#ifdef BT_LOGT
ef267d12 277 BT_LOGT("Incrementing object's reference count: %llu -> %llu: "
3fea54f6
PP
278 "addr=%p, cur-count=%llu, new-count=%llu",
279 obj->ref_count, obj->ref_count + 1,
280 obj, obj->ref_count, obj->ref_count + 1);
281#endif
282
283 bt_object_inc_ref_count(obj);
273b65be
JG
284}
285
f167d3c0 286static inline
6871026b 287void bt_object_put_ref_no_null_check(const void *c_obj)
f167d3c0 288{
398454ed
PP
289 struct bt_object *obj = (void *) c_obj;
290
98b15851
PP
291 BT_ASSERT_DBG(obj);
292 BT_ASSERT_DBG(obj->is_shared);
293 BT_ASSERT_DBG(obj->ref_count > 0);
3fea54f6 294
b9e6ec43 295#ifdef BT_LOGT
ef267d12 296 BT_LOGT("Decrementing object's reference count: %llu -> %llu: "
3fea54f6
PP
297 "addr=%p, cur-count=%llu, new-count=%llu",
298 obj->ref_count, obj->ref_count - 1,
299 obj, obj->ref_count, obj->ref_count - 1);
300#endif
301
302 obj->ref_count--;
303
304 if (obj->ref_count == 0) {
98b15851 305 BT_ASSERT_DBG(obj->release_func);
3fea54f6
PP
306 obj->release_func(obj);
307 }
f167d3c0
PP
308}
309
c5b9b441
PP
310static inline
311void bt_object_get_ref(const void *ptr)
312{
313 struct bt_object *obj = (void *) ptr;
314
91d81473 315 if (G_UNLIKELY(!obj)) {
c5b9b441
PP
316 return;
317 }
318
5d70aba9 319 BT_ASSERT_DBG(obj->is_shared);
6871026b 320 bt_object_get_ref_no_null_check(obj);
c5b9b441
PP
321}
322
323static inline
324void bt_object_put_ref(const void *ptr)
325{
326 struct bt_object *obj = (void *) ptr;
327
91d81473 328 if (G_UNLIKELY(!obj)) {
c5b9b441
PP
329 return;
330 }
331
5d70aba9
PP
332 BT_ASSERT_DBG(obj->is_shared);
333 BT_ASSERT_DBG(bt_object_get_ref_count(obj) > 0);
6871026b 334 bt_object_put_ref_no_null_check(obj);
c5b9b441
PP
335}
336
337#define BT_OBJECT_PUT_REF_AND_RESET(_var) \
338 do { \
339 bt_object_put_ref(_var); \
340 (_var) = NULL; \
341 } while (0)
342
343#define BT_OBJECT_MOVE_REF(_var_dst, _var_src) \
344 do { \
345 bt_object_put_ref(_var_dst); \
346 (_var_dst) = (_var_src); \
347 (_var_src) = NULL; \
348 } while (0)
349
83509119 350#endif /* BABELTRACE_OBJECT_INTERNAL_H */
This page took 0.124705 seconds and 5 git commands to generate.