Add g_object_add/remove_toggle_ref() functions to get notification when a

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-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-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.
This commit is contained in:
Owen Taylor 2005-05-05 14:57:29 +00:00 committed by Owen Taylor
parent 1167d7d6a7
commit 2ae1a46b4c
83 changed files with 1026 additions and 61 deletions

View File

@ -1,3 +1,18 @@
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

View File

@ -1,3 +1,18 @@
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

View File

@ -1,3 +1,18 @@
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

View File

@ -1,3 +1,18 @@
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

View File

@ -1,3 +1,10 @@
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.

View File

@ -22,6 +22,7 @@ IGNORE_HFILES= \
build \
gobject \
config.h \
gdatasetprivate.h \
glibintl.h \
gbsearcharray.h \
gmoduleconf.h \

View File

@ -980,7 +980,7 @@ G_FILE_ERROR
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
@ -1345,6 +1345,7 @@ g_nullify_pointer
<SUBSECTION Private>
G_NATIVE_ATEXIT
g_ATEXIT
g_win32_get_system_data_dirs_for_module
ATEXIT
</SECTION>
@ -1970,6 +1971,10 @@ g_datalist_remove_no_notify
<SUBSECTION>
g_datalist_foreach
g_datalist_clear
g_datalist_set_flags
g_datalist_unset_flags
g_datalist_get_flags
G_DATALIST_FLAGS_MASK
</SECTION>

View File

@ -34,6 +34,9 @@ elements. Each must use separate allocators.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GAllocator ##### -->
<para>
The <structname>GAllocator</structname> struct contains private data. and should only be accessed

View File

@ -55,6 +55,9 @@ To free an array, use g_array_free().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GArray ##### -->
<para>
Contains the public fields of an <link linkend="glib-arrays">Array</link>.

View File

@ -60,6 +60,9 @@ To free a pointer array, use g_ptr_array_free().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GPtrArray ##### -->
<para>
Contains the public fields of a pointer array.

View File

@ -63,6 +63,9 @@ locking function variants (those without the suffix _unlocked)
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GAsyncQueue ##### -->
<para>
The #GAsyncQueue struct is an opaque data structure, which represents

View File

@ -60,6 +60,9 @@ g_atomic_pointer_compare_and_exchange() respectively.
</variablelist>
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### FUNCTION g_atomic_int_get ##### -->
<para>
Reads the value of the integer pointed to by @atomic. Also acts as

View File

@ -44,6 +44,9 @@ as the standard byte order (which is in fact the big-endian byte order).
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO G_BYTE_ORDER ##### -->
<para>
The host byte order.

View File

@ -26,6 +26,9 @@ A #GCache value is the actual resource.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GCache ##### -->
<para>
The #GCache struct is an opaque data structure containing information about

View File

@ -161,6 +161,9 @@ export G_FILENAME_ENCODING=ISO-8859-1
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### FUNCTION g_convert ##### -->
<para>

View File

@ -47,6 +47,9 @@ To remove all data elements from a datalist, use g_datalist_clear().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GData ##### -->
<para>
The #GData struct is an opaque data structure to represent a
@ -202,3 +205,37 @@ The data elements' destroy functions are called if they have been set.
@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>

View File

@ -49,6 +49,9 @@ To destroy a dataset, use g_dataset_destroy().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO g_dataset_id_set_data ##### -->
<para>
Sets the data element associated with the given #GQuark id.

View File

@ -63,6 +63,9 @@ can request the current time as a #GTimeVal with g_get_current_time().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO G_USEC_PER_SEC ##### -->
<para>
Number of microseconds in one second (1 million). This macro is provided for

View File

@ -370,6 +370,9 @@ Summary of rules for use of #GError:
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GError ##### -->
<para>
The <structname>GError</structname> structure contains

View File

@ -38,6 +38,9 @@ g_dir_read_name(), g_dir_rewind(), g_dir_close().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### ENUM GFileError ##### -->
<para>
Values corresponding to <literal>errno</literal> codes returned from file operations
@ -165,6 +168,18 @@ A test to perform on a file using g_file_test().
@Returns:
<!-- ##### FUNCTION g_file_set_contents ##### -->
<para>
</para>
@filename:
@contents:
@length:
@error:
@Returns:
<!-- ##### FUNCTION g_file_test ##### -->
<para>
@ -346,3 +361,33 @@ An opaque structure representing an opened directory.
@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:

View File

@ -44,6 +44,10 @@ serializes and deserializes a desktop entry.
Desktop Entry Parser
<!-- ##### SECTION ./tmpl/glib-unused.sgml:Stability_Level ##### -->
<!-- ##### ENUM GChannelError ##### -->
<para>
@ -629,6 +633,17 @@ in any UNIX manual.
@error:
@Returns:
<!-- ##### FUNCTION g_file_replace ##### -->
<para>
</para>
@filename:
@contents:
@length:
@error:
@Returns:
<!-- ##### FUNCTION g_io_channel_error_quark ##### -->
<para>

