apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Greg Stein <gst...@lyra.org>
Subject Re: [PATCH] speedups for mod_mime and apr_hash_t
Date Wed, 07 Nov 2001 10:11:26 GMT
On Wed, Nov 07, 2001 at 12:08:11AM -0800, Brian Pane wrote:
>...
> +/**
> + * Merge two hash tables into one new hash table. If the same key
> + * is present in both tables, call the supplied merge function to
> + * produce a merged value for the key in the new table.
> + * @param p The pool to use for the new hash table
> + * @param overlay The table to add to the initial table
> + * @param base The table that represents the initial values of the new table
> + * @param merger A callback function to merge values
> + * @return A new hash table containing all of the data from the two passed in
> + */
> +APR_DECLARE(apr_hash_t *) apr_hash_merge(apr_pool_t *p,
> +                                         const apr_hash_t *overlay, 
> +                                         const apr_hash_t *base,
> +                                         void * (*merger)(apr_pool_t *p,
> +                                                     const void *key,
> +                                                     const void *overlay_val,
> +                                                     const void *base_val));

The merge function needs klen. All hash keys are ptr/len pairs.

Note that "overlay" and "base" are bogus terms since the merge defines the
operation. Just call them h1 and h2. The merger can sort out who "wins" or
how to merge them.

The merger function should take a void* context pointer. Just a pool is not
enough.

>...
> +APR_DECLARE(apr_hash_t *) apr_hash_copy(apr_pool_t *pool,
> +                                        const apr_hash_t *orig)
> +{
> +    apr_hash_t *ht;
> +    int i;
> +
> +    ht = apr_palloc(pool, sizeof(apr_hash_t));
> +    ht->pool = pool;
> +    ht->count = orig->count;
> +    ht->max = orig->max;
> +    ht->array = alloc_array(ht, ht->max);
> +
> +    for (i = 0; i <= ht->max; i++) {
> +        apr_hash_entry_t **new_entry = &(ht->array[i]);
> +        apr_hash_entry_t *orig_entry = orig->array[i];
> +        while (orig_entry) {
> +            *new_entry = (apr_hash_entry_t *)apr_palloc(ht->pool,
> +                                                sizeof(apr_hash_entry_t));

You can allocate all apr_hash_entry_t structures up front in one mother
allocation by using ht->count. Just peel off the structures as you need them
inside this loop.

Even better, you can glom the apr_hash_t, the ht->array, and the entries
into one super momma allocation.

>...
> @@ -335,10 +365,22 @@
>                                            const apr_hash_t *overlay, 
>                                            const apr_hash_t *base)
>  {
> +    return apr_hash_merge(p, overlay, base, NULL);

Passing NULL is not part of the defined interface. Update the docco or don't
pass NULL :-)

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/

Mime
View raw message