Make g_rc_box_dup()/g_arc_box_dup() more generic
[glib.git] / glib / garcbox.c
blobaaa2c8b56867457fc6986811f3e4106034e7aeb9
1 /* garcbox.c: Atomically reference counted data
3 * Copyright 2018 Emmanuele Bassi
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include "config.h"
21 #include "grcbox.h"
23 #include "gmessages.h"
24 #include "grcboxprivate.h"
25 #include "grefcount.h"
27 #ifdef ENABLE_VALGRIND
28 #include "valgrind.h"
29 #endif
31 #include <string.h>
33 #define G_ARC_BOX(p) (GArcBox *) (((char *) (p)) - G_ARC_BOX_SIZE)
35 /**
36 * SECTION:arcbox
37 * @Title: Atomically reference counted data
38 * @Short_description: Allocated memory with atomic reference counting semantics
40 * An "atomically reference counted box", or "ArcBox", is an opaque wrapper
41 * data type that is guaranteed to be as big as the size of a given data type,
42 * and which augments the given data type with thread safe reference counting
43 * semantics for its memory management.
45 * ArcBox is useful if you have a plain old data type, like a structure
46 * typically placed on the stack, and you wish to provide additional API
47 * to use it on the heap, without necessarily implementing copy/free
48 * semantics, or your own reference counting.
50 * The typical use is:
52 * |[<!-- language="C" -->
53 * typedef struct {
54 * float x, y;
55 * } Point;
57 * Point *
58 * point_new (float x, float y)
59 * {
60 * Point *res = g_arc_box_new (Point);
62 * res->x = x;
63 * res->y = y;
65 * return res;
66 * }
67 * ]|
69 * Every time you wish to acquire a reference on the memory, you should
70 * call g_arc_box_acquire(); similarly, when you wish to release a reference
71 * you should call g_arc_box_release():
73 * |[<!-- language="C" -->
74 * Point *
75 * point_ref (Point *p)
76 * {
77 * return g_arc_box_acquire (p);
78 * }
80 * void
81 * point_unref (Point *p)
82 * {
83 * g_arc_box_release (p);
84 * }
85 * ]|
87 * If you have additional memory allocated inside the structure, you can
88 * use g_arc_box_release_full(), which takes a function pointer, which
89 * will be called if the reference released was the last:
91 * |[<!-- language="C" -->
92 * typedef struct {
93 * char *name;
94 * char *address;
95 * char *city;
96 * char *state;
97 * int age;
98 * } Person;
100 * void
101 * person_clear (Person *p)
103 * g_free (p->name);
104 * g_free (p->address);
105 * g_free (p->city);
106 * g_free (p->state);
109 * void
110 * person_unref (Person *p)
112 * g_arc_box_release_full (p, (GDestroyNotify) person_clear);
114 * ]|
116 * If you wish to transfer the ownership of a reference counted data
117 * type without increasing the reference count, you can use g_steal_pointer():
119 * |[<!-- language="C" -->
120 * Person *p = g_arc_box_new (Person);
122 * fill_person_details (p);
124 * add_person_to_database (db, g_steal_pointer (&p));
125 * ]|
127 * The reference counting operations on data allocated using g_arc_box_alloc(),
128 * g_arc_box_new(), and g_arc_box_dup() are guaranteed to be atomic, and thus
129 * can be safely be performed by different threads. It is important to note that
130 * only the reference acquisition and release are atomic; changes to the content
131 * of the data are your responsibility.
133 * Since: 2.58.
137 * g_arc_box_alloc:
138 * @block_size: the size of the allocation
140 * Allocates @block_size bytes of memory, and adds atomic
141 * reference counting semantics to it.
143 * The data will be freed when its reference count drops to
144 * zero.
146 * Returns: a pointer to the allocated memory
148 * Since: 2.58
150 gpointer
151 g_arc_box_alloc (gsize block_size)
153 g_return_val_if_fail (block_size > 0, NULL);
155 return g_rc_box_alloc_full (block_size, TRUE, FALSE);
159 * g_arc_box_alloc0:
160 * @block_size: the size of the allocation
162 * Allocates @block_size bytes of memory, and adds atomic
163 * referenc counting semantics to it.
165 * The contents of the returned data is set to 0's.
167 * The data will be freed when its reference count drops to
168 * zero.
170 * Returns: a pointer to the allocated memory
172 * Since: 2.58
174 gpointer
175 g_arc_box_alloc0 (gsize block_size)
177 g_return_val_if_fail (block_size > 0, NULL);
179 return g_rc_box_alloc_full (block_size, TRUE, TRUE);
183 * g_arc_box_new:
184 * @type: the type to allocate, typically a structure name
186 * A convenience macro to allocate atomically reference counted
187 * data with the size of the given @type.
189 * This macro calls g_arc_box_alloc() with `sizeof (@type)` and
190 * casts the returned pointer to a pointer of the given @type,
191 * avoiding a type cast in the source code.
193 * This macro cannot return %NULL, as the minimum allocation
194 * size from `sizeof (@type)` is 1 byte.
196 * Returns: (not nullable): a pointer to the allocated memory,
197 * cast to a pointer for the given @type
199 * Since: 2.58
203 * g_arc_box_new0:
204 * @type: the type to allocate, typically a structure name
206 * A convenience macro to allocate atomically reference counted
207 * data with the size of the given @type, and set its contents
208 * to 0.
210 * This macro calls g_arc_box_alloc0() with `sizeof (@type)` and
211 * casts the returned pointer to a pointer of the given @type,
212 * avoiding a type cast in the source code.
214 * This macro cannot return %NULL, as the minimum allocation
215 * size from `sizeof (@type)` is 1 byte.
217 * Returns: (not nullable): a pointer to the allocated memory,
218 * cast to a pointer for the given @type
220 * Since: 2.58
224 * g_arc_box_dup:
225 * @block_size: the number of bytes to copy
226 * @mem_block: (not nullable): the memory to copy
228 * Allocates a new block of data with atomit reference counting
229 * semantics, and copies @block_size bytes of @mem_block
230 * into it.
232 * Returns: (not nullable): a pointer to the allocated memory
234 * Since: 2.58
236 gpointer
237 (g_arc_box_dup) (gsize block_size,
238 gconstpointer mem_block)
240 gpointer res;
242 g_return_val_if_fail (block_size > 0, NULL);
243 g_return_val_if_fail (mem_block != NULL, NULL);
245 res = g_rc_box_alloc_full (block_size, TRUE, FALSE);
246 memcpy (res, mem_block, block_size);
248 return res;
252 * g_arc_box_acquire:
253 * @mem_block: (not nullable): a pointer to reference counted data
255 * Atomically acquires a reference on the data pointed by @mem_block.
257 * Returns: (not nullabl): a pointer to the data, with its reference
258 * count increased
260 * Since: 2.58
262 gpointer
263 (g_arc_box_acquire) (gpointer mem_block)
265 GArcBox *real_box = G_ARC_BOX (mem_block);
267 g_return_val_if_fail (mem_block != NULL, NULL);
268 #ifndef G_DISABLE_ASSERT
269 g_return_val_if_fail (real_box->magic == G_BOX_MAGIC, NULL);
270 #endif
272 g_atomic_ref_count_inc (&real_box->ref_count);
274 return mem_block;
278 * g_arc_box_release:
279 * @mem_block: (not nullable): a pointer to reference counted data
281 * Atomically releases a reference on the data pointed by @mem_block.
283 * If the reference was the last one, it will free the
284 * resources allocated for @mem_block.
286 * Since: 2.58
288 void
289 g_arc_box_release (gpointer mem_block)
291 GArcBox *real_box = G_ARC_BOX (mem_block);
293 g_return_if_fail (mem_block != NULL);
294 #ifndef G_DISABLE_ASSERT
295 g_return_if_fail (real_box->magic == G_BOX_MAGIC);
296 #endif
298 if (g_atomic_ref_count_dec (&real_box->ref_count))
299 g_free (real_box);
303 * g_arc_box_release_full:
304 * @mem_block: (not nullable): a pointer to reference counted data
305 * @clear_func: (not nullable): a function to call when clearing the data
307 * Atomically releases a reference on the data pointed by @mem_block.
309 * If the reference was the last one, it will call @clear_func
310 * to clear the contents of @mem_block, and then will free the
311 * resources allocated for @mem_block.
313 * Since: 2.58
315 void
316 g_arc_box_release_full (gpointer mem_block,
317 GDestroyNotify clear_func)
319 GArcBox *real_box = G_ARC_BOX (mem_block);
321 g_return_if_fail (mem_block != NULL);
322 g_return_if_fail (clear_func != NULL);
323 #ifndef G_DISABLE_ASSERT
324 g_return_if_fail (real_box->magic == G_BOX_MAGIC);
325 #endif
327 if (g_atomic_ref_count_dec (&real_box->ref_count))
329 clear_func (mem_block);
330 g_free (real_box);