View File

@ -331,14 +331,14 @@ This function is deprecated and will be removed in the next major
@v1:
@v2:
@Returns:
@Returns:
<!-- ##### FUNCTION g_str_hash ##### -->
<para>
</para>
@v:
@Returns:
@v:
@Returns:

View File

@ -17,6 +17,9 @@ and the list of hook functions can be invoked.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GHookList ##### -->
<para>
The <structname>GHookList</structname> struct represents a

View File

@ -27,6 +27,9 @@ the GETTEXT_PACKAGE macro suitably for your library:
The gettext manual.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO _ ##### -->
<para>
Marks a string for translation, gets replaced with the translated string

View File

@ -64,6 +64,9 @@ Convenience functions for creating #GIOChannel instances and adding them to the
</variablelist>
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GIOChannel ##### -->
<para>
A data structure representing an IO Channel. The fields should be considered

View File

@ -97,6 +97,9 @@ Key and Group names are case-sensitive, for example a group called
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GKeyFile ##### -->
<para>
The <structname>GKeyFile</structname> struct contains only private fields

View File

@ -15,6 +15,9 @@ the standard integer and floating point types.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO G_MININT ##### -->
<para>
The minimum value which can be held in a #gint.

View File

@ -64,6 +64,9 @@ To free the entire list, use g_list_free().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GList ##### -->
<para>
The #GList struct is used for each element in a doubly-linked list.

View File

@ -64,6 +64,9 @@ To free the entire list, use g_slist_free().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GSList ##### -->
<para>
The #GSList struct is used for each element in the singly-linked list.
@ -74,7 +77,6 @@ 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.

View File

@ -14,6 +14,9 @@ These macros provide a few commonly-used features.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO G_OS_WIN32 ##### -->
<para>
This macro is defined only on Windows. So you can bracket

View File

@ -15,6 +15,9 @@ by application programmers.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO G_INLINE_FUNC ##### -->
<para>
Used to declare inline functions. If inline functions are not supported on
@ -238,6 +241,8 @@ See the GNU C documentation for details.
Since: 2.8
<!-- ##### MACRO G_GNUC_FUNCTION ##### -->
<para>
Expands to the GNU C <literal>__FUNCTION__</literal> variable if the

View File

@ -101,6 +101,9 @@ manages all available sources of events.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GMainLoop ##### -->
<para>
The <structname>GMainLoop</structname> struct is an opaque data type

View File

@ -85,6 +85,9 @@ Sections marked as CDATA
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### ENUM GMarkupError ##### -->
<para>
Error codes returned by markup parsing.

View File

@ -20,6 +20,9 @@ This also means that there is no need to check if the call succeeded.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO g_new ##### -->
<para>
Allocates @n_structs elements of type @struct_type.
@ -228,18 +231,12 @@ Wraps g_alloca() in a more typesafe manner.
<!-- ##### 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 ##### -->

View File

@ -122,6 +122,9 @@ To help debug memory chunks, use g_mem_chunk_info() and g_mem_chunk_print().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GMemChunk ##### -->
<para>
The #GMemChunk struct is an opaque data structure representing a memory

View File

@ -20,6 +20,9 @@ These can be extended with user-defined levels.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO G_LOG_DOMAIN ##### -->
<para>
Defines the log domain.

View File

@ -14,6 +14,9 @@ These are portable utility functions.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### FUNCTION g_get_application_name ##### -->
<para>
@ -74,12 +77,20 @@ These are portable utility functions.
@variable:
<!-- ##### FUNCTION g_listenv ##### -->
<para>
</para>
@Returns:
<!-- ##### FUNCTION g_get_user_name ##### -->
<para>
</para>
@Returns:
@Returns:
<!-- ##### FUNCTION g_get_real_name ##### -->
@ -87,7 +98,7 @@ These are portable utility functions.
</para>
@Returns:
@Returns:
<!-- ##### FUNCTION g_get_user_cache_dir ##### -->
@ -151,7 +162,7 @@ These are portable utility functions.
</para>
@Returns:
@Returns:
<!-- ##### FUNCTION g_basename ##### -->
@ -181,8 +192,8 @@ The returned string should be freed when no longer needed.
</para>
@file_name:
@Returns:
@file_name:
@Returns:
<!-- ##### FUNCTION g_path_skip_root ##### -->
@ -309,8 +320,8 @@ larger than @num.
@string:
@keys:
@nkeys:
@Returns:
@nkeys:
@Returns:
<!-- ##### STRUCT GDebugKey ##### -->

View File

