1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Simple cache implementation.
32 * We simply have fixed size array, and destroy previous values on collision.
34 * @author Jose Fonseca <jfonseca@vmware.com>
38 #include "pipe/p_compiler.h"
39 #include "util/u_debug.h"
41 #include "util/u_math.h"
42 #include "util/u_memory.h"
43 #include "util/u_cache.h"
46 struct util_cache_entry
60 uint32_t (*hash
)(const void *key
);
62 /** Compare two keys */
63 int (*compare
)(const void *key1
, const void *key2
);
65 /** Destroy a (key, value) pair */
66 void (*destroy
)(void *key
, void *value
);
70 struct util_cache_entry
*entries
;
79 util_cache_create(uint32_t (*hash
)(const void *key
),
80 int (*compare
)(const void *key1
, const void *key2
),
81 void (*destroy
)(void *key
, void *value
),
84 struct util_cache
*cache
;
86 cache
= CALLOC_STRUCT(util_cache
);
91 cache
->compare
= compare
;
92 cache
->destroy
= destroy
;
95 cache
->entries
= CALLOC(size
, sizeof(struct util_cache_entry
));
105 static INLINE
struct util_cache_entry
*
106 util_cache_entry_get(struct util_cache
*cache
,
111 hash
= cache
->hash(key
);
113 return &cache
->entries
[hash
% cache
->size
];
117 util_cache_entry_destroy(struct util_cache
*cache
,
118 struct util_cache_entry
*entry
)
120 void *key
= entry
->key
;
121 void *value
= entry
->value
;
128 cache
->destroy(key
, value
);
133 util_cache_set(struct util_cache
*cache
,
137 struct util_cache_entry
*entry
;
141 entry
= util_cache_entry_get(cache
, key
);
142 util_cache_entry_destroy(cache
, entry
);
150 entry
->value
= value
;
155 util_cache_get(struct util_cache
*cache
,
158 struct util_cache_entry
*entry
;
162 entry
= util_cache_entry_get(cache
, key
);
163 if(!entry
->key
&& !entry
->value
)
166 if(cache
->compare(key
, entry
->key
) != 0)
174 util_cache_clear(struct util_cache
*cache
)
180 for(i
= 0; i
< cache
->size
; ++i
)
181 util_cache_entry_destroy(cache
, &cache
->entries
[i
]);
186 util_cache_destroy(struct util_cache
*cache
)
191 if(cache
->count
>= 20*cache
->size
) {
192 /* Normal approximation of the Poisson distribution */
193 double mean
= (double)cache
->count
/(double)cache
->size
;
194 double stddev
= sqrt(mean
);
196 for(i
= 0; i
< cache
->size
; ++i
) {
197 double z
= fabs(cache
->count
- mean
)/stddev
;
198 /* This assert should not fail 99.9999998027% of the times, unless
199 * the hash function is a poor one */
205 util_cache_clear(cache
);
207 FREE(cache
->entries
);