Hello,
I'm currently working on a code with a quite painful pattern (hot path) :
value = apr_hash_get(key);
if (value == NULL) {
value = make_new_value();
apr_hash_set(key, value)
}
and would be interested in having the following apr_hash_get_or_set()
function to do something like :
value = apr_hash_get_or_set(key, ctx->spare_value);
if (value == ctx->spare_value) {
ctx->spare_value = make_new_value();
}
Do you think this is suitable for APR (possibly 1.6)?
Index: tables/apr_hash.c
===================================================================
--- tables/apr_hash.c (revision 1627394)
+++ tables/apr_hash.c (working copy)
@@ -399,6 +399,25 @@ APR_DECLARE(void) apr_hash_set(apr_hash_t *ht,
/* else key not present and val==NULL */
}
+APR_DECLARE(void *) apr_hash_get_or_set(apr_hash_t *ht,
+ const void *key,
+ apr_ssize_t klen,
+ const void *val)
+{
+ apr_hash_entry_t **hep;
+ hep = find_entry(ht, key, klen, val);
+ if (*hep) {
+ val = (*hep)->val;
+ /* check that the collision rate isn't too high */
+ if (ht->count > ht->max) {
+ expand_array(ht);
+ }
+ return (void *)val;
+ }
+ /* else key not present and val==NULL */
+ return NULL;
+}
+
APR_DECLARE(unsigned int) apr_hash_count(apr_hash_t *ht)
{
return ht->count;
Index: include/apr_hash.h
===================================================================
--- include/apr_hash.h (revision 1627394)
+++ include/apr_hash.h (working copy)
@@ -118,6 +118,20 @@ APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht, c
apr_ssize_t klen);
/**
+ * Look up the value associated with a key in a hash table, or associate the
+ * given value if none exists.
+ * @param ht The hash table
+ * @param key Pointer to the key
+ * @param klen Length of the key. Can be APR_HASH_KEY_STRING to use the string
+ * length.
+ * @param val Value to associate with the key (if none exists).
+ * @return Returns the existing value if any, the given value otherwise.
+ * @remark If the given value is NULL and a hash entry exists, nothing is done.
+ */
+APR_DECLARE(void *) apr_hash_get_or_set(apr_hash_t *ht, const void *key,
+ apr_ssize_t klen, const void *val);
+
+/**
* Start iterating over the entries in a hash table.
* @param p The pool to allocate the apr_hash_index_t iterator. If this
* pool is NULL, then an internal, non-thread-safe iterator is used.
[END]
Regards,
Yann.