@ -88,6 +88,9 @@ just_say_hello (const char *filename, GError **error)
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GModule ##### -->
<para>
The #GModule struct is an opaque data structure to represent a

View File

@ -24,6 +24,9 @@ The #GFloatIEEE754 and #GDoubleIEEE754 unions are used to access the
<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>

View File

@ -124,6 +124,9 @@ main (int argc, char *argv[])
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### ENUM GOptionError ##### -->
<para>
Error codes returned by option parsing.

View File

@ -30,6 +30,9 @@ pattern compilation.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GPatternSpec ##### -->
<para>
A <structname>GPatternSpec</structname> is the 'compiled' form of a pattern.

View File

@ -31,6 +31,9 @@ To find the #GQuark corresponding to a given string, use g_quark_try_string().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### TYPEDEF GQuark ##### -->
<para>
A GQuark is an integer which uniquely identifies a particular string.

View File

@ -35,6 +35,9 @@ To free the entire queue, use g_queue_free().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GQueue ##### -->
<para>
Contains the public fields of a <link linkend="glib-queues">Queue</link>.

View File

@ -55,6 +55,9 @@ with Glib-2.0 that you need to reproduce exactly.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GRand ##### -->
<para>
The #GRand struct is an opaque data structure. It should only be

View File

@ -56,6 +56,9 @@ To help debug #GRelation objects, use g_relation_print().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GRelation ##### -->
<para>
The #GRelation struct is an opaque data structure to represent a

View File

@ -19,6 +19,9 @@ understand it myself. Look at gtkrc.c for some code using the scanner.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GScanner ##### -->
<para>
The data structure representing a lexical scanner.

View File

@ -14,6 +14,9 @@ shell-like commandline handling.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### ENUM GShellError ##### -->
<para>
Error codes returned by shell functions.

View File

@ -14,6 +14,9 @@ process launching with <function>fork()</function>/<function>exec()</function>.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### ENUM GSpawnError ##### -->
<para>
Error codes returned by spawning processes.

View File

@ -40,6 +40,9 @@ It is not possible to free individual strings.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GStringChunk ##### -->
<para>
An opaque data structure representing String Chunks.

View File

@ -37,6 +37,9 @@ wide characters (see g_unichar_iswide()) into account.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### FUNCTION g_strdup ##### -->
<para>
Duplicates a string.

View File

@ -76,7 +76,7 @@ you do not have to worry about having enough space to copy the 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.

View File

@ -59,6 +59,9 @@ can be stopped by calling g_thread_pool_stop_unused_threads().
</variablelist>
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GThreadPool ##### -->
<para>
The #GThreadPool struct represents a thread pool. It has six public

View File

