1/* grefcount.h: Reference counting
2 *
3 * Copyright 2018 Emmanuele Bassi
4 *
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.
9 *
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.
14 *
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/>.
17 */
18
19#ifndef __GREFCOUNT_H__
20#define __GREFCOUNT_H__
21
22#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
23#error "Only <glib.h> can be included directly."
24#endif
25
26#include <glib/gtypes.h>
27
28G_BEGIN_DECLS
29
30GLIB_AVAILABLE_IN_2_58
31void g_ref_count_init (grefcount *rc);
32GLIB_AVAILABLE_IN_2_58
33void g_ref_count_inc (grefcount *rc);
34GLIB_AVAILABLE_IN_2_58
35gboolean g_ref_count_dec (grefcount *rc);
36GLIB_AVAILABLE_IN_2_58
37gboolean g_ref_count_compare (grefcount *rc,
38 gint val);
39
40GLIB_AVAILABLE_IN_2_58
41void g_atomic_ref_count_init (gatomicrefcount *arc);
42GLIB_AVAILABLE_IN_2_58
43void g_atomic_ref_count_inc (gatomicrefcount *arc);
44GLIB_AVAILABLE_IN_2_58
45gboolean g_atomic_ref_count_dec (gatomicrefcount *arc);
46GLIB_AVAILABLE_IN_2_58
47gboolean g_atomic_ref_count_compare (gatomicrefcount *arc,
48 gint val);
49
50/* On GCC we can use __extension__ to inline the API without using
51 * ancillary functions; we only do this when disabling checks, as
52 * it disables warnings when saturating the reference counters
53 */
54#if defined(__GNUC__) && defined(G_DISABLE_CHECKS)
55
56# define g_ref_count_init(rc) \
57 (G_GNUC_EXTENSION ({ \
58 G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
59 (void) (0 ? *(rc) ^ *(rc) : 1); \
60 *(rc) = -1; \
61 }))
62
63# define g_ref_count_inc(rc) \
64 (G_GNUC_EXTENSION ({ \
65 G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
66 (void) (0 ? *(rc) ^ *(rc) : 1); \
67 if (*(rc) == G_MININT) ; else { \
68 *(rc) -= 1; \
69 } \
70 }))
71
72# define g_ref_count_dec(rc) \
73 (G_GNUC_EXTENSION ({ \
74 G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
75 grefcount __rc = *(rc); \
76 __rc += 1; \
77 if (__rc == 0) ; else { \
78 *(rc) = __rc; \
79 } \
80 (gboolean) (__rc == 0); \
81 }))
82
83# define g_ref_count_compare(rc,val) \
84 (G_GNUC_EXTENSION ({ \
85 G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
86 (void) (0 ? *(rc) ^ (val) : 1); \
87 (gboolean) (*(rc) == -(val)); \
88 }))
89
90# define g_atomic_ref_count_init(rc) \
91 (G_GNUC_EXTENSION ({ \
92 G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
93 (void) (0 ? *(rc) ^ *(rc) : 1); \
94 g_atomic_int_set ((rc), 1); \
95 }))
96
97# define g_atomic_ref_count_inc(rc) \
98 (G_GNUC_EXTENSION ({ \
99 G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
100 (void) (0 ? *(rc) ^ *(rc) : 1); \
101 (void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \
102 }))
103
104# define g_atomic_ref_count_dec(rc) \
105 (G_GNUC_EXTENSION ({ \
106 G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
107 (void) (0 ? *(rc) ^ *(rc) : 1); \
108 g_atomic_int_dec_and_test ((rc)); \
109 }))
110
111# define g_atomic_ref_count_compare(rc,val) \
112 (G_GNUC_EXTENSION ({ \
113 G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
114 (void) (0 ? *(rc) ^ (val) : 1); \
115 (gboolean) (g_atomic_int_get (rc) == (val)); \
116 }))
117
118#endif /* __GNUC__ && G_DISABLE_CHECKS */
119
120G_END_DECLS
121
122#endif /* __GREFCOUNT_H__ */
123