This was inconsistently handled before and only explicit unbinding or
finalizing the binding would've previously released the transform
function. If the source/target were finalized while more strong
references to the binding still existed then the transform function
would stay alive and only the binding itself would be deactivated.
Unbinding can happen from one thread while a property notification is
being handled concurrently in another one.
To solve this, introduce a reference counter for the transform function
that ensures that it always stays valid while in use and protect access
to the one stored inside the binding with the unbind mutex.
It's possible for g_binding_unbind() to be called at the same time as
one (or both) of source and target are being finalized. The resulting
unbinding needs to be protected with a mutex to ensure that it only
happens exactly once.
As the first reference is owned by both weak notifies and the caller of
g_object_bind_property(), additional indirections are needed to ensure that
unreffing the first reference after creation still unbinds the binding
as before. This seems to be a common code pattern and how this was
intended to be used, but is only safe in single-threaded contexts as it
relies on both the source and target object to be still alive.
Add a lot of comments to the code about all these dependencies and a
couple of assertions to ensure they hold valid.
Also document that inconsistent reference ownership handling of
g_binding_unbind() that makes it unfit for automatically generated
language bindings.
Half of the references to `init_state` in `gtype.c` already correctly
accessed it atomically, but a couple didn’t. Drop the `volatile`
qualifier from its declaration, as that’s not necessary for atomic
access.
Note that this is the `init_state` in `TypeData`, *not* the `init_state`
in `IFaceEntry`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #600
These variables were already (correctly) accessed atomically. The
`volatile` qualifier doesn’t help with that.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #600
This is an API break, but no third party code should be touching
`GObject.ref_count`, let alone in a way which would be changed by the
removal of the `volatile` qualifier.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #600
This is an API break, but it should not affect third party code since
that code should not be interacting with the `data` member in a way that
invokes its `volatile` qualifier (such as copying to an intermediate
variable).
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #600
These variables were already (correctly) accessed atomically. The
`volatile` qualifier doesn’t help with that.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #600
http://isvolatileusefulwiththreads.in/c/
It’s possible that the variables here are only marked as volatile
because they’re arguments to `g_once_*()`. Those arguments will be
modified in a subsequent commit.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #600
The previous code consumed a larger additional amount of stack space.
That is because it would allocate the temporary buffer for GValues on
the stack with "g_newa (GValue, 1)" and thus the required stack
space grew with the number of arguments. Granted, this is already
a variadic C function, so the caller already placed that many elements
on the stack. For example, on the stack there are the property names
and the pointers to the arguments, which should amount to roughly
O(n_args * 16) (on 64 bit, with pointers being 8 bytes large).
That is not bad, because it means in the previous version the stack space
would grow linear with the already used stack space. However, a GValue is
an additional 24 bytes (on 64 bit), which probably more than doubles the
required stack space. Let's avoid that, by allocating the temporary list
on the heap after a certain threshold. This probably more than doubles the
number of possible arguments before the stack overflows.
Also, previously the heap allocated "params" array only grew one element
per iteration. Of course, it is likely that libc anyway reallocates
the buffers by growing the space exponentially. So realloc(ptr, 1)
probably does not O() scale worse than doubling the buffer sizes ourselves.
However, it seems clearer to keep track of the allocated sizes ourself, and
only call realloc() when we determine that we are out of space.
Especially because we need to update the value pointers on reallocation.
Note that we now require a heap allocation both for the "params" and the
"values" list. Theoretically that could be combined by using one buffer
for both. But that would make the code more complicated.
Now we pre-allocate buffers for 16 elements on the stack. That
is (16 * (16 + 24) bytes (or 640 bytes) on the stack. I think that
is still acceptable.
Two out of three callers pass the count argument from a variable
of type guint. And the third is currently an always positive gint.
We should use the correct integer type that matches the type as it
used otherwise.
This commit is the unmodified results of running
```
black $(git ls-files '*.py')
```
with black version 19.10b0. See #2046.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Add a test for a signal returning interface types, using
the generic marshaller. This will hopefully exercise newly
added code in value_from_ffi_type().
This tests the new functionality that
g_type_interface_instantiable_prerequisite
was added for.
Before the changes, this fails with
GObject-WARNING **: Unable to convert a value of type \
GObject to a value of type Foo
We do the same test with g_object_bind_property_with_closures
as well, to exercise g_cclosure_marshal_generic.
Use the new g_type_interface_instantiable_prerequisite() to check
compatibility for transform functions.
In particular, this allows interfaces (in my case GDK_TYPE_PAINTABLE) to
be transformed to/from any GObject type (in my case G_TYPE_OBJECT) using
the transform function registered to transform between any 2 objects
(g_value_object_transform_value() does a type check and uses NULL if the
types don't match).
And this in turn allows be to g_object_bind_property() a gobject-typed
generic property (GtkListItem::item) to a GtkImage::paintable.
Tests for the new functionality are included.
Use the newly added g_type_interface_instantiable_prerequisite() to
allow closure return values being interfaces by looking up the
instantiable type for the interface and using its GValue accessors.
This function returns the most specific instantiatable type
that is a prerequisite for a given interface.
This type is necessary in particular when dealing with GValues
because a GValue contains an instance of a type.
This commit includes tests for the new API.
Rather than using a mixture of ‘instantiable’ and ‘instantiatable’
everywhere, standardise on the term which is already in the public API.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
g_has_typeof macro is wrongly in the public g_ namespace, internaly
symbols are usually in the glib_ namespace. This will also allow to
define glib_typeof differently on non-GNUC compilers (e.g. c++11
decltype).
commit 916297be799ee001b4a214cc52c3b960bb0b5deb added a hash table
to provide constant time lookups of signal handlers.
Unfortunately, that commit neglected to remove handlers from
g_signal_connect_object calls from the hash table that are
disconnected implicitly when the associated object goes away.
This commit addresses that bug by changing the closure invalidate
handler associated with the signal connection to properly remove the
handler from the hash table.
It may be defined by the environment (we document that as being allowed)
— if so, individual files should not try to redefine it, as that causes
a preprocessor warning.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Add a set of new URI parsing and generating functions, including a new
parsed-URI type GUri. Move all the code from gurifuncs.c into guri.c,
reimplementing some of those functions (and
g_string_append_uri_encoded()) in terms of the new code.
Fixes:
https://gitlab.gnome.org/GNOME/glib/issues/110
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
The G_VALUE_NOCOPY_CONTENTS for strings can only be used when collecting them
and not when copying them.
Instead only avoid copies for strings that are interned.
Fixes#2141
This was mostly machine generated with the following command:
```
codespell \
--builtin clear,rare,usage \
--skip './po/*' --skip './.git/*' --skip './NEWS*' \
--write-changes .
```
using the latest git version of `codespell` as per [these
instructions](https://github.com/codespell-project/codespell#user-content-updating).
Then I manually checked each change using `git add -p`, made a few
manual fixups and dropped a load of incorrect changes.
There are still some outdated or loaded terms used in GLib, mostly to do
with git branch terminology. They will need to be changed later as part
of a wider migration of git terminology.
If I’ve missed anything, please file an issue!
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Some editors automatically remove trailing blank lines, or
automatically add a trailing newline to avoid having a trailing
non-blank line that is not terminated by a newline. To avoid unrelated
whitespace changes when users of such editors contribute to GLib,
let's pre-emptively normalize all files.
Unlike more intrusive whitespace normalization like removing trailing
whitespace from each line, this seems unlikely to cause significant
issues with cherry-picking changes to stable branches.
Implemented by:
find . -name '*.[ch]' -print0 | \
xargs -0 perl -0777 -p -i -e 's/\n+\z//g; s/\z/\n/g'
Signed-off-by: Simon McVittie <smcv@collabora.com>
The various `g_strdup_printf()` returns values in the implementations of GValue
lcopy_func are runtime checks which could be disabled if one wants and therefore
should be handled as such with g_return_val_if_fail()
The property strings are interned already, so this potentially allows for faster
comparisons. The property strings were already not copied, as they were tagged
as static.
This adds support to be able to explicitely stored interned strings into
G_TYPE_STRING GValue.
This is useful for cases where the user:
* *knows* the string to be stored in the GValue is canonical
* Wants to know whther the string stored is canonical
This allows:
* zero-cost GValue copy (the content is guaranteed to be unique and exist
throughout the process life)
* zero-cost string equality checks (if both string GValue are interned, you just
need to check the pointers for equality or not, instead of doing a strcmp).
Fixes#2109