mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36:17 +01:00
Merge branch 'wip/chergert/reduce-copies-for-gvarianttype-cache' into 'main'
gvarianttypeinfo: reduce caching overhead See merge request GNOME/glib!4293
This commit is contained in:
commit
80e8bc7c0b
99
glib/gvarianttype-private.h
Normal file
99
glib/gvarianttype-private.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/* gvarianttype-private.h
|
||||||
|
*
|
||||||
|
* Copyright © 2007, 2008 Ryan Lortie
|
||||||
|
* Copyright © 2009, 2010 Codethink Limited
|
||||||
|
* Copyright © 2024 Christian Hergert
|
||||||
|
*
|
||||||
|
* 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.1 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 General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gvarianttype.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
_g_variant_type_equal (const GVariantType *type1,
|
||||||
|
const GVariantType *type2)
|
||||||
|
{
|
||||||
|
const char *str1 = (const char *)type1;
|
||||||
|
const char *str2 = (const char *)type2;
|
||||||
|
gsize index = 0;
|
||||||
|
int brackets = 0;
|
||||||
|
|
||||||
|
if (str1 == str2)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (str1[index] != str2[index])
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (str1[index] == 'a' || str1[index] == 'm')
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (str1[index] != str2[index])
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str1[index] == '(' || str1[index] == '{')
|
||||||
|
brackets++;
|
||||||
|
|
||||||
|
else if (str1[index] == ')' || str1[index] == '}')
|
||||||
|
brackets--;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
while (brackets);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline guint
|
||||||
|
_g_variant_type_hash (gconstpointer type)
|
||||||
|
{
|
||||||
|
const gchar *type_string = type;
|
||||||
|
guint value = 0;
|
||||||
|
gsize index = 0;
|
||||||
|
int brackets = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
value = (value << 5) - value + type_string[index];
|
||||||
|
|
||||||
|
while (type_string[index] == 'a' || type_string[index] == 'm')
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
|
||||||
|
value = (value << 5) - value + type_string[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_string[index] == '(' || type_string[index] == '{')
|
||||||
|
brackets++;
|
||||||
|
|
||||||
|
else if (type_string[index] == ')' || type_string[index] == '}')
|
||||||
|
brackets--;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
while (brackets);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_END_DECLS
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "gvarianttype.h"
|
#include "gvarianttype-private.h"
|
||||||
|
|
||||||
#include <glib/gtestutils.h>
|
#include <glib/gtestutils.h>
|
||||||
#include <glib/gstrfuncs.h>
|
#include <glib/gstrfuncs.h>
|
||||||
@ -777,20 +777,9 @@ g_variant_type_is_variant (const GVariantType *type)
|
|||||||
guint
|
guint
|
||||||
g_variant_type_hash (gconstpointer type)
|
g_variant_type_hash (gconstpointer type)
|
||||||
{
|
{
|
||||||
const gchar *type_string;
|
|
||||||
guint value = 0;
|
|
||||||
gsize length;
|
|
||||||
gsize i;
|
|
||||||
|
|
||||||
g_return_val_if_fail (g_variant_type_check (type), 0);
|
g_return_val_if_fail (g_variant_type_check (type), 0);
|
||||||
|
|
||||||
type_string = g_variant_type_peek_string (type);
|
return _g_variant_type_hash (type);
|
||||||
length = g_variant_type_get_string_length (type);
|
|
||||||
|
|
||||||
for (i = 0; i < length; i++)
|
|
||||||
value = (value << 5) - value + type_string[i];
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -817,25 +806,10 @@ gboolean
|
|||||||
g_variant_type_equal (gconstpointer type1,
|
g_variant_type_equal (gconstpointer type1,
|
||||||
gconstpointer type2)
|
gconstpointer type2)
|
||||||
{
|
{
|
||||||
const gchar *string1, *string2;
|
|
||||||
gsize size1, size2;
|
|
||||||
|
|
||||||
g_return_val_if_fail (g_variant_type_check (type1), FALSE);
|
g_return_val_if_fail (g_variant_type_check (type1), FALSE);
|
||||||
g_return_val_if_fail (g_variant_type_check (type2), FALSE);
|
g_return_val_if_fail (g_variant_type_check (type2), FALSE);
|
||||||
|
|
||||||
if (type1 == type2)
|
return _g_variant_type_equal (type1, type2);
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
size1 = g_variant_type_get_string_length (type1);
|
|
||||||
size2 = g_variant_type_get_string_length (type2);
|
|
||||||
|
|
||||||
if (size1 != size2)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
string1 = g_variant_type_peek_string (type1);
|
|
||||||
string2 = g_variant_type_peek_string (type2);
|
|
||||||
|
|
||||||
return memcmp (string1, string2, size1) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gvarianttype-private.h"
|
||||||
#include "gvarianttypeinfo.h"
|
#include "gvarianttypeinfo.h"
|
||||||
|
|
||||||
#include <glib/gtestutils.h>
|
#include <glib/gtestutils.h>
|
||||||
@ -756,9 +757,8 @@ static GHashTable *g_variant_type_info_table;
|
|||||||
GVariantTypeInfo *
|
GVariantTypeInfo *
|
||||||
g_variant_type_info_get (const GVariantType *type)
|
g_variant_type_info_get (const GVariantType *type)
|
||||||
{
|
{
|
||||||
char type_char;
|
const gchar *type_string = g_variant_type_peek_string (type);
|
||||||
|
const char type_char = type_string[0];
|
||||||
type_char = g_variant_type_peek_string (type)[0];
|
|
||||||
|
|
||||||
if (type_char == G_VARIANT_TYPE_INFO_CHAR_MAYBE ||
|
if (type_char == G_VARIANT_TYPE_INFO_CHAR_MAYBE ||
|
||||||
type_char == G_VARIANT_TYPE_INFO_CHAR_ARRAY ||
|
type_char == G_VARIANT_TYPE_INFO_CHAR_ARRAY ||
|
||||||
@ -766,15 +766,12 @@ g_variant_type_info_get (const GVariantType *type)
|
|||||||
type_char == G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY)
|
type_char == G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY)
|
||||||
{
|
{
|
||||||
GVariantTypeInfo *info;
|
GVariantTypeInfo *info;
|
||||||
gchar *type_string;
|
|
||||||
|
|
||||||
type_string = g_variant_type_dup_string (type);
|
|
||||||
|
|
||||||
g_rec_mutex_lock (&g_variant_type_info_lock);
|
g_rec_mutex_lock (&g_variant_type_info_lock);
|
||||||
|
|
||||||
if (g_variant_type_info_table == NULL)
|
if (g_variant_type_info_table == NULL)
|
||||||
g_variant_type_info_table = g_hash_table_new (g_str_hash,
|
g_variant_type_info_table = g_hash_table_new ((GHashFunc)_g_variant_type_hash,
|
||||||
g_str_equal);
|
(GEqualFunc)_g_variant_type_equal);
|
||||||
info = g_hash_table_lookup (g_variant_type_info_table, type_string);
|
info = g_hash_table_lookup (g_variant_type_info_table, type_string);
|
||||||
|
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
@ -792,20 +789,19 @@ g_variant_type_info_get (const GVariantType *type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
info = (GVariantTypeInfo *) container;
|
info = (GVariantTypeInfo *) container;
|
||||||
container->type_string = type_string;
|
container->type_string = g_variant_type_dup_string (type);
|
||||||
g_atomic_ref_count_init (&container->ref_count);
|
g_atomic_ref_count_init (&container->ref_count);
|
||||||
|
|
||||||
TRACE(GLIB_VARIANT_TYPE_INFO_NEW(info, container->type_string));
|
TRACE(GLIB_VARIANT_TYPE_INFO_NEW(info, container->type_string));
|
||||||
|
|
||||||
g_hash_table_insert (g_variant_type_info_table, type_string, info);
|
g_hash_table_replace (g_variant_type_info_table,
|
||||||
type_string = NULL;
|
container->type_string, info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
g_variant_type_info_ref (info);
|
g_variant_type_info_ref (info);
|
||||||
|
|
||||||
g_rec_mutex_unlock (&g_variant_type_info_lock);
|
g_rec_mutex_unlock (&g_variant_type_info_lock);
|
||||||
g_variant_type_info_check (info, 0);
|
g_variant_type_info_check (info, 0);
|
||||||
g_free (type_string);
|
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -5859,6 +5859,24 @@ test_unaligned_construction (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_g_variant_type_hash (void)
|
||||||
|
{
|
||||||
|
char mas[4] = {'m', 'a', 's', 0};
|
||||||
|
|
||||||
|
g_assert_cmpint (g_variant_type_hash (G_VARIANT_TYPE ("a(ay)")),
|
||||||
|
!=,
|
||||||
|
g_variant_type_hash (G_VARIANT_TYPE ("aay")));
|
||||||
|
|
||||||
|
g_assert_cmpint (g_variant_type_hash (G_VARIANT_TYPE ("a{sv}")),
|
||||||
|
!=,
|
||||||
|
g_variant_type_hash (G_VARIANT_TYPE ("a(sv)")));
|
||||||
|
|
||||||
|
g_assert_cmpint (g_variant_type_hash (G_VARIANT_TYPE ("mas")),
|
||||||
|
==,
|
||||||
|
g_variant_type_hash ((const GVariantType *)mas));
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -5967,5 +5985,8 @@ main (int argc, char **argv)
|
|||||||
g_test_add_func ("/gvariant/unaligned-construction",
|
g_test_add_func ("/gvariant/unaligned-construction",
|
||||||
test_unaligned_construction);
|
test_unaligned_construction);
|
||||||
|
|
||||||
|
g_test_add_func ("/gvarianttype/hash",
|
||||||
|
test_g_variant_type_hash);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user