1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/ht-internal.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,484 @@ 1.4 +/* Based on work Copyright 2002 Christopher Clark */ 1.5 +/* Copyright 2005-2012 Nick Mathewson */ 1.6 +/* Copyright 2009-2012 Niels Provos and Nick Mathewson */ 1.7 +/* See license at end. */ 1.8 + 1.9 +/* Based on ideas by Christopher Clark and interfaces from Niels Provos. */ 1.10 + 1.11 +#ifndef _EVENT_HT_H 1.12 +#define _EVENT_HT_H 1.13 + 1.14 +#define HT_HEAD(name, type) \ 1.15 + struct name { \ 1.16 + /* The hash table itself. */ \ 1.17 + struct type **hth_table; \ 1.18 + /* How long is the hash table? */ \ 1.19 + unsigned hth_table_length; \ 1.20 + /* How many elements does the table contain? */ \ 1.21 + unsigned hth_n_entries; \ 1.22 + /* How many elements will we allow in the table before resizing it? */ \ 1.23 + unsigned hth_load_limit; \ 1.24 + /* Position of hth_table_length in the primes table. */ \ 1.25 + int hth_prime_idx; \ 1.26 + } 1.27 + 1.28 +#define HT_INITIALIZER() \ 1.29 + { NULL, 0, 0, 0, -1 } 1.30 + 1.31 +#ifdef HT_CACHE_HASH_VALUES 1.32 +#define HT_ENTRY(type) \ 1.33 + struct { \ 1.34 + struct type *hte_next; \ 1.35 + unsigned hte_hash; \ 1.36 + } 1.37 +#else 1.38 +#define HT_ENTRY(type) \ 1.39 + struct { \ 1.40 + struct type *hte_next; \ 1.41 + } 1.42 +#endif 1.43 + 1.44 +#define HT_EMPTY(head) \ 1.45 + ((head)->hth_n_entries == 0) 1.46 + 1.47 +/* How many elements in 'head'? */ 1.48 +#define HT_SIZE(head) \ 1.49 + ((head)->hth_n_entries) 1.50 + 1.51 +#define HT_FIND(name, head, elm) name##_HT_FIND((head), (elm)) 1.52 +#define HT_INSERT(name, head, elm) name##_HT_INSERT((head), (elm)) 1.53 +#define HT_REPLACE(name, head, elm) name##_HT_REPLACE((head), (elm)) 1.54 +#define HT_REMOVE(name, head, elm) name##_HT_REMOVE((head), (elm)) 1.55 +#define HT_START(name, head) name##_HT_START(head) 1.56 +#define HT_NEXT(name, head, elm) name##_HT_NEXT((head), (elm)) 1.57 +#define HT_NEXT_RMV(name, head, elm) name##_HT_NEXT_RMV((head), (elm)) 1.58 +#define HT_CLEAR(name, head) name##_HT_CLEAR(head) 1.59 +#define HT_INIT(name, head) name##_HT_INIT(head) 1.60 +/* Helper: */ 1.61 +static inline unsigned 1.62 +ht_improve_hash(unsigned h) 1.63 +{ 1.64 + /* Aim to protect against poor hash functions by adding logic here 1.65 + * - logic taken from java 1.4 hashtable source */ 1.66 + h += ~(h << 9); 1.67 + h ^= ((h >> 14) | (h << 18)); /* >>> */ 1.68 + h += (h << 4); 1.69 + h ^= ((h >> 10) | (h << 22)); /* >>> */ 1.70 + return h; 1.71 +} 1.72 + 1.73 +#if 0 1.74 +/** Basic string hash function, from Java standard String.hashCode(). */ 1.75 +static inline unsigned 1.76 +ht_string_hash(const char *s) 1.77 +{ 1.78 + unsigned h = 0; 1.79 + int m = 1; 1.80 + while (*s) { 1.81 + h += ((signed char)*s++)*m; 1.82 + m = (m<<5)-1; /* m *= 31 */ 1.83 + } 1.84 + return h; 1.85 +} 1.86 +#endif 1.87 + 1.88 +/** Basic string hash function, from Python's str.__hash__() */ 1.89 +static inline unsigned 1.90 +ht_string_hash(const char *s) 1.91 +{ 1.92 + unsigned h; 1.93 + const unsigned char *cp = (const unsigned char *)s; 1.94 + h = *cp << 7; 1.95 + while (*cp) { 1.96 + h = (1000003*h) ^ *cp++; 1.97 + } 1.98 + /* This conversion truncates the length of the string, but that's ok. */ 1.99 + h ^= (unsigned)(cp-(const unsigned char*)s); 1.100 + return h; 1.101 +} 1.102 + 1.103 +#ifdef HT_CACHE_HASH_VALUES 1.104 +#define _HT_SET_HASH(elm, field, hashfn) \ 1.105 + do { (elm)->field.hte_hash = hashfn(elm); } while (0) 1.106 +#define _HT_SET_HASHVAL(elm, field, val) \ 1.107 + do { (elm)->field.hte_hash = (val); } while (0) 1.108 +#define _HT_ELT_HASH(elm, field, hashfn) \ 1.109 + ((elm)->field.hte_hash) 1.110 +#else 1.111 +#define _HT_SET_HASH(elm, field, hashfn) \ 1.112 + ((void)0) 1.113 +#define _HT_ELT_HASH(elm, field, hashfn) \ 1.114 + (hashfn(elm)) 1.115 +#define _HT_SET_HASHVAL(elm, field, val) \ 1.116 + ((void)0) 1.117 +#endif 1.118 + 1.119 +/* Helper: alias for the bucket containing 'elm'. */ 1.120 +#define _HT_BUCKET(head, field, elm, hashfn) \ 1.121 + ((head)->hth_table[_HT_ELT_HASH(elm,field,hashfn) % head->hth_table_length]) 1.122 + 1.123 +#define HT_FOREACH(x, name, head) \ 1.124 + for ((x) = HT_START(name, head); \ 1.125 + (x) != NULL; \ 1.126 + (x) = HT_NEXT(name, head, x)) 1.127 + 1.128 +#define HT_PROTOTYPE(name, type, field, hashfn, eqfn) \ 1.129 + int name##_HT_GROW(struct name *ht, unsigned min_capacity); \ 1.130 + void name##_HT_CLEAR(struct name *ht); \ 1.131 + int _##name##_HT_REP_IS_BAD(const struct name *ht); \ 1.132 + static inline void \ 1.133 + name##_HT_INIT(struct name *head) { \ 1.134 + head->hth_table_length = 0; \ 1.135 + head->hth_table = NULL; \ 1.136 + head->hth_n_entries = 0; \ 1.137 + head->hth_load_limit = 0; \ 1.138 + head->hth_prime_idx = -1; \ 1.139 + } \ 1.140 + /* Helper: returns a pointer to the right location in the table \ 1.141 + * 'head' to find or insert the element 'elm'. */ \ 1.142 + static inline struct type ** \ 1.143 + _##name##_HT_FIND_P(struct name *head, struct type *elm) \ 1.144 + { \ 1.145 + struct type **p; \ 1.146 + if (!head->hth_table) \ 1.147 + return NULL; \ 1.148 + p = &_HT_BUCKET(head, field, elm, hashfn); \ 1.149 + while (*p) { \ 1.150 + if (eqfn(*p, elm)) \ 1.151 + return p; \ 1.152 + p = &(*p)->field.hte_next; \ 1.153 + } \ 1.154 + return p; \ 1.155 + } \ 1.156 + /* Return a pointer to the element in the table 'head' matching 'elm', \ 1.157 + * or NULL if no such element exists */ \ 1.158 + static inline struct type * \ 1.159 + name##_HT_FIND(const struct name *head, struct type *elm) \ 1.160 + { \ 1.161 + struct type **p; \ 1.162 + struct name *h = (struct name *) head; \ 1.163 + _HT_SET_HASH(elm, field, hashfn); \ 1.164 + p = _##name##_HT_FIND_P(h, elm); \ 1.165 + return p ? *p : NULL; \ 1.166 + } \ 1.167 + /* Insert the element 'elm' into the table 'head'. Do not call this \ 1.168 + * function if the table might already contain a matching element. */ \ 1.169 + static inline void \ 1.170 + name##_HT_INSERT(struct name *head, struct type *elm) \ 1.171 + { \ 1.172 + struct type **p; \ 1.173 + if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \ 1.174 + name##_HT_GROW(head, head->hth_n_entries+1); \ 1.175 + ++head->hth_n_entries; \ 1.176 + _HT_SET_HASH(elm, field, hashfn); \ 1.177 + p = &_HT_BUCKET(head, field, elm, hashfn); \ 1.178 + elm->field.hte_next = *p; \ 1.179 + *p = elm; \ 1.180 + } \ 1.181 + /* Insert the element 'elm' into the table 'head'. If there already \ 1.182 + * a matching element in the table, replace that element and return \ 1.183 + * it. */ \ 1.184 + static inline struct type * \ 1.185 + name##_HT_REPLACE(struct name *head, struct type *elm) \ 1.186 + { \ 1.187 + struct type **p, *r; \ 1.188 + if (!head->hth_table || head->hth_n_entries >= head->hth_load_limit) \ 1.189 + name##_HT_GROW(head, head->hth_n_entries+1); \ 1.190 + _HT_SET_HASH(elm, field, hashfn); \ 1.191 + p = _##name##_HT_FIND_P(head, elm); \ 1.192 + r = *p; \ 1.193 + *p = elm; \ 1.194 + if (r && (r!=elm)) { \ 1.195 + elm->field.hte_next = r->field.hte_next; \ 1.196 + r->field.hte_next = NULL; \ 1.197 + return r; \ 1.198 + } else { \ 1.199 + ++head->hth_n_entries; \ 1.200 + return NULL; \ 1.201 + } \ 1.202 + } \ 1.203 + /* Remove any element matching 'elm' from the table 'head'. If such \ 1.204 + * an element is found, return it; otherwise return NULL. */ \ 1.205 + static inline struct type * \ 1.206 + name##_HT_REMOVE(struct name *head, struct type *elm) \ 1.207 + { \ 1.208 + struct type **p, *r; \ 1.209 + _HT_SET_HASH(elm, field, hashfn); \ 1.210 + p = _##name##_HT_FIND_P(head,elm); \ 1.211 + if (!p || !*p) \ 1.212 + return NULL; \ 1.213 + r = *p; \ 1.214 + *p = r->field.hte_next; \ 1.215 + r->field.hte_next = NULL; \ 1.216 + --head->hth_n_entries; \ 1.217 + return r; \ 1.218 + } \ 1.219 + /* Invoke the function 'fn' on every element of the table 'head', \ 1.220 + * using 'data' as its second argument. If the function returns \ 1.221 + * nonzero, remove the most recently examined element before invoking \ 1.222 + * the function again. */ \ 1.223 + static inline void \ 1.224 + name##_HT_FOREACH_FN(struct name *head, \ 1.225 + int (*fn)(struct type *, void *), \ 1.226 + void *data) \ 1.227 + { \ 1.228 + unsigned idx; \ 1.229 + struct type **p, **nextp, *next; \ 1.230 + if (!head->hth_table) \ 1.231 + return; \ 1.232 + for (idx=0; idx < head->hth_table_length; ++idx) { \ 1.233 + p = &head->hth_table[idx]; \ 1.234 + while (*p) { \ 1.235 + nextp = &(*p)->field.hte_next; \ 1.236 + next = *nextp; \ 1.237 + if (fn(*p, data)) { \ 1.238 + --head->hth_n_entries; \ 1.239 + *p = next; \ 1.240 + } else { \ 1.241 + p = nextp; \ 1.242 + } \ 1.243 + } \ 1.244 + } \ 1.245 + } \ 1.246 + /* Return a pointer to the first element in the table 'head', under \ 1.247 + * an arbitrary order. This order is stable under remove operations, \ 1.248 + * but not under others. If the table is empty, return NULL. */ \ 1.249 + static inline struct type ** \ 1.250 + name##_HT_START(struct name *head) \ 1.251 + { \ 1.252 + unsigned b = 0; \ 1.253 + while (b < head->hth_table_length) { \ 1.254 + if (head->hth_table[b]) \ 1.255 + return &head->hth_table[b]; \ 1.256 + ++b; \ 1.257 + } \ 1.258 + return NULL; \ 1.259 + } \ 1.260 + /* Return the next element in 'head' after 'elm', under the arbitrary \ 1.261 + * order used by HT_START. If there are no more elements, return \ 1.262 + * NULL. If 'elm' is to be removed from the table, you must call \ 1.263 + * this function for the next value before you remove it. \ 1.264 + */ \ 1.265 + static inline struct type ** \ 1.266 + name##_HT_NEXT(struct name *head, struct type **elm) \ 1.267 + { \ 1.268 + if ((*elm)->field.hte_next) { \ 1.269 + return &(*elm)->field.hte_next; \ 1.270 + } else { \ 1.271 + unsigned b = (_HT_ELT_HASH(*elm, field, hashfn) % head->hth_table_length)+1; \ 1.272 + while (b < head->hth_table_length) { \ 1.273 + if (head->hth_table[b]) \ 1.274 + return &head->hth_table[b]; \ 1.275 + ++b; \ 1.276 + } \ 1.277 + return NULL; \ 1.278 + } \ 1.279 + } \ 1.280 + static inline struct type ** \ 1.281 + name##_HT_NEXT_RMV(struct name *head, struct type **elm) \ 1.282 + { \ 1.283 + unsigned h = _HT_ELT_HASH(*elm, field, hashfn); \ 1.284 + *elm = (*elm)->field.hte_next; \ 1.285 + --head->hth_n_entries; \ 1.286 + if (*elm) { \ 1.287 + return elm; \ 1.288 + } else { \ 1.289 + unsigned b = (h % head->hth_table_length)+1; \ 1.290 + while (b < head->hth_table_length) { \ 1.291 + if (head->hth_table[b]) \ 1.292 + return &head->hth_table[b]; \ 1.293 + ++b; \ 1.294 + } \ 1.295 + return NULL; \ 1.296 + } \ 1.297 + } 1.298 + 1.299 +#define HT_GENERATE(name, type, field, hashfn, eqfn, load, mallocfn, \ 1.300 + reallocfn, freefn) \ 1.301 + static unsigned name##_PRIMES[] = { \ 1.302 + 53, 97, 193, 389, \ 1.303 + 769, 1543, 3079, 6151, \ 1.304 + 12289, 24593, 49157, 98317, \ 1.305 + 196613, 393241, 786433, 1572869, \ 1.306 + 3145739, 6291469, 12582917, 25165843, \ 1.307 + 50331653, 100663319, 201326611, 402653189, \ 1.308 + 805306457, 1610612741 \ 1.309 + }; \ 1.310 + static unsigned name##_N_PRIMES = \ 1.311 + (unsigned)(sizeof(name##_PRIMES)/sizeof(name##_PRIMES[0])); \ 1.312 + /* Expand the internal table of 'head' until it is large enough to \ 1.313 + * hold 'size' elements. Return 0 on success, -1 on allocation \ 1.314 + * failure. */ \ 1.315 + int \ 1.316 + name##_HT_GROW(struct name *head, unsigned size) \ 1.317 + { \ 1.318 + unsigned new_len, new_load_limit; \ 1.319 + int prime_idx; \ 1.320 + struct type **new_table; \ 1.321 + if (head->hth_prime_idx == (int)name##_N_PRIMES - 1) \ 1.322 + return 0; \ 1.323 + if (head->hth_load_limit > size) \ 1.324 + return 0; \ 1.325 + prime_idx = head->hth_prime_idx; \ 1.326 + do { \ 1.327 + new_len = name##_PRIMES[++prime_idx]; \ 1.328 + new_load_limit = (unsigned)(load*new_len); \ 1.329 + } while (new_load_limit <= size && \ 1.330 + prime_idx < (int)name##_N_PRIMES); \ 1.331 + if ((new_table = mallocfn(new_len*sizeof(struct type*)))) { \ 1.332 + unsigned b; \ 1.333 + memset(new_table, 0, new_len*sizeof(struct type*)); \ 1.334 + for (b = 0; b < head->hth_table_length; ++b) { \ 1.335 + struct type *elm, *next; \ 1.336 + unsigned b2; \ 1.337 + elm = head->hth_table[b]; \ 1.338 + while (elm) { \ 1.339 + next = elm->field.hte_next; \ 1.340 + b2 = _HT_ELT_HASH(elm, field, hashfn) % new_len; \ 1.341 + elm->field.hte_next = new_table[b2]; \ 1.342 + new_table[b2] = elm; \ 1.343 + elm = next; \ 1.344 + } \ 1.345 + } \ 1.346 + if (head->hth_table) \ 1.347 + freefn(head->hth_table); \ 1.348 + head->hth_table = new_table; \ 1.349 + } else { \ 1.350 + unsigned b, b2; \ 1.351 + new_table = reallocfn(head->hth_table, new_len*sizeof(struct type*)); \ 1.352 + if (!new_table) return -1; \ 1.353 + memset(new_table + head->hth_table_length, 0, \ 1.354 + (new_len - head->hth_table_length)*sizeof(struct type*)); \ 1.355 + for (b=0; b < head->hth_table_length; ++b) { \ 1.356 + struct type *e, **pE; \ 1.357 + for (pE = &new_table[b], e = *pE; e != NULL; e = *pE) { \ 1.358 + b2 = _HT_ELT_HASH(e, field, hashfn) % new_len; \ 1.359 + if (b2 == b) { \ 1.360 + pE = &e->field.hte_next; \ 1.361 + } else { \ 1.362 + *pE = e->field.hte_next; \ 1.363 + e->field.hte_next = new_table[b2]; \ 1.364 + new_table[b2] = e; \ 1.365 + } \ 1.366 + } \ 1.367 + } \ 1.368 + head->hth_table = new_table; \ 1.369 + } \ 1.370 + head->hth_table_length = new_len; \ 1.371 + head->hth_prime_idx = prime_idx; \ 1.372 + head->hth_load_limit = new_load_limit; \ 1.373 + return 0; \ 1.374 + } \ 1.375 + /* Free all storage held by 'head'. Does not free 'head' itself, or \ 1.376 + * individual elements. */ \ 1.377 + void \ 1.378 + name##_HT_CLEAR(struct name *head) \ 1.379 + { \ 1.380 + if (head->hth_table) \ 1.381 + freefn(head->hth_table); \ 1.382 + head->hth_table_length = 0; \ 1.383 + name##_HT_INIT(head); \ 1.384 + } \ 1.385 + /* Debugging helper: return false iff the representation of 'head' is \ 1.386 + * internally consistent. */ \ 1.387 + int \ 1.388 + _##name##_HT_REP_IS_BAD(const struct name *head) \ 1.389 + { \ 1.390 + unsigned n, i; \ 1.391 + struct type *elm; \ 1.392 + if (!head->hth_table_length) { \ 1.393 + if (!head->hth_table && !head->hth_n_entries && \ 1.394 + !head->hth_load_limit && head->hth_prime_idx == -1) \ 1.395 + return 0; \ 1.396 + else \ 1.397 + return 1; \ 1.398 + } \ 1.399 + if (!head->hth_table || head->hth_prime_idx < 0 || \ 1.400 + !head->hth_load_limit) \ 1.401 + return 2; \ 1.402 + if (head->hth_n_entries > head->hth_load_limit) \ 1.403 + return 3; \ 1.404 + if (head->hth_table_length != name##_PRIMES[head->hth_prime_idx]) \ 1.405 + return 4; \ 1.406 + if (head->hth_load_limit != (unsigned)(load*head->hth_table_length)) \ 1.407 + return 5; \ 1.408 + for (n = i = 0; i < head->hth_table_length; ++i) { \ 1.409 + for (elm = head->hth_table[i]; elm; elm = elm->field.hte_next) { \ 1.410 + if (_HT_ELT_HASH(elm, field, hashfn) != hashfn(elm)) \ 1.411 + return 1000 + i; \ 1.412 + if ((_HT_ELT_HASH(elm, field, hashfn) % head->hth_table_length) != i) \ 1.413 + return 10000 + i; \ 1.414 + ++n; \ 1.415 + } \ 1.416 + } \ 1.417 + if (n != head->hth_n_entries) \ 1.418 + return 6; \ 1.419 + return 0; \ 1.420 + } 1.421 + 1.422 +/** Implements an over-optimized "find and insert if absent" block; 1.423 + * not meant for direct usage by typical code, or usage outside the critical 1.424 + * path.*/ 1.425 +#define _HT_FIND_OR_INSERT(name, field, hashfn, head, eltype, elm, var, y, n) \ 1.426 + { \ 1.427 + struct name *_##var##_head = head; \ 1.428 + struct eltype **var; \ 1.429 + if (!_##var##_head->hth_table || \ 1.430 + _##var##_head->hth_n_entries >= _##var##_head->hth_load_limit) \ 1.431 + name##_HT_GROW(_##var##_head, _##var##_head->hth_n_entries+1); \ 1.432 + _HT_SET_HASH((elm), field, hashfn); \ 1.433 + var = _##name##_HT_FIND_P(_##var##_head, (elm)); \ 1.434 + if (*var) { \ 1.435 + y; \ 1.436 + } else { \ 1.437 + n; \ 1.438 + } \ 1.439 + } 1.440 +#define _HT_FOI_INSERT(field, head, elm, newent, var) \ 1.441 + { \ 1.442 + _HT_SET_HASHVAL(newent, field, (elm)->field.hte_hash); \ 1.443 + newent->field.hte_next = NULL; \ 1.444 + *var = newent; \ 1.445 + ++((head)->hth_n_entries); \ 1.446 + } 1.447 + 1.448 +/* 1.449 + * Copyright 2005, Nick Mathewson. Implementation logic is adapted from code 1.450 + * by Cristopher Clark, retrofit to allow drop-in memory management, and to 1.451 + * use the same interface as Niels Provos's tree.h. This is probably still 1.452 + * a derived work, so the original license below still applies. 1.453 + * 1.454 + * Copyright (c) 2002, Christopher Clark 1.455 + * All rights reserved. 1.456 + * 1.457 + * Redistribution and use in source and binary forms, with or without 1.458 + * modification, are permitted provided that the following conditions 1.459 + * are met: 1.460 + * 1.461 + * * Redistributions of source code must retain the above copyright 1.462 + * notice, this list of conditions and the following disclaimer. 1.463 + * 1.464 + * * Redistributions in binary form must reproduce the above copyright 1.465 + * notice, this list of conditions and the following disclaimer in the 1.466 + * documentation and/or other materials provided with the distribution. 1.467 + * 1.468 + * * Neither the name of the original author; nor the names of any contributors 1.469 + * may be used to endorse or promote products derived from this software 1.470 + * without specific prior written permission. 1.471 + * 1.472 + * 1.473 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.474 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.475 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.476 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 1.477 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1.478 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1.479 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 1.480 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 1.481 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 1.482 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 1.483 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.484 +*/ 1.485 + 1.486 +#endif 1.487 +