Fix getauxval error at qemu
[platform/upstream/glib.git] / glib / grefcount.c
1 /* grefcount.c: Reference counting
2  *
3  * Copyright 2018  Emmanuele Bassi
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /**
22  * SECTION:refcount
23  * @Title: Reference counting
24  * @Short_description: Reference counting types and functions
25  *
26  * Reference counting is a garbage collection mechanism that is based on
27  * assigning a counter to a data type, or any memory area; the counter is
28  * increased whenever a new reference to that data type is acquired, and
29  * decreased whenever the reference is released. Once the last reference
30  * is released, the resources associated to that data type are freed.
31  *
32  * GLib uses reference counting in many of its data types, and provides
33  * the #grefcount and #gatomicrefcount types to implement safe and atomic
34  * reference counting semantics in new data types.
35  *
36  * It is important to note that #grefcount and #gatomicrefcount should be
37  * considered completely opaque types; you should always use the provided
38  * API to increase and decrease the counters, and you should never check
39  * their content directly, or compare their content with other values.
40  *
41  * Since: 2.58
42  */
43
44 #include "config.h"
45
46 #include "grefcount.h"
47
48 #include "gatomic.h"
49 #include "gmessages.h"
50
51 /**
52  * grefcount:
53  *
54  * A type for implementing non-atomic reference count semantics.
55  *
56  * Use g_ref_count_init() to initialize it; g_ref_count_inc() to
57  * increase the counter, and g_ref_count_dec() to decrease it.
58  *
59  * It is safe to use #grefcount only if you're expecting to operate
60  * on the reference counter from a single thread. It is entirely up
61  * to you to ensure that all reference count changes happen in the
62  * same thread.
63  *
64  * See also: #gatomicrefcount
65  *
66  * Since: 2.58
67  */
68
69 /**
70  * gatomicrefcount:
71  *
72  * A type for implementing atomic reference count semantics.
73  *
74  * Use g_atomic_ref_count_init() to initialize it; g_atomic_ref_count_inc()
75  * to increase the counter, and g_atomic_ref_count_dec() to decrease it.
76  *
77  * It is safe to use #gatomicrefcount if you're expecting to operate on the
78  * reference counter from multiple threads.
79  *
80  * See also: #grefcount
81  *
82  * Since: 2.58
83  */
84
85 /**
86  * g_ref_count_init:
87  * @rc: the address of a reference count variable
88  *
89  * Initializes a reference count variable to 1.
90  *
91  * Since: 2.58
92  */
93 void
94 (g_ref_count_init) (grefcount *rc)
95 {
96   g_return_if_fail (rc != NULL);
97
98   /* Non-atomic refcounting is implemented using the negative range
99    * of signed integers:
100    *
101    * G_MININT                 Z¯< 0 > Z⁺                G_MAXINT
102    * |----------------------------|----------------------------|
103    *
104    * Acquiring a reference moves us towards MININT, and releasing a
105    * reference moves us towards 0.
106    */
107   *rc = -1;
108 }
109
110 /**
111  * g_ref_count_inc:
112  * @rc: the address of a reference count variable
113  *
114  * Increases the reference count.
115  *
116  * Since: 2.58
117  */
118 void
119 (g_ref_count_inc) (grefcount *rc)
120 {
121   grefcount rrc;
122
123   g_return_if_fail (rc != NULL);
124
125   rrc = *rc;
126
127   g_return_if_fail (rrc < 0);
128
129   /* Check for saturation */
130   if (rrc == G_MININT)
131     {
132       g_critical ("Reference count %p has reached saturation", rc);
133       return;
134     }
135
136   rrc -= 1;
137
138   *rc = rrc;
139 }
140
141 /**
142  * g_ref_count_dec:
143  * @rc: the address of a reference count variable
144  *
145  * Decreases the reference count.
146  *
147  * If %TRUE is returned, the reference count reached 0. After this point, @rc
148  * is an undefined state and must be reinitialized with
149  * g_ref_count_init() to be used again.
150  *
151  * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise
152  *
153  * Since: 2.58
154  */
155 gboolean
156 (g_ref_count_dec) (grefcount *rc)
157 {
158   grefcount rrc;
159
160   g_return_val_if_fail (rc != NULL, FALSE);
161
162   rrc = *rc;
163
164   g_return_val_if_fail (rrc < 0, FALSE);
165
166   rrc += 1;
167   if (rrc == 0)
168     return TRUE;
169
170   *rc = rrc;
171
172   return FALSE;
173 }
174
175 /**
176  * g_ref_count_compare:
177  * @rc: the address of a reference count variable
178  * @val: the value to compare
179  *
180  * Compares the current value of @rc with @val.
181  *
182  * Returns: %TRUE if the reference count is the same
183  *   as the given value
184  *
185  * Since: 2.58
186  */
187 gboolean
188 (g_ref_count_compare) (grefcount *rc,
189                        gint       val)
190 {
191   grefcount rrc;
192
193   g_return_val_if_fail (rc != NULL, FALSE);
194   g_return_val_if_fail (val >= 0, FALSE);
195
196   rrc = *rc;
197
198   if (val == G_MAXINT)
199     return rrc == G_MININT;
200
201   return rrc == -val;
202 }
203
204 /**
205  * g_atomic_ref_count_init:
206  * @arc: the address of an atomic reference count variable
207  *
208  * Initializes a reference count variable to 1.
209  *
210  * Since: 2.58
211  */
212 void
213 (g_atomic_ref_count_init) (gatomicrefcount *arc)
214 {
215   g_return_if_fail (arc != NULL);
216
217   /* Atomic refcounting is implemented using the positive range
218    * of signed integers:
219    *
220    * G_MININT                 Z¯< 0 > Z⁺                G_MAXINT
221    * |----------------------------|----------------------------|
222    *
223    * Acquiring a reference moves us towards MAXINT, and releasing a
224    * reference moves us towards 0.
225    */
226   *arc = 1;
227 }
228
229 /**
230  * g_atomic_ref_count_inc:
231  * @arc: the address of an atomic reference count variable
232  *
233  * Atomically increases the reference count.
234  *
235  * Since: 2.58
236  */
237 void
238 (g_atomic_ref_count_inc) (gatomicrefcount *arc)
239 {
240   gint old_value;
241
242   g_return_if_fail (arc != NULL);
243   old_value = g_atomic_int_add (arc, 1);
244   g_return_if_fail (old_value > 0);
245
246   if (old_value == G_MAXINT)
247     g_critical ("Reference count has reached saturation");
248 }
249
250 /**
251  * g_atomic_ref_count_dec:
252  * @arc: the address of an atomic reference count variable
253  *
254  * Atomically decreases the reference count.
255  *
256  * If %TRUE is returned, the reference count reached 0. After this point, @arc
257  * is an undefined state and must be reinitialized with
258  * g_atomic_ref_count_init() to be used again.
259  *
260  * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise
261  *
262  * Since: 2.58
263  */
264 gboolean
265 (g_atomic_ref_count_dec) (gatomicrefcount *arc)
266 {
267   gint old_value;
268
269   g_return_val_if_fail (arc != NULL, FALSE);
270   old_value = g_atomic_int_add (arc, -1);
271   g_return_val_if_fail (old_value > 0, FALSE);
272
273   return old_value == 1;
274 }
275
276 /**
277  * g_atomic_ref_count_compare:
278  * @arc: the address of an atomic reference count variable
279  * @val: the value to compare
280  *
281  * Atomically compares the current value of @arc with @val.
282  *
283  * Returns: %TRUE if the reference count is the same
284  *   as the given value
285  *
286  * Since: 2.58
287  */
288 gboolean
289 (g_atomic_ref_count_compare) (gatomicrefcount *arc,
290                               gint             val)
291 {
292   g_return_val_if_fail (arc != NULL, FALSE);
293   g_return_val_if_fail (val >= 0, FALSE);
294
295   return g_atomic_int_get (arc) == val;
296 }