[gtk/docs-gtk-org] Port the reference counting sections in the GLib docs
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/docs-gtk-org] Port the reference counting sections in the GLib docs
- Date: Wed, 4 Aug 2021 14:47:01 +0000 (UTC)
commit 212e5b5679d79b9c23bb7bd6d2f748aecd97336a
Author: Emmanuele Bassi <ebassi gnome org>
Date: Wed Aug 4 15:45:48 2021 +0100
Port the reference counting sections in the GLib docs
The reference counting types sections can be combined into a single
document.
glib/glib/glib.toml.in | 3 +-
glib/glib/meson.build | 1 +
glib/glib/reference-counting.md | 161 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+), 1 deletion(-)
---
diff --git a/glib/glib/glib.toml.in b/glib/glib/glib.toml.in
index 0cfa1621e6..0fdf56dee6 100644
--- a/glib/glib/glib.toml.in
+++ b/glib/glib/glib.toml.in
@@ -33,7 +33,8 @@ base_url = "https://gitlab.gnome.org/GNOME/glib/-/blob/master/"
urlmap_file = "urlmap.js"
# The same order will be used when generating the index
content_files = [
- "error-reporting.md"
+ "error-reporting.md",
+ "reference-counting.md",
]
[[object]]
diff --git a/glib/glib/meson.build b/glib/glib/meson.build
index acedc3d529..c9a2521283 100644
--- a/glib/glib/meson.build
+++ b/glib/glib/meson.build
@@ -1,5 +1,6 @@
expand_content_files = [
'error-reporting.md',
+ 'reference-counting.md',
]
glib_gir = meson.current_source_dir() / 'GLib-2.0.gir'
diff --git a/glib/glib/reference-counting.md b/glib/glib/reference-counting.md
new file mode 100644
index 0000000000..b3944b1e84
--- /dev/null
+++ b/glib/glib/reference-counting.md
@@ -0,0 +1,161 @@
+Title: Reference Counting
+
+## Reference counting types
+
+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.
+
+## Reference counted data
+
+A "reference counted box", or "RcBox", is an opaque wrapper data type that
+is guaranteed to be as big as the size of a given data type, and which
+augments the given data type with reference counting semantics for its
+memory management.
+
+RcBox is useful if you have a plain old data type, like a structure
+typically placed on the stack, and you wish to provide additional API to use
+it on the heap; or if you want to implement a new type to be passed around
+by reference without necessarily implementing copy/free semantics or your
+own reference counting.
+
+The typical use is:
+
+```c
+typedef struct {
+ char *name;
+ char *address;
+ char *city;
+ char *state;
+ int age;
+} Person;
+
+Person *
+person_new (void)
+{
+ return g_rc_box_new0 (Person);
+}
+```
+
+Every time you wish to acquire a reference on the memory, you should call
+`g_rc_box_acquire()`; similarly, when you wish to release a reference you
+should call `g_rc_box_release()`:
+
+```c
+// Add a Person to the Database; the Database acquires ownership
+// of the Person instance
+void
+add_person_to_database (Database *db, Person *p)
+{
+ db->persons = g_list_prepend (db->persons, g_rc_box_acquire (p));
+}
+
+// Removes a Person from the Database; the reference acquired by
+// add_person_to_database() is released here
+void
+remove_person_from_database (Database *db, Person *p)
+{
+ db->persons = g_list_remove (db->persons, p);
+ g_rc_box_release (p);
+}
+```
+
+If you have additional memory allocated inside the structure, you can use
+`g_rc_box_release_full()`, which takes a function pointer, which will be
+called if the reference released was the last:
+
+```c
+void
+person_clear (Person *p)
+{
+ g_free (p->name);
+ g_free (p->address);
+ g_free (p->city);
+ g_free (p->state);
+}
+
+void
+remove_person_from_database (Database *db, Person *p)
+{
+ db->persons = g_list_remove (db->persons, p);
+ g_rc_box_release_full (p, (GDestroyNotify) person_clear);
+}
+```
+
+If you wish to transfer the ownership of a reference counted data
+type without increasing the reference count, you can use `g_steal_pointer()`:
+
+```c
+ Person *p = g_rc_box_new (Person);
+
+ // fill_person_details() is defined elsewhere
+ fill_person_details (p);
+
+ // add_person_to_database_no_ref() is defined elsewhere; it adds
+ // a Person to the Database without taking a reference
+ add_person_to_database_no_ref (db, g_steal_pointer (&p));
+```
+
+## Thread safety
+
+The reference counting operations on data allocated using
+`g_rc_box_alloc()`, `g_rc_box_new()`, and `g_rc_box_dup()` are not thread
+safe; it is your code's responsibility to ensure that references are
+acquired are released on the same thread.
+
+If you need thread safe reference counting, you should use the
+`g_atomic_rc_*` API:
+
+| Operation | Atomic equivalent |
+|---------------------------|----------------------------------|
+| `g_rc_box_alloc()` | `g_atomic_rc_box_alloc()` |
+| `g_rc_box_new()` | `g_atomic_rc_box_new()` |
+| `g_rc_box_dup()` | `g_atomic_rc_box_dup()` |
+| `g_rc_box_acquire()` | `g_atomic_rc_box_acquire()` |
+| `g_rc_box_release()` | `g_atomic_rc_box_release()` |
+| `g_rc_box_release_full()` | `g_atomic_rc_box_release_full()` |
+
+The reference counting operations on data allocated using
+`g_atomic_rc_box_alloc()`, `g_atomic_rc_box_new()`, and
+`g_atomic_rc_box_dup()` are guaranteed to be atomic, and thus can be safely
+be performed by different threads. It is important to note that only the
+reference acquisition and release are atomic; changes to the content of the
+data are your responsibility.
+
+It is a programmer error to mix the atomic and non-atomic reference counting
+operations.
+
+## Automatic pointer clean up
+
+If you want to add `g_autoptr()` support to your plain old data type through
+reference counting, you can use the `G_DEFINE_AUTOPTR_CLEANUP_FUNC()` and
+`g_rc_box_release()`:
+
+```c
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, g_rc_box_release)
+```
+
+If you need to clear the contents of the data, you will need to use an
+ancillary function that calls `g_rc_box_release_full()`:
+
+```c
+static void
+my_data_struct_release (MyDataStruct *data)
+{
+ // my_data_struct_clear() is defined elsewhere
+ g_rc_box_release_full (data, (GDestroyNotify) my_data_struct_clear);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MyDataStruct, my_data_struct_release)
+```
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]