source: trunk/src/kmk/strcache2.h@ 1909

Last change on this file since 1909 was 1909, checked in by bird, 17 years ago

strcache2: Implemented collision resolution by chaining instead of open addressing. This is faster than the open addressing approach we're using.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Id: strcache2.h 1909 2008-10-22 18:49:48Z bird $ */
2/** @file
3 * strcache - New string cache.
4 */
5
6/*
7 * Copyright (c) 2006-2008 knut st. osmundsen <bird-src-spam@anduin.net>
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27#ifndef ___strcache2_h
28#define ___strcache2_h
29
30#ifndef CHAR_BIT
31# error "include after make.h!"
32#endif
33
34#define STRCACHE2_USE_MASK 1
35#define STRCACHE2_USE_CHAINING 1
36
37/* string cache memory segment. */
38struct strcache2_seg
39{
40 struct strcache2_seg *next; /* The next cache segment. */
41 char *start; /* The first byte in the segment. */
42 size_t size; /* The size of the segment. */
43 size_t avail; /* The number of available bytes. */
44 char *cursor; /* Allocation cursor. */
45};
46
47/* string cache hash table entry. */
48struct strcache2_entry
49{
50#ifdef STRCACHE2_USE_CHAINING
51 struct strcache2_entry *next; /* Collision chain. */
52#endif
53 void *user;
54 unsigned int hash1;
55#ifndef STRCACHE2_USE_CHAINING
56 unsigned int hash2;
57#endif
58 unsigned int length;
59};
60
61/* The entry alignment, cacheline size if it's known & sensible.
62
63 On x86/AMD64 we assume a 64-byte cacheline size. As it is difficult to
64 guess other right now, these default 16 chars as that shouldn't cause
65 much trouble, even if it not the most optimial value. Override, or modify
66 for other platforms. */
67#ifndef STRCACHE2_ENTRY_ALIGN_SHIFT
68# if defined (__i386__) || defined(__x86_64__)
69# define STRCACHE2_ENTRY_ALIGN_SHIFT 6
70# else
71# define STRCACHE2_ENTRY_ALIGN_SHIFT 4
72# endif
73#endif
74#define STRCACHE2_ENTRY_ALIGNMENT (1 << STRCACHE2_ENTRY_ALIGN_SHIFT)
75
76
77struct strcache2
78{
79 struct strcache2_entry **hash_tab; /* The hash table. */
80 int case_insensitive; /* case insensitive or not. */
81#ifdef STRCACHE2_USE_MASK
82 unsigned int hash_mask; /* The AND mask matching hash_size.*/
83#else
84 unsigned int hash_div; /* The number (prime) to mod by. */
85#endif
86 unsigned long lookup_count; /* The number of lookups. */
87 unsigned long collision_1st_count; /* The number of 1st level collisions. */
88 unsigned long collision_2nd_count; /* The number of 2nd level collisions. */
89 unsigned long collision_3rd_count; /* The number of 3rd level collisions. */
90 unsigned int count; /* Number entries in the cache. */
91#ifdef STRCACHE2_USE_CHAINING
92 unsigned int collision_count; /* Number of entries in chains. */
93#endif
94 unsigned int rehash_count; /* When to rehash the table. */
95 unsigned int init_size; /* The initial hash table size. */
96 unsigned int hash_size; /* The hash table size. */
97 unsigned int def_seg_size; /* The default segment size. */
98 void *lock; /* The lock handle. */
99 struct strcache2_seg *seg_head; /* The memory segment list. */
100 struct strcache2 *next; /* The next string cache. */
101 const char *name; /* Cache name. */
102};
103
104
105void strcache2_init (struct strcache2 *cache, const char *name, unsigned int size,
106 unsigned int def_seg_size, int case_insensitive, int thread_safe);
107void strcache2_term (struct strcache2 *cache);
108void strcache2_print_stats (struct strcache2 *cache, const char *prefix);
109void strcache2_print_stats_all (const char *prefix);
110const char *strcache2_add (struct strcache2 *cache, const char *str, unsigned int length);
111const char *strcache2_iadd (struct strcache2 *cache, const char *str, unsigned int length);
112const char *strcache2_add_hashed (struct strcache2 *cache, const char *str, unsigned int length,
113 unsigned int hash1, unsigned int hash2);
114const char *strcache2_iadd_hashed (struct strcache2 *cache, const char *str, unsigned int length,
115 unsigned int hash1, unsigned int hash2);
116const char *strcache2_lookup (struct strcache2 *cache, const char *str, unsigned int length);
117const char *strcache2_ilookup (struct strcache2 *cache, const char *str, unsigned int length);
118#ifdef HAVE_CASE_INSENSITIVE_FS
119# define strcache2_add_file strcache2_iadd
120# define strcache2_add_hashed_file strcache2_iadd_hashed
121# define strcache2_lookup_file strcache2_ilookup
122#else
123# define strcache2_add_file strcache2_add
124# define strcache2_add_hashed_file strcache2_add_hashed
125# define strcache2_lookup_file strcache2_lookup
126#endif
127int strcache2_is_cached (struct strcache2 *cache, const char *str);
128int strcache2_verify_entry (struct strcache2 *cache, const char *str);
129unsigned int strcache2_get_hash2_fallback (struct strcache2 *cache, const char *str);
130unsigned int strcache2_hash_str (const char *str, unsigned int length, unsigned int *hash2p);
131unsigned int strcache2_hash_istr (const char *str, unsigned int length, unsigned int *hash2p);
132
133/* Get the hash table entry pointer. */
134MY_INLINE struct strcache2_entry const *
135strcache2_get_entry (struct strcache2 *cache, const char *str)
136{
137#ifndef NDEBUG
138 strcache2_verify_entry (cache, str);
139#endif
140 return (struct strcache2_entry const *)str - 1;
141}
142
143/* Get the string length. */
144MY_INLINE unsigned int
145strcache2_get_len (struct strcache2 *cache, const char *str)
146{
147 return strcache2_get_entry (cache, str)->length;
148}
149
150/* Get the first hash value for the string. */
151MY_INLINE unsigned int
152strcache2_get_hash1 (struct strcache2 *cache, const char *str)
153{
154 return strcache2_get_entry (cache, str)->hash1;
155}
156
157#ifndef STRCACHE2_USE_CHAINING
158/* Get the second hash value for the string. */
159MY_INLINE unsigned int
160strcache2_get_hash2 (struct strcache2 *cache, const char *str)
161{
162 unsigned int hash2 = strcache2_get_entry (cache, str)->hash2;
163 if (!hash2)
164 hash2 = strcache2_get_hash2_fallback (cache, str);
165 return hash2;
166}
167#endif
168
169/* Get the pointer hash value for the string.
170
171 This takes the string address, shift out the bits that are always zero
172 due to alignment, and then returns the unsigned integer value of it.
173
174 The results from using this is generally better than for any of the
175 other hash values. It is also sligtly faster code as it does not
176 involve any memory accesses, just a right SHIFT and an optional AND. */
177MY_INLINE unsigned int
178strcache2_get_ptr_hash (struct strcache2 *cache, const char *str)
179{
180 (void)cache;
181 return (size_t)str >> STRCACHE2_ENTRY_ALIGN_SHIFT;
182}
183
184/* Get the user value for the string. */
185MY_INLINE void *
186strcache2_get_user_val (struct strcache2 *cache, const char *str)
187{
188 return strcache2_get_entry (cache, str)->user;
189}
190
191/* Get the user value for the string. */
192MY_INLINE void
193strcache2_set_user_val (struct strcache2 *cache, const char *str, void *value)
194{
195 struct strcache2_entry *entry = (struct strcache2_entry *)str - 1;
196#ifndef NDEBUG
197 strcache2_verify_entry (cache, str);
198#endif
199 entry->user = value;
200}
201
202#endif
203
Note: See TracBrowser for help on using the repository browser.