mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-15 04:05:11 +01:00
girepository: gi_object_info_find_signal(): Avoid repeated allocations
Previously `gi_object_info_find_signal()` used `gi_object_info_get_signal()` to retrieve the *i*th signal and compare its name to the desired name. However, `gi_object_info_get_signal()` returns an allocated object. If the names were not matching, the allocated object was simply dropped, and this resulted in a lot of unnecessary allocations compared to the desired number of allocations, which is one. To avoid much of the overhead pertaining to the creation of these allocated `GISignalInfo` objects, introduce a new function that inspects the signal blobs directly and returns an allocated `GISignalInfo` object just for the matching signal. The function is largely a copy-and-paste of `gi_base_info_find_vfunc()`, which does the same thing, only for virtual functions. See https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/504
This commit is contained in:
parent
705832f269
commit
7a528d0ff0
@ -580,6 +580,22 @@ gi_object_info_get_n_signals (GIObjectInfo *info)
|
|||||||
return blob->n_signals;
|
return blob->n_signals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
object_get_signal_offset (GIObjectInfo *info, unsigned int n)
|
||||||
|
{
|
||||||
|
GIRealInfo *rinfo = (GIRealInfo *) info;
|
||||||
|
Header *header = (Header *) rinfo->typelib->data;
|
||||||
|
ObjectBlob *blob = (ObjectBlob *) &rinfo->typelib->data[rinfo->offset];
|
||||||
|
|
||||||
|
return rinfo->offset + header->object_blob_size
|
||||||
|
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
|
||||||
|
+ blob->n_fields * header->field_blob_size
|
||||||
|
+ blob->n_field_callbacks * header->callback_blob_size
|
||||||
|
+ blob->n_properties * header->property_blob_size
|
||||||
|
+ blob->n_methods * header->function_blob_size
|
||||||
|
+ n * header->signal_blob_size;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gi_object_info_get_signal:
|
* gi_object_info_get_signal:
|
||||||
* @info: a #GIObjectInfo
|
* @info: a #GIObjectInfo
|
||||||
@ -595,28 +611,37 @@ GISignalInfo *
|
|||||||
gi_object_info_get_signal (GIObjectInfo *info,
|
gi_object_info_get_signal (GIObjectInfo *info,
|
||||||
unsigned int n)
|
unsigned int n)
|
||||||
{
|
{
|
||||||
size_t offset;
|
|
||||||
GIRealInfo *rinfo = (GIRealInfo *)info;
|
GIRealInfo *rinfo = (GIRealInfo *)info;
|
||||||
Header *header;
|
|
||||||
ObjectBlob *blob;
|
|
||||||
|
|
||||||
g_return_val_if_fail (info != NULL, NULL);
|
g_return_val_if_fail (info != NULL, NULL);
|
||||||
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
|
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
|
||||||
g_return_val_if_fail (n <= G_MAXUINT16, NULL);
|
g_return_val_if_fail (n <= G_MAXUINT16, NULL);
|
||||||
|
|
||||||
header = (Header *)rinfo->typelib->data;
|
|
||||||
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
|
|
||||||
|
|
||||||
offset = rinfo->offset + header->object_blob_size
|
|
||||||
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
|
|
||||||
+ blob->n_fields * header->field_blob_size
|
|
||||||
+ blob->n_field_callbacks * header->callback_blob_size
|
|
||||||
+ blob->n_properties * header->property_blob_size
|
|
||||||
+ blob->n_methods * header->function_blob_size
|
|
||||||
+ n * header->signal_blob_size;
|
|
||||||
|
|
||||||
return (GISignalInfo *) gi_base_info_new (GI_INFO_TYPE_SIGNAL, (GIBaseInfo*)info,
|
return (GISignalInfo *) gi_base_info_new (GI_INFO_TYPE_SIGNAL, (GIBaseInfo*)info,
|
||||||
rinfo->typelib, offset);
|
rinfo->typelib, object_get_signal_offset (info, n));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GISignalInfo *
|
||||||
|
find_signal (GIRealInfo *rinfo,
|
||||||
|
uint32_t offset,
|
||||||
|
uint16_t n_signals,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
Header *header = (Header *) rinfo->typelib->data;
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < n_signals; i++)
|
||||||
|
{
|
||||||
|
const SignalBlob *sblob = (SignalBlob *) &rinfo->typelib->data[offset];
|
||||||
|
const char *sname = gi_typelib_get_string (rinfo->typelib, sblob->name);
|
||||||
|
|
||||||
|
if (strcmp (name, sname) == 0)
|
||||||
|
return (GISignalInfo *) gi_base_info_new (GI_INFO_TYPE_SIGNAL, (GIBaseInfo *) rinfo,
|
||||||
|
rinfo->typelib, offset);
|
||||||
|
|
||||||
|
offset += header->signal_blob_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -637,22 +662,13 @@ GISignalInfo *
|
|||||||
gi_object_info_find_signal (GIObjectInfo *info,
|
gi_object_info_find_signal (GIObjectInfo *info,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
size_t n_signals;
|
GIRealInfo *rinfo = (GIRealInfo *) info;
|
||||||
|
|
||||||
n_signals = gi_object_info_get_n_signals (info);
|
g_return_val_if_fail (info != NULL, NULL);
|
||||||
for (size_t i = 0; i < n_signals; i++)
|
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
|
||||||
{
|
|
||||||
GISignalInfo *siginfo = gi_object_info_get_signal (info, i);
|
|
||||||
|
|
||||||
if (g_strcmp0 (gi_base_info_get_name ((GIBaseInfo *) siginfo), name) != 0)
|
return find_signal (rinfo, object_get_signal_offset (info, 0),
|
||||||
{
|
gi_object_info_get_n_signals (info), name);
|
||||||
gi_base_info_unref ((GIBaseInfo*)siginfo);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return siginfo;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,6 +111,9 @@ test_repository_info (RepositoryFixture *fx,
|
|||||||
object_info_by_gtype = GI_OBJECT_INFO (gi_repository_find_by_gtype (fx->repository, G_TYPE_OBJECT));
|
object_info_by_gtype = GI_OBJECT_INFO (gi_repository_find_by_gtype (fx->repository, G_TYPE_OBJECT));
|
||||||
g_assert_nonnull (object_info);
|
g_assert_nonnull (object_info);
|
||||||
|
|
||||||
|
signal_info = gi_object_info_find_signal (object_info, "does-not-exist");
|
||||||
|
g_assert_null (signal_info);
|
||||||
|
|
||||||
signal_info = gi_object_info_find_signal (object_info, "notify");
|
signal_info = gi_object_info_find_signal (object_info, "notify");
|
||||||
g_assert_nonnull (signal_info);
|
g_assert_nonnull (signal_info);
|
||||||
g_assert_true (GI_IS_SIGNAL_INFO (signal_info));
|
g_assert_true (GI_IS_SIGNAL_INFO (signal_info));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user