@ -49,6 +49,9 @@ primitives to portably create and manage threads (#GThread).
</variablelist>
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO G_THREADS_ENABLED ##### -->
<para>

View File

@ -17,6 +17,9 @@ get exactly right, so #GTimer provides a portable/convenient interface.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GTimer ##### -->
<para>
Opaque datatype that records a start time.

View File

@ -21,6 +21,9 @@ is a perfectly valid empty stack.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GTrashStack ##### -->
<para>
Each piece of memory that is pushed onto the stack

View File

@ -40,6 +40,9 @@ To destroy a #GTree, use g_tree_destroy().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GTree ##### -->
<para>
The <structname>GTree</structname> struct is an opaque data structure representing a

View File

@ -49,6 +49,9 @@ g_node_destroy().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GNode ##### -->
<para>
The <structname>GNode</structname> struct represents one node in a

View File

@ -55,6 +55,9 @@ integer; values outside the range of a 32-bit integer will be mangled.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO GINT_TO_POINTER ##### -->
<para>
Stuffs an integer into a pointer type.

View File

@ -37,6 +37,9 @@ for completeness - #gchar, #gint, #gshort, #glong, #gfloat, #gdouble.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### TYPEDEF gboolean ##### -->
<para>
A standard <type>boolean</type> type.

View File

@ -29,6 +29,9 @@ Convenience functions for converting between UTF-8 and the locale encoding.
</variablelist>
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### TYPEDEF gunichar ##### -->
<para>
A type which can hold any UCS-4 character code.

View File

@ -16,6 +16,9 @@ typically use the features described here.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### VARIABLE glib_major_version ##### -->
<para>
The major version number of the GLib library.

View File

@ -14,6 +14,9 @@ These functions provide support for outputting messages.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### FUNCTION g_print ##### -->
<para>
Outputs a formatted message via the print handler.

View File

@ -242,6 +242,9 @@ g_object_weak_ref
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

View File

@ -14,6 +14,9 @@ A mechanism to wrap opaque C structures registered by the type system
#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

View File

@ -60,6 +60,9 @@ automatically removed when the objects they point to go away.
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### MACRO G_CLOSURE_NEEDS_MARSHAL ##### -->
<para>
Returns %TRUE if a #GClosureMarshal marshaller has not yet been set on

View File

@ -21,6 +21,9 @@ g_object_class_install_property(), g_object_set(), g_object_get(),
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.

View File

@ -70,6 +70,9 @@ handles multiple registered types per module.
#GTypeModule and g_type_register_dynamic().
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GTypePlugin ##### -->
<para>
The <structname>GTypePlugin</structname> typedef is used as a placeholder

View File

@ -14,6 +14,9 @@ The base object type
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### STRUCT GObject ##### -->
<para>
All the fields in the <structname>GObject</structname> structure are private
@ -432,6 +435,76 @@ to match the one used with g_object_add_weak_pointer().
@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.

View File

@ -833,7 +833,6 @@ A #GParamSpec derived structure that contains the meta data for double propertie
@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>

View File

@ -14,6 +14,9 @@ Converting varargs to generic values
</para>
<!-- ##### SECTION Stability_Level ##### -->
<!-- ##### UNION GTypeCValue ##### -->
<para>
A union holding one collected value.

View File

@ -70,6 +70,7 @@ libglib_2_0_la_SOURCES = \
gcompletion.c \
gconvert.c \
gdataset.c \
gdatasetprivate.h \
gdate.c \
gdir.c \
gerror.c \

View File

@ -37,6 +37,7 @@
#include "glib.h"
#include "galias.h"
#include "gdatasetprivate.h"
/* --- defines --- */
@ -91,7 +92,6 @@ static GHashTable *g_quark_ht = NULL;
static gchar **g_quarks = NULL;
static GQuark g_quark_seq_id = 0;
/* --- functions --- */
/* HOLDS: g_dataset_global_lock */
@ -102,8 +102,8 @@ g_datalist_clear_i (GData **datalist)
/* 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)
{
@ -139,7 +139,7 @@ g_datalist_clear (GData **datalist)
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);
}
@ -210,7 +210,7 @@ g_data_set_internal (GData **datalist,
{
register GData *list;
list = *datalist;
list = G_DATALIST_GET_POINTER (datalist);
if (!data)
{
register GData *prev;
@ -226,12 +226,12 @@ g_data_set_internal (GData **datalist,
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);
}
@ -309,11 +309,11 @@ g_data_set_internal (GData **datalist,
}
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;
@ -459,7 +459,7 @@ g_datalist_id_get_data (GData **datalist,
{
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;
}
@ -509,7 +509,7 @@ g_datalist_foreach (GData **datalist,
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);
@ -524,6 +524,70 @@ g_datalist_init (GData **datalist)
*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)

View File

@ -39,19 +39,35 @@ typedef void (*GDataForeachFunc) (GQuark key_id,
/* 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) \

53
glib/gdatasetprivate.h Normal file
View File

@ -0,0 +1,53 @@
/* 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__ */

View File

@ -1068,7 +1068,7 @@ write_to_temp_file (const gchar *contents,
}
/**
* 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
@ -1108,10 +1108,10 @@ write_to_temp_file (const gchar *contents,
* 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;

View File

@ -86,7 +86,7 @@ gboolean g_file_get_contents (const gchar *filename,
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);

View File

@ -152,9 +152,12 @@ g_uri_list_extract_uris G_GNUC_MALLOC
#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
@ -252,7 +255,7 @@ g_build_path G_GNUC_NULL_TERMINATED
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

View File

@ -1,3 +1,11 @@
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:

View File

@ -18,6 +18,7 @@
*/
#include "gobject.h"
#include "gobjectalias.h"
#include <glib/gdatasetprivate.h>
/*
* MT safe
@ -39,6 +40,10 @@
#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 {
@ -105,6 +110,7 @@ static void object_interface_check_properties (gpointer func_da
/* --- 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, };
@ -241,6 +247,7 @@ g_object_do_class_init (GObjectClass *class)
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;
@ -1519,10 +1526,8 @@ g_object_weak_unref (GObject *object,
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;
}
}
@ -1554,6 +1559,106 @@ g_object_remove_weak_pointer (GObject *object,
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)
{
@ -1568,6 +1673,8 @@ 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;
}
@ -1586,7 +1693,11 @@ g_object_unref (gpointer _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);
}

View File

@ -178,6 +178,18 @@ void g_object_add_weak_pointer (GObject *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,

View File

@ -148,6 +148,8 @@ g_object_unref
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

View File

@ -52,7 +52,8 @@ test_programs = \
ifaceinit \
ifaceinherit \
ifaceproperties \
override
override \
references
check_PROGRAMS = $(test_programs)

281
tests/gobject/references.c Normal file
View File

@ -0,0 +1,281 @@
/* 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;
}