https://developer.gnome.org/glib/unstable/glib-GVariant.html#g-variant-ref-sink
I have read the above glib manual which says: "GVariant
uses a floating reference count system. All functions with names starting with g_variant_new_
return floating references." But where is the actual description of what a floating reference count is? I couldn't find a comprehensive description of it.
In particular I want to understand when there is a need to unreference a variant and when not to. For example:
GVariant *a_v = g_variant_new_boolean(TRUE);
GVariant *another_v = g_variant_new("v", a_v);
a_v
because it is consumed by the second g_variant_new
. Is that correct?another_v
(assuming another_v
is not passed to anything else from that point on)?There is a section on floating references in the GObject reference manual which goes into a bit more detail. Floating references may seem a bit obscure, but they are really very useful for C so taking a few minutes to really understand them is a good idea.
I'm going to assume you understand how reference counting work—if not there is a lot of documentation out there, take a few minutes and read up on that first.
First, lets look at what would happen with your example if g_variant_new_boolean
returned a regular reference. When you first get the value, the reference count would be 1. When you pass it to g_variant_new
, g_variant_new
will increase the reference count to 2. At some point I assume you'll dispose of another_v
, at which point the reference count for a_v
will drop to 1… but remember, the memory isn't released until the reference count reaches 0.
In order to get around this you have two options. The first is to make g_variant_new
steal the caller's reference, which basically sucks as a solution. You give away your reference when you call g_variant_new
(or any similar function), so in the future you need to manually ref a_v
every time you want to pass it to something else.
The other option is to just unref it manually when you're done. It's not the end of the world, but it's easy to forget to do or get wrong (like by forgetting to unref it in an error path).
What GVariant does instead is return a "floating" ref. The easiest way to think of it (IMHO) is that the first time g_variant_ref
gets called it doesn't really do anything—it just "sinks" the floating ref. The reference count goes from 1 to 1. Subsequent calls to g_variant_ref
, however, will increase the reference count.
Now lets look at what actually happens with your example. g_variant_new_boolean
returns a floating reference. You then pass it to g_variant_new
, which calls g_variant_ref
, which sinks the floating reference. The reference count is now 1, and when another_v
's refcount reaches 0 a_v
's refcount will be decremented, in this case reaching 0 and everything will be freed. No need for you to call g_variant_unref
.
The cool part about floating references, though, is what happens with something like this:
GVariant *a_v = g_variant_new_boolean(TRUE);
GVariant *another_v = g_variant_new("v", a_v);
GVariant *yet_another_v = g_variant_new("v", a_v);
When g_variant_new
is called the second time a_v
's refcount will increment again (to 2). No need to call g_variant_ref
before passing a_v
to g_variant_new
a second time—the first call looks just like the first, and consistency is a very nice feature in an API.
At this point it's probably obvious, but yes, you do need to call g_variant_unref
on another_v
(and, in that last example, yet_another_v
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With