aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-08-01 15:57:48 +0000
committerNick Mathewson <nickm@torproject.org>2007-08-01 15:57:48 +0000
commitd5c78593d20d40e4801e7017a04d9d0ba85374f9 (patch)
treecc8916211ad7cab64c9420da3707daaeddf0f2d7
parent484c8b776d6d3df9e3ef474ddd85d73b2da79594 (diff)
downloadtor-d5c78593d20d40e4801e7017a04d9d0ba85374f9.tar
tor-d5c78593d20d40e4801e7017a04d9d0ba85374f9.tar.gz
r13873@Kushana: nickm | 2007-07-31 10:54:05 -0700
Split over-optimized digestmap_set code into a generic part and a digestmap-specific part. svn:r11012
-rw-r--r--src/common/container.c49
-rw-r--r--src/common/ht.h25
2 files changed, 47 insertions, 27 deletions
diff --git a/src/common/container.c b/src/common/container.c
index c31a4d271..a148af266 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -769,8 +769,6 @@ digestmap_set(digestmap_t *map, const char *key, void *val)
{
#ifndef OPTIMIZED_DIGESTMAP_SET
digestmap_entry_t *resolve;
-#else
- digestmap_entry_t **resolve_ptr;
#endif
digestmap_entry_t search;
void *oldval;
@@ -792,31 +790,28 @@ digestmap_set(digestmap_t *map, const char *key, void *val)
return NULL;
}
#else
- /* XXXX020 We spend up to 5% of our time in this function, so the code
- * below is meant to optimize the check/alloc/set cycle by avoiding the
- * two trips to the hash table that we do in the unoptimized code above.
- * (Each of HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.)
- *
- * Unfortunately, doing this requires us to poke around inside hash-table
- * internals. It would be nice to avoid that. */
- if (!map->head.hth_table ||
- map->head.hth_n_entries >= map->head.hth_load_limit)
- digestmap_impl_HT_GROW((&map->head), map->head.hth_n_entries+1);
- _HT_SET_HASH(&search, node, digestmap_entry_hash);
- resolve_ptr = _digestmap_impl_HT_FIND_P(&map->head, &search);
- if (*resolve_ptr) {
- oldval = (*resolve_ptr)->val;
- (*resolve_ptr)->val = val;
- return oldval;
- } else {
- digestmap_entry_t *newent = tor_malloc_zero(sizeof(digestmap_entry_t));
- memcpy(newent->key, key, DIGEST_LEN);
- newent->val = val;
- newent->node.hte_hash = search.node.hte_hash;
- *resolve_ptr = newent;
- ++map->head.hth_n_entries;
- return NULL;
- }
+ /* We spend up to 5% of our time in this function, so the code below is
+ * meant to optimize the check/alloc/set cycle by avoiding the two trips to
+ * the hash table that we do in the unoptimized code above. (Each of
+ * HT_INSERT and HT_FIND calls HT_SET_HASH and HT_FIND_P.)
+ */
+ _HT_FIND_OR_INSERT(digestmap_impl, node, digestmap_entry_hash, &(map->head),
+ digestmap_entry_t, &search, ptr,
+ {
+ /* we found an entry. */
+ oldval = (*ptr)->val;
+ (*ptr)->val = val;
+ return oldval;
+ },
+ {
+ /* We didn't find the entry. */
+ digestmap_entry_t *newent =
+ tor_malloc_zero(sizeof(digestmap_entry_t));
+ memcpy(newent->key, key, DIGEST_LEN);
+ newent->val = val;
+ _HT_FOI_INSERT(node, &(map->head), &search, newent, ptr);
+ return NULL;
+ });
#endif
}
diff --git a/src/common/ht.h b/src/common/ht.h
index 72fe5e2cb..095bca356 100644
--- a/src/common/ht.h
+++ b/src/common/ht.h
@@ -382,6 +382,31 @@ ht_string_hash(const char *s)
return 0; \
}
+/** Implements an over-optimized "find and insert if absent" block;
+ * not meant for direct usage by typical code, or usage outside the critical
+ * path.*/
+#define _HT_FIND_OR_INSERT(name, field, hashfn, head, eltype, elm, var, y, n) \
+ { \
+ struct name *_##var##_head = head; \
+ eltype **var; \
+ if (!_##var##_head->hth_table || \
+ _##var##_head->hth_n_entries >= _##var##_head->hth_load_limit) \
+ name##_HT_GROW(_##var##_head, _##var##_head->hth_n_entries+1); \
+ _HT_SET_HASH((elm), field, hashfn); \
+ var = _##name##_HT_FIND_P(_##var##_head, (elm)); \
+ if (*var) { \
+ y; \
+ } else { \
+ n; \
+ } \
+ }
+#define _HT_FOI_INSERT(field, head, elm, newent, var) \
+ { \
+ newent->field.hte_hash = (elm)->field.hte_hash; \
+ *var = newent; \
+ ++((head)->hth_n_entries); \
+ }
+
/*
* Copyright 2005, Nick Mathewson. Implementation logic is adapted from code
* by Cristopher Clark, retrofit to allow drop-in memory management, and to