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