ginitable: Relax idempotency requirements on init() and init_async()

The previously documented requirements for implementing init() and
init_async() as completely idempotent were really quite hard to achieve,
and brought a lot of pain for very little gain. Many implementations of
GInitable and GAsyncInitable did not actually follow the requirements,
or did not correctly handle concurrent init_async() calls.

Relax those requirements so that classes can decide whether their init()
or init_async() implementations need to be idempotent.

https://bugzilla.gnome.org/show_bug.cgi?id=766660
This commit is contained in:
Philip Withnall 2016-06-15 11:25:19 -04:00 committed by Philip Withnall
parent 6c95cd22e9
commit deab643651
2 changed files with 29 additions and 10 deletions

View File

@ -166,6 +166,9 @@ g_async_initable_default_init (GAsyncInitableInterface *iface)
* initial construction. If the object also implements #GInitable you can
* optionally call g_initable_init() instead.
*
* This method is intended for language bindings. If writing in C,
* g_async_initable_new_async() should typically be used instead.
*
* When the initialization is finished, @callback will be called. You can
* then call g_async_initable_init_finish() to get the result of the
* initialization.
@ -183,11 +186,11 @@ g_async_initable_default_init (GAsyncInitableInterface *iface)
* have undefined behaviour. They will often fail with g_critical() or
* g_warning(), but this must not be relied on.
*
* Implementations of this method must be idempotent: i.e. multiple calls
* to this function with the same argument should return the same results.
* Only the first call initializes the object; further calls return the result
* of the first call. This is so that it's safe to implement the singleton
* pattern in the GObject constructor function.
* Callers should not assume that a class which implements #GAsyncInitable can
* be initialized multiple times; for more information, see g_initable_init().
* If a class explicitly supports being initialized multiple times,
* implementation requires yielding all subsequent calls to init_async() on the
* results of the first call.
*
* For classes that also support the #GInitable interface, the default
* implementation of this method will run the g_initable_init() function

View File

@ -72,6 +72,9 @@ g_initable_default_init (GInitableInterface *iface)
*
* Initializes the object implementing the interface.
*
* This method is intended for language bindings. If writing in C,
* g_initable_new() should typically be used instead.
*
* The object must be initialized before any real use after initial
* construction, either with this function or g_async_initable_init_async().
*
@ -87,11 +90,24 @@ g_initable_default_init (GInitableInterface *iface)
* g_object_unref() are considered to be invalid, and have undefined
* behaviour. See the [introduction][ginitable] for more details.
*
* Implementations of this method must be idempotent, i.e. multiple calls
* to this function with the same argument should return the same results.
* Only the first call initializes the object, further calls return the result
* of the first call. This is so that it's safe to implement the singleton
* pattern in the GObject constructor function.
* Callers should not assume that a class which implements #GInitable can be
* initialized multiple times, unless the class explicitly documents itself as
* supporting this. Generally, a class implementation of init() can assume
* (and assert) that it will only be called once. Previously, this documentation
* recommended all #GInitable implementations should be idempotent; that
* recommendation was relaxed in GLib 2.54.
*
* If a class explicitly supports being initialized multiple times, it is
* recommended that the method is idempotent: multiple calls with the same
* arguments should return the same results. Only the first call initializes
* the object; further calls return the result of the first call.
*
* One reason why a class might need to support idempotent initialization is if
* it is designed to be used via the singleton pattern, with a
* #GObjectClass.constructor that sometimes returns an existing instance.
* In this pattern, a caller would expect to be able to call g_initable_init()
* on the result of g_object_new(), regardless of whether it is in fact a new
* instance.
*
* Returns: %TRUE if successful. If an error has occurred, this function will
* return %FALSE and set @error appropriately if present.