mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-06 09:26: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 "gvarianttype.h"
|
||||
#include "gvarianttype-private.h"
|
||||
|
||||
#include <glib/gtestutils.h>
|
||||
#include <glib/gstrfuncs.h>
|
||||
@ -777,20 +777,9 @@ g_variant_type_is_variant (const GVariantType *type)
|
||||
guint
|
||||
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);
|
||||
|
||||
type_string = g_variant_type_peek_string (type);
|
||||
length = g_variant_type_get_string_length (type);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
value = (value << 5) - value + type_string[i];
|
||||
|
||||
return value;
|
||||
return _g_variant_type_hash (type);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -817,25 +806,10 @@ gboolean
|
||||
g_variant_type_equal (gconstpointer type1,
|
||||
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 (type2), FALSE);
|
||||
|
||||
if (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;
|
||||
return _g_variant_type_equal (type1, type2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gvarianttype-private.h"
|
||||
#include "gvarianttypeinfo.h"
|
||||
|
||||
#include <glib/gtestutils.h>
|
||||
@ -756,9 +757,8 @@ static GHashTable *g_variant_type_info_table;
|
||||
GVariantTypeInfo *
|
||||
g_variant_type_info_get (const GVariantType *type)
|
||||
{
|
||||
char type_char;
|
||||
|
||||
type_char = g_variant_type_peek_string (type)[0];
|
||||
const gchar *type_string = g_variant_type_peek_string (type);
|
||||
const char type_char = type_string[0];
|
||||
|
||||
if (type_char == G_VARIANT_TYPE_INFO_CHAR_MAYBE ||
|
||||
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)
|
||||
{
|
||||
GVariantTypeInfo *info;
|
||||
gchar *type_string;
|
||||
|
||||
type_string = g_variant_type_dup_string (type);
|
||||
|
||||
g_rec_mutex_lock (&g_variant_type_info_lock);
|
||||
|
||||
if (g_variant_type_info_table == NULL)
|
||||
g_variant_type_info_table = g_hash_table_new (g_str_hash,
|
||||
g_str_equal);
|
||||
g_variant_type_info_table = g_hash_table_new ((GHashFunc)_g_variant_type_hash,
|
||||
(GEqualFunc)_g_variant_type_equal);
|
||||
info = g_hash_table_lookup (g_variant_type_info_table, type_string);
|
||||
|
||||
if (info == NULL)
|
||||
@ -792,20 +789,19 @@ g_variant_type_info_get (const GVariantType *type)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
TRACE(GLIB_VARIANT_TYPE_INFO_NEW(info, container->type_string));
|
||||
|
||||
g_hash_table_insert (g_variant_type_info_table, type_string, info);
|
||||
type_string = NULL;
|
||||
g_hash_table_replace (g_variant_type_info_table,
|
||||
container->type_string, info);
|
||||
}
|
||||
else
|
||||
g_variant_type_info_ref (info);
|
||||
|
||||
g_rec_mutex_unlock (&g_variant_type_info_lock);
|
||||
g_variant_type_info_check (info, 0);
|
||||
g_free (type_string);
|
||||
|
||||
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
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@ -5967,5 +5985,8 @@ main (int argc, char **argv)
|
||||
g_test_add_func ("/gvariant/unaligned-construction",
|
||||
test_unaligned_construction);
|
||||
|
||||
g_test_add_func ("/gvarianttype/hash",
|
||||
test_g_variant_type_hash);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user