[systemd-devel] [PATCH 21/26] hashmap: rewrite the implementation

Lennart Poettering lennart at poettering.net
Mon Oct 20 11:42:24 PDT 2014


On Thu, 16.10.14 09:50, Michal Schmidt (mschmidt at redhat.com) wrote:

> +/* Distance from Initial Bucket */
> +typedef uint8_t dib_raw_t;
> +#define DIB_RAW_OVERFLOW ((dib_raw_t)0xfdU) /* indicates DIB value is greater than representable */
> +#define DIB_RAW_REHASH   ((dib_raw_t)0xfeU) /* entry yet to be rehashed during in-place resize */
> +#define DIB_RAW_FREE     ((dib_raw_t)0xffU) /* a free bucket */
> +#define DIB_RAW_INIT   ((char)DIB_RAW_FREE) /* a byte to memset a
> DIB store with when initializing */

Not sure I am a fan of typedeffing things like this if we only use it
internally, but doesn't matter really...

> +enum {
> +        HASHMAP_TYPE_PLAIN,
> +        HASHMAP_TYPE_LINKED,
> +        HASHMAP_TYPE_SET,
> +        __HASHMAP_TYPE_COUNT
> +};

Why is this enum anonymous? Wouldn't it be nicer to give it a name? We
only use it internally only anyway...

So far we called the final counting entry of such enums _FOOBAR_MAX,
not __FOOBAR_COUNT, please stick to this naming scheme... (also iirc
the C standard reserves the double "_" prefix for the language
itself. The kernel ignores that C standard issue so far, but we should
probably honour it.

> +/* Fields that all hashmap/set types must have */
> +struct HashmapBase {
> +        const struct hash_ops *hash_ops;  /* hash and compare ops to use */
> +
> +        union _packed_ {
> +                struct indirect_storage indirect; /* if  has_indirect */
> +                struct direct_storage direct;     /* if !has_indirect */
> +        };
> +
> +        uint8_t type:2;             /* HASHMAP_TYPE_* */

Should probably be a named enum (see above)

> +        uint8_t has_indirect:1;     /* whether indirect storage is
> used */

Should really be a "bool", no?

>  
> -int hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops) {
> -        Hashmap *q;
> +static void __remove_entry(HashmapBase *h, unsigned idx) {
> +        unsigned left, right, prev, dib;
> +        dib_raw_t raw_dib, *dibs;

Don't like the double __ prefix for fucntions here either...

> +static struct HashmapBase *__hashmap_new(const struct hash_ops *hash_ops, uint8_t type  HASHMAP_DEBUG_PARAMS) {
> +        HashmapBase *h;
> +
> +        h = malloc0(all_hashmap_sizes[type]);
> +        if (!h)
> +                return NULL;
> +

Hmm, a malloc() for each hashmap we allocate? Isn#t that prohibitively
expensive given how slow malloc() is? We have soo many hashmaps!

> +        h->type = type;
> +        h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
> +
> +        if (type == HASHMAP_TYPE_LINKED) {
> +                LinkedHashmap *lh = (LinkedHashmap*)h;
> +                lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
> +        }
> +
> +        reset_direct_storage(h);
> +
> +        if (!shared_hash_key_initialized) {
> +                random_bytes(shared_hash_key, sizeof(shared_hash_key));
> +                shared_hash_key_initialized= true;
> +        }
> +
> +#ifdef ENABLE_HASHMAP_DEBUG
> +        LIST_PREPEND(debug_list, hashmap_debug_list, &h->debug);
> +        h->debug.func = func;
> +        h->debug.file = file;
> +        h->debug.line = line;
> +#endif
> +
> +        return h;
> +}
> +
> +Hashmap *_hashmap_new(const struct hash_ops *hash_ops  HASHMAP_DEBUG_PARAMS) {
> +        return (Hashmap*)       __hashmap_new(hash_ops, HASHMAP_TYPE_PLAIN  HASHMAP_DEBUG_PASS_ARGS);
> +}
> +
> +LinkedHashmap *_linked_hashmap_new(const struct hash_ops *hash_ops  HASHMAP_DEBUG_PARAMS) {
> +        return (LinkedHashmap*) __hashmap_new(hash_ops, HASHMAP_TYPE_LINKED  HASHMAP_DEBUG_PASS_ARGS);
> +}
> +
> +Set *_set_new(const struct hash_ops *hash_ops  HASHMAP_DEBUG_PARAMS) {
> +        return (Set*)           __hashmap_new(hash_ops, HASHMAP_TYPE_SET  HASHMAP_DEBUG_PASS_ARGS);
> +}

Not liking the double underscores... I know this is kernel style, but it's still in conflict with ISO C...

Can we maybe name this internal_xyz or so?

Beyond these superficialities I have nothing to complain. Didn't test
it though. But I trust you...

Lennart

-- 
Lennart Poettering, Red Hat


More information about the systemd-devel mailing list