| 
									
										
										
										
											2023-11-29 12:13:13 +00:00
										 |  |  |  | Title: Floating References | 
					
						
							| 
									
										
										
										
											2023-10-09 23:17:19 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-29 12:13:13 +00:00
										 |  |  |  | # Floating References
 | 
					
						
							| 
									
										
										
										
											2023-10-09 23:17:19 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | **Note**: Floating references are a C convenience API and should not be used | 
					
						
							|  |  |  |  | in modern GObject code. Language bindings in particular find the concept | 
					
						
							|  |  |  |  | highly problematic, as floating references are not identifiable through | 
					
						
							|  |  |  |  | annotations, and neither are deviations from the floating reference | 
					
						
							|  |  |  |  | behavior, like types that inherit from [class@GObject.InitiallyUnowned] and | 
					
						
							|  |  |  |  | still return a full reference from [`id@g_object_new`]. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [class@GObject.InitiallyUnowned] is derived from [class@GObject.Object]. The | 
					
						
							|  |  |  |  | only difference between the two is that the initial reference of a | 
					
						
							|  |  |  |  | `GInitiallyUnowned` is flagged as a "floating" reference. This means that it | 
					
						
							|  |  |  |  | is not specifically claimed to be "owned" by any code portion. The main | 
					
						
							|  |  |  |  | motivation for providing floating references is C convenience. In | 
					
						
							|  |  |  |  | particular, it allows code to be written as: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```c | 
					
						
							|  |  |  |  | container = create_container (); | 
					
						
							|  |  |  |  | container_add_child (container, create_child()); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | If `container_add_child()` calls [`method@GObject.Object.ref_sink`] on the | 
					
						
							|  |  |  |  | passed-in child, no reference of the newly created child is leaked. Without | 
					
						
							|  |  |  |  | floating references, `container_add_child()` can only acquire a reference | 
					
						
							|  |  |  |  | the new child, so to implement this code without reference leaks, it would | 
					
						
							|  |  |  |  | have to be written as: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```c | 
					
						
							|  |  |  |  | Child *child; | 
					
						
							|  |  |  |  | container = create_container (); | 
					
						
							|  |  |  |  | child = create_child (); | 
					
						
							|  |  |  |  | container_add_child (container, child); | 
					
						
							|  |  |  |  | g_object_unref (child); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | The floating reference can be converted into an ordinary reference by | 
					
						
							|  |  |  |  | calling `g_object_ref_sink()`. For already sunken objects (objects that | 
					
						
							|  |  |  |  | don't have a floating reference anymore), `g_object_ref_sink()` is | 
					
						
							|  |  |  |  | equivalent to [`method@GObject.Object.ref`] and returns a new reference. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Since floating references are useful almost exclusively for C convenience, | 
					
						
							|  |  |  |  | language bindings that provide automated reference and memory ownership | 
					
						
							|  |  |  |  | maintenance (such as smart pointers or garbage collection) should not expose | 
					
						
							|  |  |  |  | floating references in their API. The best practice for handling types that | 
					
						
							|  |  |  |  | have initially floating references is to immediately sink those references | 
					
						
							|  |  |  |  | after `g_object_new()` returns, by checking if the `GType` inherits from | 
					
						
							|  |  |  |  | `GInitiallyUnowned`. For instance: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```c | 
					
						
							|  |  |  |  | GObject *res = g_object_new_with_properties (gtype, | 
					
						
							|  |  |  |  |                                              n_props, | 
					
						
							|  |  |  |  |                                              prop_names, | 
					
						
							|  |  |  |  |                                              prop_values); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // or: if (g_type_is_a (gtype, G_TYPE_INITIALLY_UNOWNED)) | 
					
						
							|  |  |  |  | if (G_IS_INITIALLY_UNOWNED (res)) | 
					
						
							|  |  |  |  |   g_object_ref_sink (res); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | return res; | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Some object implementations may need to save an object's floating state | 
					
						
							|  |  |  |  | across certain code portions (an example is `GtkMenu` in GTK3), to achieve | 
					
						
							|  |  |  |  | this, the following sequence can be used: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```c | 
					
						
							|  |  |  |  | // save floating state | 
					
						
							|  |  |  |  | gboolean was_floating = g_object_is_floating (object); | 
					
						
							|  |  |  |  | g_object_ref_sink (object); | 
					
						
							|  |  |  |  | // protected code portion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ... | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // restore floating state | 
					
						
							|  |  |  |  | if (was_floating) | 
					
						
							|  |  |  |  |   g_object_force_floating (object); | 
					
						
							|  |  |  |  | else | 
					
						
							|  |  |  |  |   g_object_unref (object); // release previously acquired reference | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Replacing floating references with annotations
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | You should avoid basing your object hierarchy on floating references, as | 
					
						
							|  |  |  |  | they are hard to understand even in C, and introduce additional limitations | 
					
						
							|  |  |  |  | when consuming a GObject-based API in other languages. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | One way to express the ownership transfer between ‘container’ and ‘child’ | 
					
						
							|  |  |  |  | instances is to use ownership transfer annotations in your documentation and | 
					
						
							|  |  |  |  | introspection data. For instance, you can implement this pattern: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```c | 
					
						
							|  |  |  |  | container_add_child (container, create_child ()); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | without leaking by having `container_add_child()` defined as: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```c | 
					
						
							|  |  |  |  | /** | 
					
						
							|  |  |  |  |  * container_add_child: | 
					
						
							|  |  |  |  |  * @self: a container | 
					
						
							|  |  |  |  |  * @child: (transfer full): the child to add to the container | 
					
						
							|  |  |  |  |  * | 
					
						
							|  |  |  |  |  * ... | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | void | 
					
						
							|  |  |  |  | container_add_child (Container *container, | 
					
						
							|  |  |  |  |                      Child *child) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   container->children = g_list_append (container->children, child); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | The container does not explicitly acquire a reference on the child; instead, | 
					
						
							|  |  |  |  | the ownership of the child is transferred to the container. The transfer | 
					
						
							|  |  |  |  | annotation will be used by language bindings to ensure that there are no | 
					
						
							|  |  |  |  | leaks; and documentation tools will explicitly note that the callee now owns | 
					
						
							|  |  |  |  | the value passed by the caller. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Replacing floating references with weak references
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Another option for replacing floating references is to use weak references | 
					
						
							|  |  |  |  | in place of strong ones. A ‘container’ can acquire a weak reference on the | 
					
						
							|  |  |  |  | ‘child’ instance by using [`method@GObject.Object.weak_ref`]. Once the | 
					
						
							|  |  |  |  | child instance loses its last strong reference, the container holding a | 
					
						
							|  |  |  |  | weak reference is notified, and it can either remove the child from its | 
					
						
							|  |  |  |  | internal list, or turn a weak reference into a strong one. |