Il est souvent utile pour l'exploitation forestière dans des applications en temps réel comme les jeux pour donner un nom à chaque entité. Cela facilite le retrait des erreurs car la recherche d'entités via des noms uniques est plus facile que de regarder des nombres uniques ou d'autres formes d'identifiants. Mais les cordes sont énormes et les copier et les comparer sont lentes, donc elles ne peuvent souvent pas être utilisées dans le code critique des performances.
Une solution est des chaînes hachés qui ne sont que des entiers et donc petits, rapides à copier et à comparer. Mais les hachages ne permettent pas de récupérer la valeur de chaîne d'origine, ce qui est exactement ce qui est nécessaire à des fins de journalisation et de débogage! De plus, il y a un risque de collisions, donc le code de hachage égal ne signifie pas nécessairement des chaînes égales. Cette chance est petite, mais une source de bugs difficiles à trouver.
Une autre solution est l'interminale de chaîne. String Interning utilise une table de recherche globale où chaque chaîne n'est stockée qu'une seule fois et est référencée via un index ou quelque chose de similaire. La copie et la comparaison sont également rapides, mais elles ne sont toujours pas parfaites: vous ne pouvez y accéder qu'à l'heure d'exécution. Il n'est pas possible d'obtenir la valeur à compilation.
Donc, d'une part, nous voulons des identificateurs rapides et légers, mais d'autre part, des méthodes pour récupérer le nom.
Cette bibliothèque open source fournit un mélange entre les deux solutions sous la forme de la classe String_id . Chaque objet stocke une valeur de chaîne hachée et un pointeur vers la base de données dans laquelle la valeur de chaîne d'origine est stockée. Cela permet de récupérer la valeur de la chaîne en cas de besoin tout en obtenant les avantages de performance des chaînes hachés. De plus, la base de données peut détecter les collisions qui peuvent être gérées via un gestionnaire de collision personnalisé. Il existe un littéral défini par l'utilisateur pour créer une valeur de chaîne hachée de compilation pour l'utiliser comme une expression constante.
La base de données peut être n'importe quel type défini par l'utilisateur dérivé d'une certaine classe d'interface. Il existe plusieurs bases de données prédéfinies. Cela comprend une base de données factice qui ne stockait rien, un adaptateur pour d'autres bases de données pour les faire par threadsafe et une base de données hautement optimisée pour le stockage et la récupération efficaces des chaînes. Un typedef default_database est l'une de ces bases de données et peut être définie via les options CMake suivantes:
Foonathan_string_id_database - Si vous éteignez , la base de données est complètement désactivée, par exemple la base de données factice est utilisée. Cela ne permet pas à la récupération des chaînes ou à la vérification des collisions, mais n'a pas besoin de autant de mémoire. Il est allumé par défaut.
Foonathan_string_id_multithread - Si ON , l'accès à la base de données sera synchronisé via un mutex, par exemple, l'adaptateur de sécurité de thread sera utilisé. Il n'a aucun effet si la base de données est désactivée. La valeur par défaut est activée .
Il existe des cours de générateurs spéciaux. Ils ont une interface similaire aux générateurs de nombres aléatoires dans les bibliothèques standard, mais génèrent des identifiants de chaîne. Ceci est utilisé pour générer un tas d'identifiants de manière automatisée. Les générateurs veillent également à ce que de nouveaux identifiants soient toujours générés. Cela peut également être contrôlé via un gestionnaire similaire à la gestion des collisions.
Voir exemple / main.cpp pour un exemple.
Il utilise actuellement un hachage FNV-1A 64 bits. Les collisions sont vraiment rares, j'ai testé 219 606 mots anglais (en minuscules) mélangés à un tas de chiffres et je n'ai pas rencontré une seule collision. Comme il s'agit du cas d'utilisation normal pour les identifiants, la fonction de hachage est assez bonne. De plus, il y a une bonne distribution des valeurs hachées et il est facile à calculer.
La base de données utilise une table de hachage spécialisée. Les collisions de l'indice de seau sont résolues via un chaînage séparé avec une liste unique. Chaque nœud contient la chaîne directement sans allocation de mémoire supplémentaire. Les nœuds de la liste liés sont triés à l'aide de la valeur de hachage. Cela permet de récupérer et de vérifier efficace s'il existe déjà une chaîne avec la même valeur de hachage stockée. Cela le rend très efficace et plus rapide que le std :: non ordonné_map qui a été utilisé auparavant (au moins plus rapide que l'implémentation libstdc ++ que j'ai utilisée pour les repères).
Cette bibliothèque a été compilée sous les compilateurs suivants:
Il existe les options de compatibilité et les Marcos de remplacement pour les opérateurs de constexpr, noexcept, de remplacement et littéraux. Les fonctions de gestionnaire atomique peuvent être désactivées éventuelles et sont désactivées pour GCC 4.6 par défaut car il ne les prend pas en charge.