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

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

kmk: added strcache2_get_ptr_hash for more efficent hashing by string pool users; replacing hash1 with that and hash2 with hash1, thus avoiding unnecessary hash2 calculations.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.4 KB
Line 
1/* $Id: strcache2.h 1897 2008-10-21 01:21:39Z 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/* string cache memory segment. */
35struct strcache2_seg
36{
37 struct strcache2_seg *next; /* The next cache segment. */
38 char *start; /* The first byte in the segment. */
39 size_t size; /* The size of the segment. */
40 size_t avail; /* The number of available bytes. */
41 char *cursor; /* Allocation cursor. */
42};
43
44/* string cache hash table entry. */
45struct strcache2_entry
46{
47 void *user;
48 unsigned int hash1;
49 unsigned int hash2;
50 unsigned int length;
51};
52
53/* The entry alignment.
54 As it is very difficult to derive this from any #define or typedef, a
55 default value of 16 (chars) was choosen as this fits most platforms.
56 For odd platforms, just override this define. */
57#ifndef STRCACHE2_ENTRY_ALIGN_SHIFT
58# define STRCACHE2_ENTRY_ALIGN_SHIFT 4
59#endif
60#define STRCACHE2_ENTRY_ALIGNMENT (1 << STRCACHE2_ENTRY_ALIGN_SHIFT)
61
62
63struct strcache2
64{
65 struct strcache2_entry **hash_tab; /* The hash table. */
66 int case_insensitive; /* case insensitive or not. */
67 unsigned int hash_mask; /* The AND mask matching hash_size.*/
68 unsigned long lookup_count; /* The number of lookups. */
69 unsigned long collision_1st_count; /* The number of 1st level collisions. */
70 unsigned long collision_2nd_count; /* The number of 2nd level collisions. */
71 unsigned long collision_3rd_count; /* The number of 3rd level collisions. */
72 unsigned int count; /* Number entries in the cache. */
73 unsigned int rehash_count; /* When to rehash the table. */
74 unsigned int init_size; /* The initial hash table size. */
75 unsigned int hash_size; /* The hash table size. */
76 unsigned int def_seg_size; /* The default segment size. */
77 void *lock; /* The lock handle. */
78 struct strcache2_seg *seg_head; /* The memory segment list. */
79 struct strcache2 *next; /* The next string cache. */
80 const char *name; /* Cache name. */
81};
82
83
84void strcache2_init (struct strcache2 *cache, const char *name, unsigned int size,
85 unsigned int def_seg_size, int case_insensitive, int thread_safe);
86void strcache2_term (struct strcache2 *cache);
87void strcache2_print_stats (struct strcache2 *cache, const char *prefix);
88void strcache2_print_stats_all (const char *prefix);
89const char *strcache2_add (struct strcache2 *cache, const char *str, unsigned int length);
90const char *strcache2_iadd (struct strcache2 *cache, const char *str, unsigned int length);
91#ifdef HAVE_CASE_INSENSITIVE_FS
92# define strcache2_add_file(cache, str, length) strcache2_iadd((cache), (str), (length))
93#else
94# define strcache2_add_file(cache, str, length) strcache2_add((cache), (str), (length))
95#endif
96const char *strcache2_add_hashed (struct strcache2 *cache, const char *str, unsigned int length,
97 unsigned int hash1, unsigned int hash2);
98const char *strcache2_lookup (struct strcache2 *cache, const char *str, unsigned int length);
99int strcache2_is_cached (struct strcache2 *cache, const char *str);
100int strcache2_verify_entry (struct strcache2 *cache, const char *str);
101unsigned int strcache2_get_hash2_fallback (struct strcache2 *cache, const char *str);
102unsigned int strcache2_hash_str (const char *str, unsigned int length, unsigned int *hash2p);
103unsigned int strcache2_hash_istr (const char *str, unsigned int length, unsigned int *hash2p);
104
105/* Get the hash table entry pointer. */
106MY_INLINE struct strcache2_entry const *
107strcache2_get_entry (struct strcache2 *cache, const char *str)
108{
109#ifndef NDEBUG
110 strcache2_verify_entry (cache, str);
111#endif
112 return (struct strcache2_entry const *)str - 1;
113}
114
115/* Get the string length. */
116MY_INLINE unsigned int
117strcache2_get_len (struct strcache2 *cache, const char *str)
118{
119 return strcache2_get_entry (cache, str)->length;
120}
121
122/* Get the first hash value for the string. */
123MY_INLINE unsigned int
124strcache2_get_hash1 (struct strcache2 *cache, const char *str)
125{
126 return strcache2_get_entry (cache, str)->hash1;
127}
128
129/* Get the second hash value for the string. */
130MY_INLINE unsigned int
131strcache2_get_hash2 (struct strcache2 *cache, const char *str)
132{
133 unsigned int hash2 = strcache2_get_entry (cache, str)->hash2;
134 if (!hash2)
135 hash2 = strcache2_get_hash2_fallback (cache, str);
136 return hash2;
137}
138
139/* Get the pointer hash value for the string.
140
141 This takes the string address, shift out the bits that are always zero
142 due to alignment, and then returns the unsigned integer value of it.
143
144 The results from using this is generally better than for any of the
145 other hash values. It is also sligtly faster code as it does not
146 involve any memory accesses, just a right SHIFT and an optional AND. */
147MY_INLINE unsigned int
148strcache2_get_ptr_hash (struct strcache2 *cache, const char *str)
149{
150 (void)cache;
151 return (size_t)str >> STRCACHE2_ENTRY_ALIGN_SHIFT;
152}
153
154/* Get the user value for the string. */
155MY_INLINE void *
156strcache2_get_user_val (struct strcache2 *cache, const char *str)
157{
158 return strcache2_get_entry (cache, str)->user;
159}
160
161/* Get the user value for the string. */
162MY_INLINE void
163strcache2_set_user_val (struct strcache2 *cache, const char *str, void *value)
164{
165 struct strcache2_entry *entry = (struct strcache2_entry *)str - 1;
166#ifndef NDEBUG
167 strcache2_verify_entry (cache, str);
168#endif
169 entry->user = value;
170}
171
172#endif
173
Note: See TracBrowser for help on using the repository browser.