Justus Winter, le Thu 15 May 2014 23:10:50 +0200, a écrit :
> If libihash is used to implement a cache, a insertion is always
> preceeded by a lookup.  hurd_ihash_add has to do the lookup again.
> 
> Provide a new pair of functions, hurd_ihash_locp_add and
> hurd_ihash_locp_find, that can be used in combination to avoid the
> second lookup.

Ack.

> * libihash/ihash.c (hurd_ihash_locp_add): New function using a
> location pointer...
> (hurd_ihash_locp_find): ... that has been returned by this function.
> * libihash/ihash.h (hurd_ihash_locp_add): New declaration.
> (hurd_ihash_locp_find): Likewise.
> (hurd_ihash_locp_value): New function.
> ---
>  libihash/ihash.c | 78 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  libihash/ihash.h | 52 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 129 insertions(+), 1 deletion(-)
> 
> diff --git a/libihash/ihash.c b/libihash/ihash.c
> index 5b7b542..167c872 100644
> --- a/libihash/ihash.c
> +++ b/libihash/ihash.c
> @@ -258,7 +258,54 @@ add_one (hurd_ihash_t ht, hurd_ihash_key_t key, 
> hurd_ihash_value_t value)
>    return 0;
>  }
>  
> -  
> +
> +/* Add VALUE to the hash table HT under the key KEY at LOCP.  If there
> +   already is an item under this key, call the cleanup function (if
> +   any) for it before overriding the value.  This function is faster
> +   than hurd_ihash_add.
> +
> +   If LOCP is NULL, fall back to hurd_ihash_add.  Otherwise, LOCP must
> +   be valid and may either be obtained from hurd_ihash_locp_find, or
> +   from an item that is currently in the hash table.  If an item is
> +   replaced, KEY must match the key of the previous item.
> +
> +   If a memory allocation error occurs, ENOMEM is returned, otherwise
> +   0.  */
> +error_t
> +hurd_ihash_locp_add (hurd_ihash_t ht, hurd_ihash_locp_t locp,
> +                     hurd_ihash_key_t key, hurd_ihash_value_t value)
> +{
> +  struct _hurd_ihash_item *item = (struct _hurd_ihash_item *) locp;
> +
> +  /* In case of complications, fall back to hurd_ihash_add.  */
> +  if (ht->size == 0
> +      || item == NULL
> +      || item->value == _HURD_IHASH_DELETED
> +      || hurd_ihash_get_load (ht) > ht->max_load)
> +    return hurd_ihash_add (ht, key, value);
> +
> +  if (item->value == _HURD_IHASH_EMPTY)
> +    {
> +      item->key = key;
> +      ht->nr_items += 1;
> +    }
> +  else
> +    {
> +      assert (item->key == key);
> +      if (ht->cleanup)
> +        (*ht->cleanup) (locp, ht->cleanup_data);
> +    }
> +
> +  item->value = value;
> +
> +  if (ht->locp_offset != HURD_IHASH_NO_LOCP)
> +    *((hurd_ihash_locp_t *) (((char *) value) + ht->locp_offset))
> +      = locp;
> +
> +  return 0;
> +}
> +
> +
>  /* Add ITEM to the hash table HT under the key KEY.  If there already
>     is an item under this key, call the cleanup function (if any) for
>     it before overriding the value.  If a memory allocation error
> @@ -327,6 +374,35 @@ hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key_t key)
>      }
>  }
>  
> +/* Find the item in the hash table HT with key KEY.  If it is found,
> +   return the location of its slot in the hash table.  If it is not
> +   found, this function may still return a location.
> +
> +   This location pointer can always be safely accessed using
> +   hurd_ihash_locp_value.  If the lookup is successful,
> +   hurd_ihash_locp_value will return the value related to KEY.
> +
> +   If the lookup is successful, the returned location can be used with
> +   hurd_ihash_locp_add to update the item, and with
> +   hurd_ihash_locp_remove to remove it.
> +
> +   If the lookup is not successful, the returned location can be used
> +   with hurd_ihash_locp_add to add the item.
> +
> +   Note that returned location is only valid until the next insertion
> +   or deletion.  */
> +hurd_ihash_locp_t
> +hurd_ihash_locp_find (hurd_ihash_t ht, hurd_ihash_key_t key)
> +{
> +  int idx;
> +
> +  if (ht->size == 0)
> +    return NULL;
> +
> +  idx = find_index (ht, key);
> +  return &ht->items[idx].value;
> +}
> +
>  
>  /* Remove the entry with the key KEY from the hash table HT.  If such
>     an entry was found and removed, 1 is returned, otherwise 0.  */
> diff --git a/libihash/ihash.h b/libihash/ihash.h
> index 394bcf9..f7ecf1b 100644
> --- a/libihash/ihash.h
> +++ b/libihash/ihash.h
> @@ -26,6 +26,7 @@
>  #include <sys/types.h>
>  #include <limits.h>
>  #include <stdint.h>
> +#include <stddef.h>
>  
>  
>  /* The type of the values corresponding to the keys.  Must be a
> @@ -198,10 +199,61 @@ hurd_ihash_get_load (hurd_ihash_t ht)
>  error_t hurd_ihash_add (hurd_ihash_t ht, hurd_ihash_key_t key,
>                       hurd_ihash_value_t item);
>  
> +/* Add VALUE to the hash table HT under the key KEY at LOCP.  If there
> +   already is an item under this key, call the cleanup function (if
> +   any) for it before overriding the value.  This function is faster
> +   than hurd_ihash_add.
> +
> +   If LOCP is NULL, fall back to hurd_ihash_add.  Otherwise, LOCP must
> +   be valid and may either be obtained from hurd_ihash_locp_find, or
> +   from an item that is currently in the hash table.  If an item is
> +   replaced, KEY must match the key of the previous item.
> +
> +   If a memory allocation error occurs, ENOMEM is returned, otherwise
> +   0.  */
> +error_t hurd_ihash_locp_add (hurd_ihash_t ht, hurd_ihash_locp_t locp,
> +                             hurd_ihash_key_t key, hurd_ihash_value_t value);
> +
>  /* Find and return the item in the hash table HT with key KEY, or NULL
>     if it doesn't exist.  */
>  hurd_ihash_value_t hurd_ihash_find (hurd_ihash_t ht, hurd_ihash_key_t key);
>  
> +/* Find the item in the hash table HT with key KEY.  If it is found,
> +   return the location of its slot in the hash table.  If it is not
> +   found, this function may still return a location.
> +
> +   This location pointer can always be safely accessed using
> +   hurd_ihash_locp_value.  If the lookup is successful,
> +   hurd_ihash_locp_value will return the value related to KEY.
> +
> +   If the lookup is successful, the returned location can be used with
> +   hurd_ihash_locp_add to update the item, and with
> +   hurd_ihash_locp_remove to remove it.
> +
> +   If the lookup is not successful, the returned location can be used
> +   with hurd_ihash_locp_add to add the item.
> +
> +   Note that returned location is only valid until the next insertion
> +   or deletion.  */
> +hurd_ihash_locp_t hurd_ihash_locp_find (hurd_ihash_t ht,
> +                                        hurd_ihash_key_t key);
> +
> +/* Given an hash table bucket location LOCP, return the value stored
> +   there, or NULL if it is empty or LOCP is NULL.  */
> +static inline void *
> +hurd_ihash_locp_value (hurd_ihash_locp_t locp)
> +{
> +  struct _hurd_ihash_item *item = (struct _hurd_ihash_item *) locp;
> +
> +  if (item == NULL)
> +    return NULL;
> +
> +  if (hurd_ihash_value_valid (item->value))
> +    return item->value;
> +
> +  return NULL;
> +}
> +
>  /* Iterate over all elements in the hash table.  You use this macro
>     with a block, for example like this:
>  
> -- 
> 2.0.0.rc0
> 

-- 
Samuel
mdiym42: note to self
mdiym42: make sure your cat is not sleeping in the bass drum before you start 
playing them

Reply via email to