703 lines
20 KiB
Diff
703 lines
20 KiB
Diff
|
From 9e5a53d576765819d1c7c233515b9f6e5d77eb61 Mon Sep 17 00:00:00 2001
|
|||
|
From: Emmanuele Bassi <ebassi@gnome.org>
|
|||
|
Date: Wed, 17 Jan 2018 16:38:45 +0000
|
|||
|
Subject: [PATCH] Add reference counting types
|
|||
|
|
|||
|
We have a common pattern for reference counting in GLib, but we always
|
|||
|
implement it with ad hoc code. This is a good chance at trying to
|
|||
|
standardise the implementation and make it public, so that other code
|
|||
|
using GLib can take advantage of shared behaviour and semantics.
|
|||
|
|
|||
|
Instead of simply taking an integer variable, we should create type
|
|||
|
aliases, to immediately distinguish the reference counting semantics of
|
|||
|
the code; we can handle mixing atomic reference counting with a
|
|||
|
non-atomic type (and vice versa) by using differently signed values for
|
|||
|
the atomic and non-atomic cases.
|
|||
|
|
|||
|
The gatomicrefcount type is modelled on the Linux kernel refcount_t
|
|||
|
type; the grefcount type is added to let single-threaded code bases to
|
|||
|
avoid paying the price of atomic memory barriers on reference counting
|
|||
|
operations.
|
|||
|
---
|
|||
|
docs/reference/glib/glib-docs.xml | 1 +
|
|||
|
docs/reference/glib/glib-sections.txt | 15 ++
|
|||
|
glib/Makefile.am | 2 +
|
|||
|
glib/glib.h | 1 +
|
|||
|
glib/grefcount.c | 285 ++++++++++++++++++++++++++
|
|||
|
glib/grefcount.h | 52 +++++
|
|||
|
glib/gtypes.h | 3 +
|
|||
|
glib/meson.build | 2 +
|
|||
|
8 files changed, 361 insertions(+)
|
|||
|
create mode 100644 glib/grefcount.c
|
|||
|
create mode 100644 glib/grefcount.h
|
|||
|
|
|||
|
diff --git a/docs/reference/glib/glib-docs.xml b/docs/reference/glib/glib-docs.xml
|
|||
|
index a0716c1727..26cdafb67b 100644
|
|||
|
--- a/docs/reference/glib/glib-docs.xml
|
|||
|
+++ b/docs/reference/glib/glib-docs.xml
|
|||
|
@@ -119,6 +119,7 @@
|
|||
|
<xi:include href="xml/gvariant.xml"/>
|
|||
|
<xi:include href="gvariant-varargs.xml"/>
|
|||
|
<xi:include href="gvariant-text.xml"/>
|
|||
|
+ <xi:include href="xml/refcount.xml"/>
|
|||
|
</chapter>
|
|||
|
|
|||
|
<chapter id="deprecated">
|
|||
|
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
|
|||
|
index 0183b0898a..331d92c75f 100644
|
|||
|
--- a/docs/reference/glib/glib-sections.txt
|
|||
|
+++ b/docs/reference/glib/glib-sections.txt
|
|||
|
@@ -3449,3 +3449,18 @@ g_hostname_is_ip_address
|
|||
|
g_uuid_string_is_valid
|
|||
|
g_uuid_string_random
|
|||
|
</SECTION>
|
|||
|
+
|
|||
|
+<SECTION>
|
|||
|
+<FILE>refcount</FILE>
|
|||
|
+grefcount
|
|||
|
+g_ref_count_init
|
|||
|
+g_ref_count_inc
|
|||
|
+g_ref_count_dec
|
|||
|
+g_ref_count_compare
|
|||
|
+<SUBSECTION>
|
|||
|
+gatomicrefcount
|
|||
|
+g_atomic_ref_count_init
|
|||
|
+g_atomic_ref_count_inc
|
|||
|
+g_atomic_ref_count_dec
|
|||
|
+g_atomic_ref_count_compare
|
|||
|
+</SECTION>
|
|||
|
diff --git a/glib/Makefile.am b/glib/Makefile.am
|
|||
|
index 0497061265..4d04e09daa 100644
|
|||
|
--- a/glib/Makefile.am
|
|||
|
+++ b/glib/Makefile.am
|
|||
|
@@ -149,6 +149,7 @@ libglib_2_0_la_SOURCES = \
|
|||
|
gquark.c \
|
|||
|
gqueue.c \
|
|||
|
grand.c \
|
|||
|
+ grefcount.c \
|
|||
|
gregex.c \
|
|||
|
gscanner.c \
|
|||
|
gscripttable.h \
|
|||
|
@@ -284,6 +285,7 @@ glibsubinclude_HEADERS = \
|
|||
|
gquark.h \
|
|||
|
gqueue.h \
|
|||
|
grand.h \
|
|||
|
+ grefcount.h \
|
|||
|
gregex.h \
|
|||
|
gscanner.h \
|
|||
|
gsequence.h \
|
|||
|
diff --git a/glib/glib.h b/glib/glib.h
|
|||
|
index 4f5a7f702f..84299c4f90 100644
|
|||
|
--- a/glib/glib.h
|
|||
|
+++ b/glib/glib.h
|
|||
|
@@ -69,6 +69,7 @@
|
|||
|
#include <glib/gquark.h>
|
|||
|
#include <glib/gqueue.h>
|
|||
|
#include <glib/grand.h>
|
|||
|
+#include <glib/grefcount.h>
|
|||
|
#include <glib/gregex.h>
|
|||
|
#include <glib/gscanner.h>
|
|||
|
#include <glib/gsequence.h>
|
|||
|
diff --git a/glib/grefcount.c b/glib/grefcount.c
|
|||
|
new file mode 100644
|
|||
|
index 0000000000..10e35a217d
|
|||
|
--- /dev/null
|
|||
|
+++ b/glib/grefcount.c
|
|||
|
@@ -0,0 +1,285 @@
|
|||
|
+/* grefcount.c: Reference counting
|
|||
|
+ *
|
|||
|
+ * Copyright 2018 Emmanuele Bassi
|
|||
|
+ *
|
|||
|
+ * This library is free software; you can redistribute it and/or
|
|||
|
+ * modify it under the terms of the GNU Lesser General Public
|
|||
|
+ * License as published by the Free Software Foundation; either
|
|||
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|||
|
+ *
|
|||
|
+ * This library is distributed in the hope that it will be useful,
|
|||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
+ * Lesser General Public License for more details.
|
|||
|
+ *
|
|||
|
+ * You should have received a copy of the GNU Lesser General Public
|
|||
|
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|||
|
+ */
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * SECTION:refcount
|
|||
|
+ * @Title: Reference counting
|
|||
|
+ * @Short_description: Reference counting types and functions
|
|||
|
+ *
|
|||
|
+ * Reference counting is a garbage collection mechanism that is based on
|
|||
|
+ * assigning a counter to a data type, or any memory area; the counter is
|
|||
|
+ * increased whenever a new reference to that data type is acquired, and
|
|||
|
+ * decreased whenever the reference is released. Once the last reference
|
|||
|
+ * is released, the resources associated to that data type are freed.
|
|||
|
+ *
|
|||
|
+ * GLib uses reference counting in many of its data types, and provides
|
|||
|
+ * the #grefcount and #gatomicrefcount types to implement safe and atomic
|
|||
|
+ * reference counting semantics in new data types.
|
|||
|
+ *
|
|||
|
+ * It is important to note that #grefcount and #gatomicrefcount should be
|
|||
|
+ * considered completely opaque types; you should always use the provided
|
|||
|
+ * API to increase and decrease the counters, and you should never check
|
|||
|
+ * their content directly, or compare their content with other values.
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+
|
|||
|
+#include "config.h"
|
|||
|
+
|
|||
|
+#include "grefcount.h"
|
|||
|
+
|
|||
|
+#include "gatomic.h"
|
|||
|
+#include "gmessages.h"
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * grefcount:
|
|||
|
+ *
|
|||
|
+ * A type for implementing non-atomic reference count semantics.
|
|||
|
+ *
|
|||
|
+ * Use g_ref_count_init() to initialize it; g_ref_count_inc() to
|
|||
|
+ * increase the counter, and g_ref_count_dec() to decrease it.
|
|||
|
+ *
|
|||
|
+ * It is safe to use #grefcount only if you're expecting to operate
|
|||
|
+ * on the reference counter from a single thread. It is entirely up
|
|||
|
+ * to you to ensure that all reference count changes happen in the
|
|||
|
+ * same thread.
|
|||
|
+ *
|
|||
|
+ * See also: #gatomicrefcount
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * gatomicrefcount:
|
|||
|
+ *
|
|||
|
+ * A type for implementing atomic reference count semantics.
|
|||
|
+ *
|
|||
|
+ * Use g_atomic_ref_count_init() to initialize it; g_atomic_ref_count_inc()
|
|||
|
+ * to increase the counter, and g_atomic_ref_count_dec() to decrease it.
|
|||
|
+ *
|
|||
|
+ * It is safe to use #gatomicrefcount if you're expecting to operate on the
|
|||
|
+ * reference counter from multiple threads.
|
|||
|
+ *
|
|||
|
+ * See also: #grefcount
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * g_ref_count_init:
|
|||
|
+ * @rc: the address of a reference count variable
|
|||
|
+ *
|
|||
|
+ * Initializes a reference count variable.
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+void
|
|||
|
+g_ref_count_init (grefcount *rc)
|
|||
|
+{
|
|||
|
+ g_return_if_fail (rc != NULL);
|
|||
|
+
|
|||
|
+ /* Non-atomic refcounting is implemented using the negative range
|
|||
|
+ * of signed integers:
|
|||
|
+ *
|
|||
|
+ * G_MININT Z¯< 0 > Z⺠G_MAXINT
|
|||
|
+ * |----------------------------|----------------------------|
|
|||
|
+ *
|
|||
|
+ * Acquiring a reference moves us towards MININT, and releasing a
|
|||
|
+ * reference moves us towards 0.
|
|||
|
+ */
|
|||
|
+ *rc = -1;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * g_ref_count_inc:
|
|||
|
+ * @rc: the address of a reference count variable
|
|||
|
+ *
|
|||
|
+ * Increases the reference count.
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+void
|
|||
|
+g_ref_count_inc (grefcount *rc)
|
|||
|
+{
|
|||
|
+ grefcount rrc;
|
|||
|
+
|
|||
|
+ g_return_if_fail (rc != NULL);
|
|||
|
+
|
|||
|
+ rrc = *rc;
|
|||
|
+
|
|||
|
+ g_return_if_fail (rrc < 0);
|
|||
|
+
|
|||
|
+ /* Check for saturation */
|
|||
|
+ if (rrc == G_MININT)
|
|||
|
+ {
|
|||
|
+ g_critical ("Reference count %p has reached saturation", rc);
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ rrc -= 1;
|
|||
|
+
|
|||
|
+ *rc = rrc;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * g_ref_count_dec:
|
|||
|
+ * @rc: the address of a reference count variable
|
|||
|
+ *
|
|||
|
+ * Decreases the reference count.
|
|||
|
+ *
|
|||
|
+ * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+gboolean
|
|||
|
+g_ref_count_dec (grefcount *rc)
|
|||
|
+{
|
|||
|
+ grefcount rrc;
|
|||
|
+
|
|||
|
+ g_return_val_if_fail (rc != NULL, FALSE);
|
|||
|
+
|
|||
|
+ rrc = *rc;
|
|||
|
+
|
|||
|
+ g_return_val_if_fail (rrc < 0, FALSE);
|
|||
|
+
|
|||
|
+ rrc += 1;
|
|||
|
+ if (rrc == 0)
|
|||
|
+ return TRUE;
|
|||
|
+
|
|||
|
+ *rc = rrc;
|
|||
|
+
|
|||
|
+ return FALSE;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * g_ref_count_compare:
|
|||
|
+ * @rc: the address of a reference count variable
|
|||
|
+ * @val: the value to compare
|
|||
|
+ *
|
|||
|
+ * Compares the current value of @rc with @val.
|
|||
|
+ *
|
|||
|
+ * Returns: %TRUE if the reference count is the same
|
|||
|
+ * as the given value
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+gboolean
|
|||
|
+g_ref_count_compare (grefcount *rc,
|
|||
|
+ gint val)
|
|||
|
+{
|
|||
|
+ grefcount rrc;
|
|||
|
+
|
|||
|
+ g_return_val_if_fail (rc != NULL, FALSE);
|
|||
|
+ g_return_val_if_fail (val >= 0, FALSE);
|
|||
|
+
|
|||
|
+ rrc = *rc;
|
|||
|
+
|
|||
|
+ if (val == G_MAXINT)
|
|||
|
+ return rrc == G_MININT;
|
|||
|
+
|
|||
|
+ return rrc == -val;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * g_atomic_ref_count_init:
|
|||
|
+ * @arc: the address of an atomic reference count variable
|
|||
|
+ *
|
|||
|
+ * Atomically initializes a reference count variable.
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+void
|
|||
|
+g_atomic_ref_count_init (gatomicrefcount *arc)
|
|||
|
+{
|
|||
|
+ g_return_if_fail (arc != NULL);
|
|||
|
+
|
|||
|
+ /* Atomic refcounting is implemented using the positive range
|
|||
|
+ * of signed integers:
|
|||
|
+ *
|
|||
|
+ * G_MININT Z¯< 0 > Z⺠G_MAXINT
|
|||
|
+ * |----------------------------|----------------------------|
|
|||
|
+ *
|
|||
|
+ * Acquiring a reference moves us towards MAXINT, and releasing a
|
|||
|
+ * reference moves us towards 0.
|
|||
|
+ */
|
|||
|
+ g_atomic_int_set (arc, 1);
|
|||
|
+}
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * g_atomic_ref_count_inc:
|
|||
|
+ * @arc: the address of an atomic reference count variable
|
|||
|
+ *
|
|||
|
+ * Atomically increases the reference count.
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+void
|
|||
|
+g_atomic_ref_count_inc (gatomicrefcount *arc)
|
|||
|
+{
|
|||
|
+ g_return_if_fail (arc != NULL);
|
|||
|
+ g_return_if_fail (g_atomic_int_get (arc) > 0);
|
|||
|
+
|
|||
|
+ if (g_atomic_int_get (arc) == G_MAXINT)
|
|||
|
+ {
|
|||
|
+ g_critical ("Reference count has reached saturation");
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ g_atomic_int_inc (arc);
|
|||
|
+}
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * g_atomic_ref_count_dec:
|
|||
|
+ * @arc: the address of an atomic reference count variable
|
|||
|
+ *
|
|||
|
+ * Atomically decreases the reference count.
|
|||
|
+ *
|
|||
|
+ * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+gboolean
|
|||
|
+g_atomic_ref_count_dec (gatomicrefcount *arc)
|
|||
|
+{
|
|||
|
+ g_return_val_if_fail (arc != NULL, FALSE);
|
|||
|
+ g_return_val_if_fail (g_atomic_int_get (arc) > 0, FALSE);
|
|||
|
+
|
|||
|
+ return g_atomic_int_dec_and_test (arc);
|
|||
|
+}
|
|||
|
+
|
|||
|
+/**
|
|||
|
+ * g_atomic_ref_count_compare:
|
|||
|
+ * @arc: the address of an atomic reference count variable
|
|||
|
+ * @val: the value to compare
|
|||
|
+ *
|
|||
|
+ * Atomically compares the current value of @arc with @val.
|
|||
|
+ *
|
|||
|
+ * Returns: %TRUE if the reference count is the same
|
|||
|
+ * as the given value
|
|||
|
+ *
|
|||
|
+ * Since: 2.58
|
|||
|
+ */
|
|||
|
+gboolean
|
|||
|
+g_atomic_ref_count_compare (gatomicrefcount *arc,
|
|||
|
+ gint val)
|
|||
|
+{
|
|||
|
+ g_return_val_if_fail (arc != NULL, FALSE);
|
|||
|
+ g_return_val_if_fail (val >= 0, FALSE);
|
|||
|
+
|
|||
|
+ return g_atomic_int_get (arc) == val;
|
|||
|
+}
|
|||
|
diff --git a/glib/grefcount.h b/glib/grefcount.h
|
|||
|
new file mode 100644
|
|||
|
index 0000000000..b24c71e8cb
|
|||
|
--- /dev/null
|
|||
|
+++ b/glib/grefcount.h
|
|||
|
@@ -0,0 +1,52 @@
|
|||
|
+/* grefcount.h: Reference counting
|
|||
|
+ *
|
|||
|
+ * Copyright 2018 Emmanuele Bassi
|
|||
|
+ *
|
|||
|
+ * This library is free software; you can redistribute it and/or
|
|||
|
+ * modify it under the terms of the GNU Lesser General Public
|
|||
|
+ * License as published by the Free Software Foundation; either
|
|||
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|||
|
+ *
|
|||
|
+ * This library is distributed in the hope that it will be useful,
|
|||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
+ * Lesser General Public License for more details.
|
|||
|
+ *
|
|||
|
+ * You should have received a copy of the GNU Lesser General Public
|
|||
|
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|||
|
+ */
|
|||
|
+
|
|||
|
+#ifndef __GREFCOUNT_H__
|
|||
|
+#define __GREFCOUNT_H__
|
|||
|
+
|
|||
|
+#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
|||
|
+#error "Only <glib.h> can be included directly."
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+#include <glib/gtypes.h>
|
|||
|
+
|
|||
|
+G_BEGIN_DECLS
|
|||
|
+
|
|||
|
+GLIB_AVAILABLE_IN_2_56
|
|||
|
+void g_ref_count_init (grefcount *rc);
|
|||
|
+GLIB_AVAILABLE_IN_2_56
|
|||
|
+void g_ref_count_inc (grefcount *rc);
|
|||
|
+GLIB_AVAILABLE_IN_2_56
|
|||
|
+gboolean g_ref_count_dec (grefcount *rc);
|
|||
|
+GLIB_AVAILABLE_IN_2_56
|
|||
|
+gboolean g_ref_count_compare (grefcount *rc,
|
|||
|
+ gint val);
|
|||
|
+
|
|||
|
+GLIB_AVAILABLE_IN_2_56
|
|||
|
+void g_atomic_ref_count_init (gatomicrefcount *arc);
|
|||
|
+GLIB_AVAILABLE_IN_2_56
|
|||
|
+void g_atomic_ref_count_inc (gatomicrefcount *arc);
|
|||
|
+GLIB_AVAILABLE_IN_2_56
|
|||
|
+gboolean g_atomic_ref_count_dec (gatomicrefcount *arc);
|
|||
|
+GLIB_AVAILABLE_IN_2_56
|
|||
|
+gboolean g_atomic_ref_count_compare (gatomicrefcount *arc,
|
|||
|
+ gint val);
|
|||
|
+
|
|||
|
+G_END_DECLS
|
|||
|
+
|
|||
|
+#endif /* __GREFCOUNT_H__ */
|
|||
|
diff --git a/glib/gtypes.h b/glib/gtypes.h
|
|||
|
index 09d9bd1456..67adb7f1f8 100644
|
|||
|
--- a/glib/gtypes.h
|
|||
|
+++ b/glib/gtypes.h
|
|||
|
@@ -510,6 +510,9 @@ struct _GTimeVal
|
|||
|
glong tv_usec;
|
|||
|
};
|
|||
|
|
|||
|
+typedef gint grefcount;
|
|||
|
+typedef volatile gint gatomicrefcount;
|
|||
|
+
|
|||
|
G_END_DECLS
|
|||
|
|
|||
|
/* We prefix variable declarations so they can
|
|||
|
diff --git a/glib/meson.build b/glib/meson.build
|
|||
|
index 036d1f4d60..76d354c2a7 100644
|
|||
|
--- a/glib/meson.build
|
|||
|
+++ b/glib/meson.build
|
|||
|
@@ -76,6 +76,7 @@ glib_sub_headers = files(
|
|||
|
'gquark.h',
|
|||
|
'gqueue.h',
|
|||
|
'grand.h',
|
|||
|
+ 'grefcount.h',
|
|||
|
'gregex.h',
|
|||
|
'gscanner.h',
|
|||
|
'gsequence.h',
|
|||
|
@@ -159,6 +160,7 @@ glib_sources = files(
|
|||
|
'gquark.c',
|
|||
|
'gqueue.c',
|
|||
|
'grand.c',
|
|||
|
+ 'grefcount.c',
|
|||
|
'gregex.c',
|
|||
|
'gscanner.c',
|
|||
|
'gsequence.c',
|
|||
|
--
|
|||
|
GitLab
|
|||
|
|
|||
|
From 827c208cbf9cc0ef17b8c4531a40aafe1edc3f01 Mon Sep 17 00:00:00 2001
|
|||
|
From: Emmanuele Bassi <ebassi@gnome.org>
|
|||
|
Date: Mon, 4 Jun 2018 11:38:40 +0100
|
|||
|
Subject: [PATCH] Use macros for refcount types API
|
|||
|
|
|||
|
If we're using GCC we can use __extension__ to inline the grefcount and
|
|||
|
gatomicrefcount API, and avoid the function call.
|
|||
|
|
|||
|
These macros are only enabled if G_DISABLE_CHECKS is defined, as they
|
|||
|
remove critical warnings when the reference counters achieve saturation.
|
|||
|
---
|
|||
|
glib/grefcount.c | 20 +++++++-------
|
|||
|
glib/grefcount.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|||
|
2 files changed, 80 insertions(+), 10 deletions(-)
|
|||
|
|
|||
|
diff --git a/glib/grefcount.c b/glib/grefcount.c
|
|||
|
index 10e35a217d..37085316b9 100644
|
|||
|
--- a/glib/grefcount.c
|
|||
|
+++ b/glib/grefcount.c
|
|||
|
@@ -89,7 +89,7 @@
|
|||
|
* Since: 2.58
|
|||
|
*/
|
|||
|
void
|
|||
|
-g_ref_count_init (grefcount *rc)
|
|||
|
+(g_ref_count_init) (grefcount *rc)
|
|||
|
{
|
|||
|
g_return_if_fail (rc != NULL);
|
|||
|
|
|||
|
@@ -114,7 +114,7 @@ g_ref_count_init (grefcount *rc)
|
|||
|
* Since: 2.58
|
|||
|
*/
|
|||
|
void
|
|||
|
-g_ref_count_inc (grefcount *rc)
|
|||
|
+(g_ref_count_inc) (grefcount *rc)
|
|||
|
{
|
|||
|
grefcount rrc;
|
|||
|
|
|||
|
@@ -147,7 +147,7 @@ g_ref_count_inc (grefcount *rc)
|
|||
|
* Since: 2.58
|
|||
|
*/
|
|||
|
gboolean
|
|||
|
-g_ref_count_dec (grefcount *rc)
|
|||
|
+(g_ref_count_dec) (grefcount *rc)
|
|||
|
{
|
|||
|
grefcount rrc;
|
|||
|
|
|||
|
@@ -179,8 +179,8 @@ g_ref_count_dec (grefcount *rc)
|
|||
|
* Since: 2.58
|
|||
|
*/
|
|||
|
gboolean
|
|||
|
-g_ref_count_compare (grefcount *rc,
|
|||
|
- gint val)
|
|||
|
+(g_ref_count_compare) (grefcount *rc,
|
|||
|
+ gint val)
|
|||
|
{
|
|||
|
grefcount rrc;
|
|||
|
|
|||
|
@@ -204,7 +204,7 @@ g_ref_count_compare (grefcount *rc,
|
|||
|
* Since: 2.58
|
|||
|
*/
|
|||
|
void
|
|||
|
-g_atomic_ref_count_init (gatomicrefcount *arc)
|
|||
|
+(g_atomic_ref_count_init) (gatomicrefcount *arc)
|
|||
|
{
|
|||
|
g_return_if_fail (arc != NULL);
|
|||
|
|
|||
|
@@ -229,7 +229,7 @@ g_atomic_ref_count_init (gatomicrefcount *arc)
|
|||
|
* Since: 2.58
|
|||
|
*/
|
|||
|
void
|
|||
|
-g_atomic_ref_count_inc (gatomicrefcount *arc)
|
|||
|
+(g_atomic_ref_count_inc) (gatomicrefcount *arc)
|
|||
|
{
|
|||
|
g_return_if_fail (arc != NULL);
|
|||
|
g_return_if_fail (g_atomic_int_get (arc) > 0);
|
|||
|
@@ -254,7 +254,7 @@ g_atomic_ref_count_inc (gatomicrefcount *arc)
|
|||
|
* Since: 2.58
|
|||
|
*/
|
|||
|
gboolean
|
|||
|
-g_atomic_ref_count_dec (gatomicrefcount *arc)
|
|||
|
+(g_atomic_ref_count_dec) (gatomicrefcount *arc)
|
|||
|
{
|
|||
|
g_return_val_if_fail (arc != NULL, FALSE);
|
|||
|
g_return_val_if_fail (g_atomic_int_get (arc) > 0, FALSE);
|
|||
|
@@ -275,8 +275,8 @@ g_atomic_ref_count_dec (gatomicrefcount *arc)
|
|||
|
* Since: 2.58
|
|||
|
*/
|
|||
|
gboolean
|
|||
|
-g_atomic_ref_count_compare (gatomicrefcount *arc,
|
|||
|
- gint val)
|
|||
|
+(g_atomic_ref_count_compare) (gatomicrefcount *arc,
|
|||
|
+ gint val)
|
|||
|
{
|
|||
|
g_return_val_if_fail (arc != NULL, FALSE);
|
|||
|
g_return_val_if_fail (val >= 0, FALSE);
|
|||
|
diff --git a/glib/grefcount.h b/glib/grefcount.h
|
|||
|
index b24c71e8cb..dec9a5ffb8 100644
|
|||
|
--- a/glib/grefcount.h
|
|||
|
+++ b/glib/grefcount.h
|
|||
|
@@ -47,6 +47,76 @@ GLIB_AVAILABLE_IN_2_58
|
|||
|
gboolean g_atomic_ref_count_compare (gatomicrefcount *arc,
|
|||
|
gint val);
|
|||
|
|
|||
|
+/* On GCC we can use __extension__ to inline the API without using
|
|||
|
+ * ancillary functions; we only do this when disabling checks, as
|
|||
|
+ * it disables warnings when saturating the reference counters
|
|||
|
+ */
|
|||
|
+#if defined(__GNUC__) && defined(G_DISABLE_CHECKS)
|
|||
|
+
|
|||
|
+# define g_ref_count_init(rc) \
|
|||
|
+ (G_GNUC_EXTENSION ({ \
|
|||
|
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
|
|||
|
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
|||
|
+ *(rc) = -1; \
|
|||
|
+ }))
|
|||
|
+
|
|||
|
+# define g_ref_count_inc(rc) \
|
|||
|
+ (G_GNUC_EXTENSION ({ \
|
|||
|
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
|
|||
|
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
|||
|
+ if (*(rc) == G_MININT) ; else { \
|
|||
|
+ *(rc) -= 1; \
|
|||
|
+ } \
|
|||
|
+ }))
|
|||
|
+
|
|||
|
+# define g_ref_count_dec(rc) \
|
|||
|
+ (G_GNUC_EXTENSION ({ \
|
|||
|
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
|
|||
|
+ grefcount __rc = *(rc); \
|
|||
|
+ __rc += 1; \
|
|||
|
+ if (__rc == 0) ; else { \
|
|||
|
+ *(rc) = __rc; \
|
|||
|
+ } \
|
|||
|
+ (gboolean) (__rc == 0); \
|
|||
|
+ }))
|
|||
|
+
|
|||
|
+# define g_ref_count_compare(rc,val) \
|
|||
|
+ (G_GNUC_EXTENSION ({ \
|
|||
|
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (grefcount)); \
|
|||
|
+ (void) (0 ? *(rc) ^ (val) : 1); \
|
|||
|
+ (gboolean) (*(rc) == -(val)); \
|
|||
|
+ }))
|
|||
|
+
|
|||
|
+# define g_atomic_ref_count_init(rc) \
|
|||
|
+ (G_GNUC_EXTENSION ({ \
|
|||
|
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
|
|||
|
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
|||
|
+ g_atomic_int_set ((rc), 1); \
|
|||
|
+ }))
|
|||
|
+
|
|||
|
+# define g_atomic_ref_count_inc(rc) \
|
|||
|
+ (G_GNUC_EXTENSION ({ \
|
|||
|
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
|
|||
|
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
|||
|
+ (void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \
|
|||
|
+ }))
|
|||
|
+
|
|||
|
+# define g_atomic_ref_count_dec(rc) \
|
|||
|
+ (G_GNUC_EXTENSION ({ \
|
|||
|
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
|
|||
|
+ (void) (0 ? *(rc) ^ *(rc) : 1); \
|
|||
|
+ g_atomic_int_dec_and_test ((rc)); \
|
|||
|
+ }))
|
|||
|
+
|
|||
|
+# define g_atomic_ref_count_compare(rc,val) \
|
|||
|
+ (G_GNUC_EXTENSION ({ \
|
|||
|
+ G_STATIC_ASSERT (sizeof *(rc) == sizeof (gatomicrefcount)); \
|
|||
|
+ (void) (0 ? *(rc) ^ (val) : 1); \
|
|||
|
+ (gboolean) (g_atomic_int_get (rc) == (val)); \
|
|||
|
+ }))
|
|||
|
+
|
|||
|
+#endif /* __GNUC__ && G_DISABLE_CHECKS */
|
|||
|
+
|
|||
|
G_END_DECLS
|
|||
|
|
|||
|
#endif /* __GREFCOUNT_H__ */
|
|||
|
--
|
|||
|
GitLab
|
|||
|
|
|||
|
From 09c149453ac969dedb1cb2d15d489d1dd81412bf Mon Sep 17 00:00:00 2001
|
|||
|
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
|||
|
Date: Sat, 13 Oct 2018 23:10:33 +0200
|
|||
|
Subject: [PATCH] grefcount: add missing gatomic.h
|
|||
|
MIME-Version: 1.0
|
|||
|
Content-Type: text/plain; charset=UTF-8
|
|||
|
Content-Transfer-Encoding: 8bit
|
|||
|
|
|||
|
Without gatomic.h, build fails on:
|
|||
|
In file included from garcbox.c:24:0:
|
|||
|
garcbox.c: In function ‘g_atomic_rc_box_acquire’:
|
|||
|
grefcount.h:101:13: error: implicit declaration of function ‘g_atomic_int_get’; did you mean ‘__atomic_store’? [-Werror=implicit-function-declaration]
|
|||
|
(void) (g_atomic_int_get (rc) == G_MAXINT ? 0 : g_atomic_int_inc ((rc))); \
|
|||
|
^
|
|||
|
garcbox.c:292:3: note: in expansion of macro ‘g_atomic_ref_count_inc’
|
|||
|
g_atomic_ref_count_inc (&real_box->ref_count);
|
|||
|
|
|||
|
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
|||
|
---
|
|||
|
glib/grefcount.h | 1 +
|
|||
|
1 file changed, 1 insertion(+)
|
|||
|
|
|||
|
diff --git a/glib/grefcount.h b/glib/grefcount.h
|
|||
|
index dec9a5ffb8..b6eced1b7d 100644
|
|||
|
--- a/glib/grefcount.h
|
|||
|
+++ b/glib/grefcount.h
|
|||
|
@@ -23,6 +23,7 @@
|
|||
|
#error "Only <glib.h> can be included directly."
|
|||
|
#endif
|
|||
|
|
|||
|
+#include <glib/gatomic.h>
|
|||
|
#include <glib/gtypes.h>
|
|||
|
|
|||
|
G_BEGIN_DECLS
|
|||
|
--
|
|||
|
GitLab
|
|||
|
|