Raoul722
Raoul722

Reputation: 1264

Full macro in header file

I found a header to define hashtable with the following code :

#ifndef HASH_H
#define HASH_H

#define DEFINE_HASHTABLE(name, type, key, h_list, hashfunc)\
\
struct list * hashtable;\
\
static int hashtable_init (size_t size)\
{\
    unsigned long i;\
    hashtable = (struct list*)malloc(size * sizeof (struct list_head));\
    if (!hashtable)\
        return -1;\
    for (i = 0; i < size; i++)\
        INIT_LIST_HEAD(&hashtable[i]);\
    return 0;\
}\
\
static inline void hashtable_add(type *elem)\
{\
    struct list_head *head = hashtable + hashfunc(elem->key);\
    list_add(&elem->h_list, head);\
}\
\
static inline void hashtable_del(type *elem)\
{\
    list_del(&elem->h_list);\
}\
\
static inline type * hashtable_find(unsigned long key)\
{\
    type *elem;\
    struct list_head *head = hashtable + hashfunc(key);\
\
    list_for_each_entry(elem, head, h_list){\
        if (elem->key == key) \
            return elem; \
    }\
    return NULL;\
}

#endif /* _HASH_H */

I never seen a header file such this one. What is the advantage of this way to write a header (I mean full macro)? Is it about genericity or things like that?

Upvotes: 1

Views: 94

Answers (1)

unwind
unwind

Reputation: 399803

It's a way to try to ensure that all the hash function calls have their inline request granted, i.e. to reduce the number of function calls when doing hash table operations.

It's just an attempt, it can't guarantee that the functions will be inlined, but by making them static the chance at least improves. See this question for lots of discussion about this, in particular @Christoph's answer here.

Note that it will only work once per C file, since there's no "unique" part added to the function names.

If you do:

#include "hash.h"

DEFINE_HASHTABLE(foo, /* rest of arguments */);
DEFINE_HASHTABLE(bar, /* another bunch of args */);

you will get compilation errors, since all the hashtable_ functions will be defined twice. The macro writer could improve this by adding the name to all the things defined (variables and functions) by the set of macros.

I.e. this:

struct list * hashtable;\
\
static int hashtable_init (size_t size)\

should become something like:

static list *hashtable_ ##name;\
\
static int hashtable_ ##name ##_init(size_t size)\

and so on (where name is the first macro argument, i.e. the foo and bar from my example usage above).

Upvotes: 2

Related Questions