+2005-05-05 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gdataset.[ch] glib/gdatasetprivate.h: Add
+ g_datalist_set/unset_flags(), g_datalist_get_flags() functions
+ to squeeze some bits into a GDataSet... this is needed for
+ efficient implementation of toggle references in GObject.
+
+ * tests/gobject/references.c tests/gobject/Makefile.am:
+ Add a test case for weak and toggle references.
+
+ * glib/gfileutils.[ch]: Rename g_file_replace() back
+ to g_file_set_contents().
+
+ * glib/glib.symbols: Update.
+
2005-05-02 Matthias Clasen <mclasen@redhat.com>
* glib/gstring.c (g_str_equal, g_str_hash): Move docs
+2005-05-05 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gdataset.[ch] glib/gdatasetprivate.h: Add
+ g_datalist_set/unset_flags(), g_datalist_get_flags() functions
+ to squeeze some bits into a GDataSet... this is needed for
+ efficient implementation of toggle references in GObject.
+
+ * tests/gobject/references.c tests/gobject/Makefile.am:
+ Add a test case for weak and toggle references.
+
+ * glib/gfileutils.[ch]: Rename g_file_replace() back
+ to g_file_set_contents().
+
+ * glib/glib.symbols: Update.
+
2005-05-02 Matthias Clasen <mclasen@redhat.com>
* glib/gstring.c (g_str_equal, g_str_hash): Move docs
+2005-05-05 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gdataset.[ch] glib/gdatasetprivate.h: Add
+ g_datalist_set/unset_flags(), g_datalist_get_flags() functions
+ to squeeze some bits into a GDataSet... this is needed for
+ efficient implementation of toggle references in GObject.
+
+ * tests/gobject/references.c tests/gobject/Makefile.am:
+ Add a test case for weak and toggle references.
+
+ * glib/gfileutils.[ch]: Rename g_file_replace() back
+ to g_file_set_contents().
+
+ * glib/glib.symbols: Update.
+
2005-05-02 Matthias Clasen <mclasen@redhat.com>
* glib/gstring.c (g_str_equal, g_str_hash): Move docs
+2005-05-05 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gdataset.[ch] glib/gdatasetprivate.h: Add
+ g_datalist_set/unset_flags(), g_datalist_get_flags() functions
+ to squeeze some bits into a GDataSet... this is needed for
+ efficient implementation of toggle references in GObject.
+
+ * tests/gobject/references.c tests/gobject/Makefile.am:
+ Add a test case for weak and toggle references.
+
+ * glib/gfileutils.[ch]: Rename g_file_replace() back
+ to g_file_set_contents().
+
+ * glib/glib.symbols: Update.
+
2005-05-02 Matthias Clasen <mclasen@redhat.com>
* glib/gstring.c (g_str_equal, g_str_hash): Move docs
+2005-05-05 Owen Taylor <otaylor@redhat.com>
+
+ * glib/Makefile.am glib/glib-sections.txt gobject/gobject-sections.txt:
+ Update
+
+ * gobject/tmpl/objects.sgml: Document toggle-references.
+
2005-05-02 Matthias Clasen <mclasen@redhat.com>
* glib/tmpl/hash_tables.sgml: Move some docs inline.
build \
gobject \
config.h \
+ gdatasetprivate.h \
glibintl.h \
gbsearcharray.h \
gmoduleconf.h \
GFileTest
g_file_error_from_errno
g_file_get_contents
-g_file_replace
+g_file_set_contents
g_file_test
g_mkstemp
g_file_open_tmp
<SUBSECTION Private>
G_NATIVE_ATEXIT
g_ATEXIT
+g_win32_get_system_data_dirs_for_module
ATEXIT
</SECTION>
<SUBSECTION>
g_datalist_foreach
g_datalist_clear
+g_datalist_set_flags
+g_datalist_unset_flags
+g_datalist_get_flags
+G_DATALIST_FLAGS_MASK
</SECTION>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GAllocator ##### -->
<para>
The <structname>GAllocator</structname> struct contains private data. and should only be accessed
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GArray ##### -->
<para>
Contains the public fields of an <link linkend="glib-arrays">Array</link>.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GPtrArray ##### -->
<para>
Contains the public fields of a pointer array.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GAsyncQueue ##### -->
<para>
The #GAsyncQueue struct is an opaque data structure, which represents
</variablelist>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### FUNCTION g_atomic_int_get ##### -->
<para>
Reads the value of the integer pointed to by @atomic. Also acts as
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_BYTE_ORDER ##### -->
<para>
The host byte order.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GCache ##### -->
<para>
The #GCache struct is an opaque data structure containing information about
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### FUNCTION g_convert ##### -->
<para>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GData ##### -->
<para>
The #GData struct is an opaque data structure to represent a
@datalist: a datalist.
+<!-- ##### FUNCTION g_datalist_set_flags ##### -->
+<para>
+
+</para>
+
+@datalist:
+@flags:
+
+
+<!-- ##### FUNCTION g_datalist_unset_flags ##### -->
+<para>
+
+</para>
+
+@datalist:
+@flags:
+
+
+<!-- ##### FUNCTION g_datalist_get_flags ##### -->
+<para>
+
+</para>
+
+@datalist:
+@Returns:
+
+
+<!-- ##### MACRO G_DATALIST_FLAGS_MASK ##### -->
+<para>
+
+</para>
+
+
+
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO g_dataset_id_set_data ##### -->
<para>
Sets the data element associated with the given #GQuark id.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_USEC_PER_SEC ##### -->
<para>
Number of microseconds in one second (1 million). This macro is provided for
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GError ##### -->
<para>
The <structname>GError</structname> structure contains
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### ENUM GFileError ##### -->
<para>
Values corresponding to <literal>errno</literal> codes returned from file operations
@Returns:
+<!-- ##### FUNCTION g_file_set_contents ##### -->
+<para>
+
+</para>
+
+@filename:
+@contents:
+@length:
+@error:
+@Returns:
+
+
<!-- ##### FUNCTION g_file_test ##### -->
<para>
@Returns:
+<!-- ##### FUNCTION g_chmod ##### -->
+<para>
+
+</para>
+
+@filename:
+@mode:
+@Returns:
+
+
+<!-- ##### FUNCTION g_access ##### -->
+<para>
+
+</para>
+
+@filename:
+@mode:
+@Returns:
+
+
+<!-- ##### FUNCTION g_creat ##### -->
+<para>
+
+</para>
+
+@filename:
+@mode:
+@Returns:
+
+
Desktop Entry Parser
+<!-- ##### SECTION ./tmpl/glib-unused.sgml:Stability_Level ##### -->
+
+
+
<!-- ##### ENUM GChannelError ##### -->
<para>
@error:
@Returns:
+<!-- ##### FUNCTION g_file_replace ##### -->
+<para>
+
+</para>
+
+@filename:
+@contents:
+@length:
+@error:
+@Returns:
+
<!-- ##### FUNCTION g_io_channel_error_quark ##### -->
<para>
@v1:
@v2:
-@Returns:
+@Returns:
<!-- ##### FUNCTION g_str_hash ##### -->
<para>
</para>
-@v:
-@Returns:
+@v:
+@Returns:
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GHookList ##### -->
<para>
The <structname>GHookList</structname> struct represents a
The gettext manual.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO _ ##### -->
<para>
Marks a string for translation, gets replaced with the translated string
</variablelist>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GIOChannel ##### -->
<para>
A data structure representing an IO Channel. The fields should be considered
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GKeyFile ##### -->
<para>
The <structname>GKeyFile</structname> struct contains only private fields
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_MININT ##### -->
<para>
The minimum value which can be held in a #gint.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GList ##### -->
<para>
The #GList struct is used for each element in a doubly-linked list.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GSList ##### -->
<para>
The #GSList struct is used for each element in the singly-linked list.
<link linkend="glib-Type-Conversion-Macros">Type Conversion Macros</link>.
@next: contains the link to the next element in the list.
-
<!-- ##### FUNCTION g_slist_alloc ##### -->
<para>
Allocates space for one #GSList element.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_OS_WIN32 ##### -->
<para>
This macro is defined only on Windows. So you can bracket
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_INLINE_FUNC ##### -->
<para>
Used to declare inline functions. If inline functions are not supported on
Since: 2.8
+
+
<!-- ##### MACRO G_GNUC_FUNCTION ##### -->
<para>
Expands to the GNU C <literal>__FUNCTION__</literal> variable if the
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GMainLoop ##### -->
<para>
The <structname>GMainLoop</structname> struct is an opaque data type
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### ENUM GMarkupError ##### -->
<para>
Error codes returned by markup parsing.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO g_new ##### -->
<para>
Allocates @n_structs elements of type @struct_type.
<!-- ##### MACRO g_memmove ##### -->
<para>
-Copies a block of memory @n bytes long, from @s to @d.
-The source and destination areas may overlap.
-</para>
-<para>
-In order to use this function, you must include <filename>string.h</filename>
-yourself, because this macro will typically simply resolve
-to <function>memmove()</function> and GLib does not include <filename>string.h</filename> for you.
+
</para>
-@d: the destination address to copy the bytes to.
-@s: the source address to copy the bytes from.
-@n: the number of bytes to copy.
+@dest:
+@src:
+@len:
<!-- ##### FUNCTION g_memdup ##### -->
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GMemChunk ##### -->
<para>
The #GMemChunk struct is an opaque data structure representing a memory
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_LOG_DOMAIN ##### -->
<para>
Defines the log domain.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### FUNCTION g_get_application_name ##### -->
<para>
@variable:
+<!-- ##### FUNCTION g_listenv ##### -->
+<para>
+
+</para>
+
+@Returns:
+
+
<!-- ##### FUNCTION g_get_user_name ##### -->
<para>
</para>
-@Returns:
+@Returns:
<!-- ##### FUNCTION g_get_real_name ##### -->
</para>
-@Returns:
+@Returns:
<!-- ##### FUNCTION g_get_user_cache_dir ##### -->
</para>
-@Returns:
+@Returns:
<!-- ##### FUNCTION g_basename ##### -->
</para>
-@file_name:
-@Returns:
+@file_name:
+@Returns:
<!-- ##### FUNCTION g_path_skip_root ##### -->
@string:
@keys:
-@nkeys:
-@Returns:
+@nkeys:
+@Returns:
<!-- ##### STRUCT GDebugKey ##### -->
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GModule ##### -->
<para>
The #GModule struct is an opaque data structure to represent a
<ulink url="http://cch.loria.fr/documentation/IEEE754/numerical_comp_guide/ncg_math.doc.html">http://cch.loria.fr/documentation/IEEE754/numerical_comp_guide/ncg_math.doc.html</ulink>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_IEEE754_FLOAT_BIAS ##### -->
<para>
See <ulink url="http://cch.loria.fr/documentation/IEEE754/numerical_comp_guide/ncg_math.doc.html">http://cch.loria.fr/documentation/IEEE754/numerical_comp_guide/ncg_math.doc.html</ulink>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### ENUM GOptionError ##### -->
<para>
Error codes returned by option parsing.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GPatternSpec ##### -->
<para>
A <structname>GPatternSpec</structname> is the 'compiled' form of a pattern.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### TYPEDEF GQuark ##### -->
<para>
A GQuark is an integer which uniquely identifies a particular string.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GQueue ##### -->
<para>
Contains the public fields of a <link linkend="glib-queues">Queue</link>.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GRand ##### -->
<para>
The #GRand struct is an opaque data structure. It should only be
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GRelation ##### -->
<para>
The #GRelation struct is an opaque data structure to represent a
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GScanner ##### -->
<para>
The data structure representing a lexical scanner.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### ENUM GShellError ##### -->
<para>
Error codes returned by shell functions.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### ENUM GSpawnError ##### -->
<para>
Error codes returned by spawning processes.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GStringChunk ##### -->
<para>
An opaque data structure representing String Chunks.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### FUNCTION g_strdup ##### -->
<para>
Duplicates a string.
</para>
@string: the destination #GString. Its current contents are destroyed.
-@rval: the string to copy into @string
+@rval: the string to copy into @string
@Returns: the destination #GString.
<!-- # Unused Parameters # -->
@val: the string to copy into @string.
</variablelist>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GThreadPool ##### -->
<para>
The #GThreadPool struct represents a thread pool. It has six public
</variablelist>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_THREADS_ENABLED ##### -->
<para>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GTimer ##### -->
<para>
Opaque datatype that records a start time.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GTrashStack ##### -->
<para>
Each piece of memory that is pushed onto the stack
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GTree ##### -->
<para>
The <structname>GTree</structname> struct is an opaque data structure representing a
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GNode ##### -->
<para>
The <structname>GNode</structname> struct represents one node in a
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO GINT_TO_POINTER ##### -->
<para>
Stuffs an integer into a pointer type.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### TYPEDEF gboolean ##### -->
<para>
A standard <type>boolean</type> type.
</variablelist>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### TYPEDEF gunichar ##### -->
<para>
A type which can hold any UCS-4 character code.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### VARIABLE glib_major_version ##### -->
<para>
The major version number of the GLib library.
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### FUNCTION g_print ##### -->
<para>
Outputs a formatted message via the print handler.
g_object_weak_unref
g_object_add_weak_pointer
g_object_remove_weak_pointer
+GToggleNotify
+g_object_add_toggle_ref
+g_object_remove_toggle_ref
g_object_connect
g_object_disconnect
g_object_set
#GParamSpecBoxed, g_param_spec_boxed()
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### USER_FUNCTION GBoxedCopyFunc ##### -->
<para>
This function is provided by the user and should produce a copy of the passed
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_CLOSURE_NEEDS_MARSHAL ##### -->
<para>
Returns %TRUE if a #GClosureMarshal marshaller has not yet been set on
g_object_set_property(), g_object_get_property(), g_value_register_transform_func()
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### MACRO G_TYPE_IS_PARAM ##### -->
<para>
Returns whether @type "is a" %G_TYPE_PARAM.
#GTypeModule and g_type_register_dynamic().
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GTypePlugin ##### -->
<para>
The <structname>GTypePlugin</structname> typedef is used as a placeholder
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### STRUCT GObject ##### -->
<para>
All the fields in the <structname>GObject</structname> structure are private
@weak_pointer_location: The memory address of a pointer.
+<!-- ##### USER_FUNCTION GToggleNotify ##### -->
+<para>
+A callback function used for notification when the state
+of a toggle reference changes. See g_object_add_toggle_ref().
+</para>
+
+@data: Callback data passed to g_object_add_toggle_ref()
+@object: The object on which g_object_add_toggle_ref() was called.
+@is_last_ref: %TRUE if the toggle reference is now the
+ last reference to the object. %FALSE if the toggle
+ reference was the last reference and there are now other
+ references.
+
+
+<!-- ##### FUNCTION g_object_add_toggle_ref ##### -->
+<para>
+Increases the reference count of the object by one and sets a
+callback to be called when all other references to the object are
+dropped, or when this is already the last reference to the object
+and another reference is established.
+</para>
+<para>
+This functionality is intended for binding @object to a proxy
+object managed by another memory manager. This is done with two
+paired references: the strong reference added by
+g_object_add_toggle_ref() and a reverse reference to the proxy
+object which is either a strong reference or weak reference.
+</para>
+<para>
+The setup is that when there are no other references to @object,
+only a weak reference is held in the reverse direction from @object
+to the proxy object, but when there are other references held to
+@object, a strong reference is held. The @notify callback is called
+when the reference from @object to the proxy object should be
+<firstterm>toggled</firstterm> from strong to weak (@is_last_ref
+true) or weak to strong (@is_last_ref false).
+</para>
+<para>
+Since a (normal) reference must be held to the object before
+calling g_object_toggle_ref(), the initial state of the reverse
+link is always strong.
+</para>
+<para>
+Multiple toggle references may be added to the same gobject,
+however if there are multiple toggle references to an object, none
+of them will ever be notified until all but one are removed. For
+this reason, you should only ever use a toggle reference if there
+is important state in the proxy object.
+</para>
+
+@object: a #GObject
+@notify: a function to call when this reference is the
+ last reference to the object, or is no longer
+ the last reference.
+@data: data to pass to @notify
+
+
+<!-- ##### FUNCTION g_object_remove_toggle_ref ##### -->
+<para>
+Removes a reference added with g_object_add_toggle_ref(). The
+reference count of the object is decreased by one.
+</para>
+
+@object: a #GObject
+@notify: a function to call when this reference is the
+ last reference to the object, or is no longer
+ the last reference.
+@data: data to pass to @notify
+
+
<!-- ##### FUNCTION g_object_connect ##### -->
<para>
A convenience function to connect multiple signals at once.
@default_value: default value for the property specified
@epsilon: values closer than @epsilon will be considered identical
by g_param_values_cmp(); the default value is 1e-90.
-
<!-- ##### FUNCTION g_param_spec_double ##### -->
<para>
</para>
+<!-- ##### SECTION Stability_Level ##### -->
+
+
<!-- ##### UNION GTypeCValue ##### -->
<para>
A union holding one collected value.
gcompletion.c \
gconvert.c \
gdataset.c \
+ gdatasetprivate.h \
gdate.c \
gdir.c \
gerror.c \
#include "glib.h"
#include "galias.h"
+#include "gdatasetprivate.h"
/* --- defines --- */
static gchar **g_quarks = NULL;
static GQuark g_quark_seq_id = 0;
-
/* --- functions --- */
/* HOLDS: g_dataset_global_lock */
/* unlink *all* items before walking their destructors
*/
- list = *datalist;
- *datalist = NULL;
+ list = G_DATALIST_GET_POINTER (datalist);
+ G_DATALIST_SET_POINTER (datalist, NULL);
while (list)
{
if (!g_dataset_location_ht)
g_data_initialize ();
- while (*datalist)
+ while (G_DATALIST_GET_POINTER (datalist))
g_datalist_clear_i (datalist);
G_UNLOCK (g_dataset_global);
}
{
register GData *list;
- list = *datalist;
+ list = G_DATALIST_GET_POINTER (datalist);
if (!data)
{
register GData *prev;
prev->next = list->next;
else
{
- *datalist = list->next;
+ G_DATALIST_SET_POINTER (datalist, list->next);
/* the dataset destruction *must* be done
* prior to invokation of the data destroy function
*/
- if (!*datalist && dataset)
+ if (!list->next && dataset)
g_dataset_destroy_internal (dataset);
}
}
else
list = g_chunk_new (GData, g_data_mem_chunk);
- list->next = *datalist;
+ list->next = G_DATALIST_GET_POINTER (datalist);
list->id = key_id;
list->data = data;
list->destroy_func = destroy_func;
- *datalist = list;
+ G_DATALIST_SET_POINTER (datalist, list);
}
return NULL;
{
register GData *list;
- for (list = *datalist; list; list = list->next)
+ for (list = G_DATALIST_GET_POINTER (datalist); list; list = list->next)
if (list->id == key_id)
return list->data;
}
g_return_if_fail (datalist != NULL);
g_return_if_fail (func != NULL);
- for (list = *datalist; list; list = next)
+ for (list = G_DATALIST_GET_POINTER (datalist); list; list = next)
{
next = list->next;
func (list->id, list->data, user_data);
*datalist = NULL;
}
+/**
+ * g_datalist_set_flags:
+ * @datalist: pointer to the location that holds a list
+ * @flags: the flags to turn on. The values of the flags are
+ * restricted by %G_DATALIST_FLAGS_MASK (currently
+ * 3; giving two possible boolean flags).
+ * A value for @flags that doesn't fit within the mask is
+ * an error.
+ *
+ * Turns on flag values for a data list. This function is used
+ * to keep a small number of boolean flags in an object with
+ * a data list without using any additional space. It is
+ * not generally useful except in circumstances where space
+ * is very tight. (It is used in the base #GObject type, for
+ * example.)
+ **/
+void
+g_datalist_set_flags (GData **datalist,
+ guint flags)
+{
+ g_return_if_fail (datalist != NULL);
+ g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
+
+ G_DATALIST_SET_FLAGS (datalist, flags);
+}
+
+/**
+ * g_datalist_unset_flags:
+ * @datalist: pointer to the location that holds a list
+ * @flags: the flags to turn off. The values of the flags are
+ * restricted by %G_DATALIST_FLAGS_MASK (currently
+ * 3: giving two possible boolean flags).
+ * A value for @flags that doesn't fit within the mask is
+ * an error.
+ *
+ * Turns off flag values for a data list. See g_datalist_unset_flags()
+ **/
+void
+g_datalist_unset_flags (GData **datalist,
+ guint flags)
+{
+ g_return_if_fail (datalist != NULL);
+ g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
+
+ G_DATALIST_UNSET_FLAGS (datalist, flags);
+}
+
+/**
+ * g_datalist_get_flags:
+ * @datalist: pointer to the location that holds a list
+ *
+ * Gets flags values packed in together with the datalist.
+ * See g_datalist_set_flags().
+ *
+ * Return value: the flags of the datalist
+ **/
+guint
+g_datalist_get_flags (GData **datalist)
+{
+ g_return_val_if_fail (datalist != NULL, 0);
+
+ return G_DATALIST_GET_FLAGS (datalist);
+}
+
/* HOLDS: g_dataset_global_lock */
static void
g_data_initialize (void)
/* Keyed Data List
*/
-void g_datalist_init (GData **datalist);
-void g_datalist_clear (GData **datalist);
-gpointer g_datalist_id_get_data (GData **datalist,
- GQuark key_id);
-void g_datalist_id_set_data_full (GData **datalist,
- GQuark key_id,
- gpointer data,
- GDestroyNotify destroy_func);
-gpointer g_datalist_id_remove_no_notify (GData **datalist,
- GQuark key_id);
-void g_datalist_foreach (GData **datalist,
- GDataForeachFunc func,
- gpointer user_data);
+void g_datalist_init (GData **datalist);
+void g_datalist_clear (GData **datalist);
+gpointer g_datalist_id_get_data (GData **datalist,
+ GQuark key_id);
+void g_datalist_id_set_data_full (GData **datalist,
+ GQuark key_id,
+ gpointer data,
+ GDestroyNotify destroy_func);
+gpointer g_datalist_id_remove_no_notify (GData **datalist,
+ GQuark key_id);
+void g_datalist_foreach (GData **datalist,
+ GDataForeachFunc func,
+ gpointer user_data);
+
+/**
+ * G_DATALIST_FLAGS_MASK:
+ *
+ * A bitmask that restricts the possible flags passed to
+ * g_datalist_set_flags(). Passing a flags value where
+ * flags & ~G_DATALIST_FLAGS_MASK != 0 is an error.
+ */
+#define G_DATALIST_FLAGS_MASK 0x3
+
+void g_datalist_set_flags (GData **datalist,
+ guint flags);
+void g_datalist_unset_flags (GData **datalist,
+ guint flags);
+guint g_datalist_get_flags (GData **datalist);
+
#define g_datalist_id_set_data(dl, q, d) \
g_datalist_id_set_data_full ((dl), (q), (d), NULL)
#define g_datalist_id_remove_data(dl, q) \
--- /dev/null
+/* GLIB - Library of useful routines for C programming
+ * gdataset-private.h: Internal macros for accessing dataset values
+ * Copyright (C) 2005 Red Hat
+ *
+ * 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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __G_DATASETPRIVATE_H__
+#define __G_DATASETPRIVATE_H__
+
+#include <glib/gdataset.h>
+
+G_BEGIN_DECLS
+
+#define G_DATALIST_GET_FLAGS(datalist) \
+ ((gsize)*(datalist) & G_DATALIST_FLAGS_MASK)
+#define G_DATALIST_SET_FLAGS(datalist, flags) G_STMT_START { \
+ *datalist = (GData *)((flags) | (gsize)*(datalist)); \
+} G_STMT_END
+#define G_DATALIST_UNSET_FLAGS(datalist, flags) G_STMT_START { \
+ *datalist = (GData *)(~(gsize)(flags) & (gsize)*(datalist)); \
+} G_STMT_END
+
+#define G_DATALIST_GET_POINTER(datalist) \
+ ((GData *)((gsize)*(datalist) & ~(gsize)G_DATALIST_FLAGS_MASK))
+#define G_DATALIST_SET_POINTER(datalist,pointer) G_STMT_START { \
+ *(datalist) = (GData *)(G_DATALIST_GET_FLAGS (datalist) | \
+ (gsize)pointer); \
+} G_STMT_END
+
+G_END_DECLS
+
+#endif /* __G_DATASETPRIVATE_H__ */
}
/**
- * g_file_replace:
+ * g_file_set_contents:
* @filename: name of a file to write @contents to, in the GLib file name
* encoding
* @contents: string to write to the file
* Since: 2.8
**/
gboolean
-g_file_replace (const gchar *filename,
- const gchar *contents,
- gssize length,
- GError **error)
+g_file_set_contents (const gchar *filename,
+ const gchar *contents,
+ gssize length,
+ GError **error)
{
gchar *tmp_filename;
gboolean retval;
gchar **contents,
gsize *length,
GError **error);
-gboolean g_file_replace (const gchar *filename,
+gboolean g_file_set_contents (const gchar *filename,
const gchar *contents,
gssize length,
GError **error);
#if IN_FILE(__G_DATASET_C__)
g_datalist_clear
g_datalist_foreach
+g_datalist_get_flags
g_datalist_id_get_data
g_datalist_id_remove_no_notify
g_datalist_id_set_data_full
+g_datalist_set_flags
+g_datalist_unset_flags
g_datalist_init
g_dataset_destroy
g_dataset_foreach
g_file_error_from_errno
g_file_error_quark
g_file_get_contents PRIVATE
-g_file_replace
+g_file_set_contents
g_file_open_tmp PRIVATE
g_file_test PRIVATE
g_file_read_link
+2005-05-05 Owen Taylor <otaylor@redhat.com>
+
+ * gobject.[ch] gobject.symbols: Add
+ g_object_add/remove_toggle_ref() functions to get notification
+ when a reference count is the last remaining reference; this
+ enables better memory management for language bindings.
+ (http://mail.gnome.org/archives/gtk-devel-list/2005-April/msg00095.html)
+
2005-04-29 Matthias Clasen <mclasen@redhat.com>
* gobject.symbols:
*/
#include "gobject.h"
#include "gobjectalias.h"
+#include <glib/gdatasetprivate.h>
/*
* MT safe
#define PARAM_SPEC_PARAM_ID(pspec) ((pspec)->param_id)
#define PARAM_SPEC_SET_PARAM_ID(pspec, id) ((pspec)->param_id = (id))
+#define OBJECT_HAS_TOGGLE_REF_FLAG 0x1
+#define OBJECT_HAS_TOGGLE_REF(object) \
+ ((G_DATALIST_GET_FLAGS(&(object)->qdata) & OBJECT_HAS_TOGGLE_REF_FLAG) != 0)
+
/* --- signals --- */
enum {
/* --- variables --- */
static GQuark quark_closure_array = 0;
static GQuark quark_weak_refs = 0;
+static GQuark quark_toggle_refs = 0;
static GParamSpecPool *pspec_pool = NULL;
static GObjectNotifyContext property_notify_context = { 0, };
static gulong gobject_signals[LAST_SIGNAL] = { 0, };
quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
quark_weak_refs = g_quark_from_static_string ("GObject-weak-references");
+ quark_toggle_refs = g_quark_from_static_string ("GObject-toggle-references");
pspec_pool = g_param_spec_pool_new (TRUE);
property_notify_context.quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
property_notify_context.dispatcher = g_object_notify_dispatcher;
found_one = TRUE;
wstack->n_weak_refs -= 1;
if (i != wstack->n_weak_refs)
- {
- wstack->weak_refs[i].notify = wstack->weak_refs[wstack->n_weak_refs].notify;
- wstack->weak_refs[i].data = wstack->weak_refs[wstack->n_weak_refs].data;
- }
+ wstack->weak_refs[i] = wstack->weak_refs[wstack->n_weak_refs];
+
break;
}
}
weak_pointer_location);
}
+typedef struct {
+ GObject *object;
+ guint n_toggle_refs;
+ struct {
+ GToggleNotify notify;
+ gpointer data;
+ } toggle_refs[1]; /* flexible array */
+} ToggleRefStack;
+
+static void
+toggle_refs_notify (GObject *object,
+ gboolean is_last_ref)
+{
+ ToggleRefStack *tstack = g_datalist_id_get_data (&object->qdata, quark_toggle_refs);
+
+ /* Reentrancy here is not as tricky as it seems, because a toggle reference
+ * will only be notified when there is exactly one of them.
+ */
+ g_assert (tstack->n_toggle_refs == 1);
+ tstack->toggle_refs[0].notify (tstack->toggle_refs[0].data, tstack->object, is_last_ref);
+}
+
+void
+g_object_add_toggle_ref (GObject *object,
+ GToggleNotify notify,
+ gpointer data)
+{
+ ToggleRefStack *tstack;
+ guint i;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (notify != NULL);
+ g_return_if_fail (object->ref_count >= 1);
+
+ g_object_ref (object);
+
+ tstack = g_datalist_id_remove_no_notify (&object->qdata, quark_toggle_refs);
+ if (tstack)
+ {
+ i = tstack->n_toggle_refs++;
+ /* allocate i = tstate->n_toggle_refs - 1 positions beyond the 1 declared
+ * in tstate->toggle_refs */
+ tstack = g_realloc (tstack, sizeof (*tstack) + sizeof (tstack->toggle_refs[0]) * i);
+ }
+ else
+ {
+ tstack = g_renew (ToggleRefStack, NULL, 1);
+ tstack->object = object;
+ tstack->n_toggle_refs = 1;
+ i = 0;
+ }
+
+ /* Set a flag for fast lookup after adding the first toggle reference */
+ if (tstack->n_toggle_refs == 1)
+ G_DATALIST_SET_FLAGS (&object->qdata, OBJECT_HAS_TOGGLE_REF_FLAG);
+
+ tstack->toggle_refs[i].notify = notify;
+ tstack->toggle_refs[i].data = data;
+ g_datalist_id_set_data_full (&object->qdata, quark_toggle_refs, tstack,
+ (GDestroyNotify)g_free);
+}
+
+void
+g_object_remove_toggle_ref (GObject *object,
+ GToggleNotify notify,
+ gpointer data)
+{
+ ToggleRefStack *tstack;
+ gboolean found_one = FALSE;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (notify != NULL);
+
+ tstack = g_datalist_id_get_data (&object->qdata, quark_toggle_refs);
+ if (tstack)
+ {
+ guint i;
+
+ for (i = 0; i < tstack->n_toggle_refs; i++)
+ if (tstack->toggle_refs[i].notify == notify &&
+ tstack->toggle_refs[i].data == data)
+ {
+ found_one = TRUE;
+ tstack->n_toggle_refs -= 1;
+ if (i != tstack->n_toggle_refs)
+ tstack->toggle_refs[i] = tstack->toggle_refs[tstack->n_toggle_refs];
+
+ if (tstack->n_toggle_refs == 0)
+ G_DATALIST_UNSET_FLAGS (&object->qdata, OBJECT_HAS_TOGGLE_REF_FLAG);
+
+ g_object_unref (object);
+
+ break;
+ }
+ }
+
+ if (!found_one)
+ g_warning ("%s: couldn't find toggle ref %p(%p)", G_STRFUNC, notify, data);
+}
+
gpointer
g_object_ref (gpointer _object)
{
#endif /* G_ENABLE_DEBUG */
object->ref_count += 1;
+ if (object->ref_count == 2 && OBJECT_HAS_TOGGLE_REF (object))
+ toggle_refs_notify (object, FALSE);
return object;
}
#endif /* G_ENABLE_DEBUG */
if (object->ref_count > 1)
- object->ref_count -= 1;
+ {
+ object->ref_count -= 1;
+ if (object->ref_count == 1 && OBJECT_HAS_TOGGLE_REF (object))
+ toggle_refs_notify (object, TRUE);
+ }
else
g_object_last_unref (object);
}
gpointer *weak_pointer_location);
void g_object_remove_weak_pointer (GObject *object,
gpointer *weak_pointer_location);
+
+typedef void (*GToggleNotify) (gpointer data,
+ GObject *object,
+ gboolean is_last_ref);
+
+void g_object_add_toggle_ref (GObject *object,
+ GToggleNotify notify,
+ gpointer data);
+void g_object_remove_toggle_ref (GObject *object,
+ GToggleNotify notify,
+ gpointer data);
+
gpointer g_object_get_qdata (GObject *object,
GQuark quark);
void g_object_set_qdata (GObject *object,
g_object_watch_closure
g_object_weak_ref
g_object_weak_unref
+g_object_add_toggle_ref
+g_object_remove_toggle_ref
g_value_get_object
g_value_set_object
g_value_dup_object
ifaceinit \
ifaceinherit \
ifaceproperties \
- override
+ override \
+ references
check_PROGRAMS = $(test_programs)
--- /dev/null
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * 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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#undef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "TestReferences"
+
+#undef G_DISABLE_ASSERT
+#undef G_DISABLE_CHECKS
+#undef G_DISABLE_CAST_CHECKS
+
+#include <glib-object.h>
+
+/* This test tests weak and toggle references
+ */
+
+static GObject *global_object;
+
+static gboolean object_destroyed;
+static gboolean weak_ref1_notified;
+static gboolean weak_ref2_notified;
+static gboolean toggle_ref1_weakened;
+static gboolean toggle_ref1_strengthened;
+static gboolean toggle_ref2_weakened;
+static gboolean toggle_ref2_strengthened;
+static gboolean toggle_ref3_weakened;
+static gboolean toggle_ref3_strengthened;
+
+/*
+ * TestObject, a parent class for TestObject
+ */
+#define TEST_TYPE_OBJECT (test_object_get_type ())
+typedef struct _TestObject TestObject;
+typedef struct _TestObjectClass TestObjectClass;
+
+struct _TestObject
+{
+ GObject parent_instance;
+};
+struct _TestObjectClass
+{
+ GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT);
+
+static void
+test_object_finalize (GObject *object)
+{
+ object_destroyed = TRUE;
+
+ G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
+}
+
+static void
+test_object_class_init (TestObjectClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = test_object_finalize;
+}
+
+static void
+test_object_init (TestObject *test_object)
+{
+}
+
+static void
+clear_flags (void)
+{
+ object_destroyed = FALSE;
+ weak_ref1_notified = FALSE;
+ weak_ref2_notified = FALSE;
+ toggle_ref1_weakened = FALSE;
+ toggle_ref1_strengthened = FALSE;
+ toggle_ref2_weakened = FALSE;
+ toggle_ref2_strengthened = FALSE;
+ toggle_ref3_weakened = FALSE;
+ toggle_ref3_strengthened = FALSE;
+}
+
+static void
+weak_ref1 (gpointer data,
+ GObject *object)
+{
+ g_assert (object == global_object);
+ g_assert (data == GUINT_TO_POINTER (42));
+
+ weak_ref1_notified = TRUE;
+}
+
+static void
+weak_ref2 (gpointer data,
+ GObject *object)
+{
+ g_assert (object == global_object);
+ g_assert (data == GUINT_TO_POINTER (24));
+
+ weak_ref2_notified = TRUE;
+}
+
+static void
+toggle_ref1 (gpointer data,
+ GObject *object,
+ gboolean is_last_ref)
+{
+ g_assert (object == global_object);
+ g_assert (data == GUINT_TO_POINTER (42));
+
+ if (is_last_ref)
+ toggle_ref1_weakened = TRUE;
+ else
+ toggle_ref1_strengthened = TRUE;
+}
+
+static void
+toggle_ref2 (gpointer data,
+ GObject *object,
+ gboolean is_last_ref)
+{
+ g_assert (object == global_object);
+ g_assert (data == GUINT_TO_POINTER (24));
+
+ if (is_last_ref)
+ toggle_ref2_weakened = TRUE;
+ else
+ toggle_ref2_strengthened = TRUE;
+}
+
+static void
+toggle_ref3 (gpointer data,
+ GObject *object,
+ gboolean is_last_ref)
+{
+ g_assert (object == global_object);
+ g_assert (data == GUINT_TO_POINTER (34));
+
+ if (is_last_ref)
+ {
+ toggle_ref3_weakened = TRUE;
+ g_object_remove_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
+ }
+ else
+ toggle_ref3_strengthened = TRUE;
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ GObject *object;
+
+ g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
+ G_LOG_LEVEL_WARNING |
+ G_LOG_LEVEL_CRITICAL);
+ g_type_init ();
+
+ /* Test basic weak reference operation
+ */
+ global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
+
+ g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
+
+ clear_flags ();
+ g_object_unref (object);
+ g_assert (weak_ref1_notified == TRUE);
+ g_assert (object_destroyed == TRUE);
+
+ /* Test two weak references at once
+ */
+ global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
+
+ g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
+ g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
+
+ clear_flags ();
+ g_object_unref (object);
+ g_assert (weak_ref1_notified == TRUE);
+ g_assert (weak_ref2_notified == TRUE);
+ g_assert (object_destroyed == TRUE);
+
+ /* Test remove weak references
+ */
+ global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
+
+ g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
+ g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
+ g_object_weak_unref (object, weak_ref1, GUINT_TO_POINTER (42));
+
+ clear_flags ();
+ g_object_unref (object);
+ g_assert (weak_ref1_notified == FALSE);
+ g_assert (weak_ref2_notified == TRUE);
+ g_assert (object_destroyed == TRUE);
+
+ /* Test basic toggle reference operation
+ */
+ global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
+
+ g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
+
+ clear_flags ();
+ g_object_unref (object);
+ g_assert (toggle_ref1_weakened == TRUE);
+ g_assert (toggle_ref1_strengthened == FALSE);
+ g_assert (object_destroyed == FALSE);
+
+ clear_flags ();
+ g_object_ref (object);
+ g_assert (toggle_ref1_weakened == FALSE);
+ g_assert (toggle_ref1_strengthened == TRUE);
+ g_assert (object_destroyed == FALSE);
+
+ g_object_unref (object);
+
+ clear_flags ();
+ g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
+ g_assert (toggle_ref1_weakened == FALSE);
+ g_assert (toggle_ref1_strengthened == FALSE);
+ g_assert (object_destroyed == TRUE);
+
+ global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
+
+ /* Test two toggle references at once
+ */
+ g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
+ g_object_add_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
+
+ clear_flags ();
+ g_object_unref (object);
+ g_assert (toggle_ref1_weakened == FALSE);
+ g_assert (toggle_ref1_strengthened == FALSE);
+ g_assert (toggle_ref2_weakened == FALSE);
+ g_assert (toggle_ref2_strengthened == FALSE);
+ g_assert (object_destroyed == FALSE);
+
+ clear_flags ();
+ g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
+ g_assert (toggle_ref1_weakened == FALSE);
+ g_assert (toggle_ref1_strengthened == FALSE);
+ g_assert (toggle_ref2_weakened == TRUE);
+ g_assert (toggle_ref2_strengthened == FALSE);
+ g_assert (object_destroyed == FALSE);
+
+ clear_flags ();
+ g_object_remove_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
+ g_assert (toggle_ref1_weakened == FALSE);
+ g_assert (toggle_ref1_strengthened == FALSE);
+ g_assert (toggle_ref2_weakened == FALSE);
+ g_assert (toggle_ref2_strengthened == FALSE);
+ g_assert (object_destroyed == TRUE);
+
+ /* Test a toggle reference that removes itself
+ */
+ global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
+
+ g_object_add_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
+
+ clear_flags ();
+ g_object_unref (object);
+ g_assert (toggle_ref3_weakened == TRUE);
+ g_assert (toggle_ref3_strengthened == FALSE);
+ g_assert (object_destroyed == TRUE);
+
+ return 0;
+}