Repository: valkey-io/valkey
File: src/hashtable.c (C)

Code before:
/* Number of top-level buckets. */
static inline size_t numBuckets(int exp) {
    return exp == -1 ? 0 : (size_t)1 << exp;
}

/* Bitmask for masking the hash value to get bucket index. */
static inline size_t expToMask(int exp) {
    return exp == -1 ? 0 : numBuckets(exp) - 1;
}

/* Returns the 'exp', where num_buckets = 1 << exp. The number of
 * buckets is a power of two. */
static signed char nextBucketExp(size_t min_capacity) {
    if (min_capacity == 0) return -1;
    /* ceil(x / y) = floor((x - 1) / y) + 1 */
    size_t min_buckets = (min_capacity * BUCKET_FACTOR - 1) / BUCKET_DIVISOR + 1;
    if (min_buckets >= SIZE_MAX / 2) return CHAR_BIT * sizeof(size_t) - 1;
    if (min_buckets == 1) return 0;
    return CHAR_BIT * sizeof(size_t) - __builtin_clzl(min_buckets - 1);
}

#define SWAP(a, b, type) do { \
    type temp = (a); \
    (a) = (b); \
    (b) = temp; \
} while(0)

/* This function swaps ht[0] and ht[1] in the hashtable. */
static void swapTables(hashtable *ht) {
    assert(hashtableIsRehashing(ht));

    SWAP(ht->tables[0], ht->tables[1], bucket *);
    SWAP(ht->used[0], ht->used[1], size_t);
    SWAP(ht->bucket_exp[0], ht->bucket_exp[1], int8_t);
    SWAP(ht->child_buckets[0], ht->child_buckets[1], size_t);
}

/* Swaps the tables and frees the old table. */
static void rehashingCompleted(hashtable *ht) {
    if (ht->type->rehashingCompleted) ht->type->rehashingCompleted(ht);
    if (ht->tables[0]) {
        zfree(ht->tables[0]);
        if (ht->type->trackMemUsage) {
            ht->type->trackMemUsage(ht, -sizeof(bucket) * numBuckets(ht->bucket_exp[0]));
        }
    }

    swapTables(ht);
    resetTable(ht, 1);
    ht->rehash_idx = -1;
}

Review comment (suggestion):
Clang-format wants it like this.

```suggestion
#define SWAP(a, b, type) \
    do {                 \
        type temp = (a); \
        (a) = (b);       \
        (b) = temp;      \
    } while (0)
```

Code after:
/* Number of top-level buckets. */
static inline size_t numBuckets(int exp) {
    return exp == -1 ? 0 : (size_t)1 << exp;
}

/* Bitmask for masking the hash value to get bucket index. */
static inline size_t expToMask(int exp) {
    return exp == -1 ? 0 : numBuckets(exp) - 1;
}

/* Returns the 'exp', where num_buckets = 1 << exp. The number of
 * buckets is a power of two. */
static signed char nextBucketExp(size_t min_capacity) {
    if (min_capacity == 0) return -1;
    /* ceil(x / y) = floor((x - 1) / y) + 1 */
    size_t min_buckets = (min_capacity * BUCKET_FACTOR - 1) / BUCKET_DIVISOR + 1;
    if (min_buckets >= SIZE_MAX / 2) return CHAR_BIT * sizeof(size_t) - 1;
    if (min_buckets == 1) return 0;
    return CHAR_BIT * sizeof(size_t) - __builtin_clzl(min_buckets - 1);
}

#define SWAP(a, b, type) \
    do {                 \
        type temp = (a); \
        (a) = (b);       \
        (b) = temp;      \
    } while (0)

/* This function swaps ht[0] and ht[1] in the hashtable. */
static void swapTables(hashtable *ht) {
    assert(hashtableIsRehashing(ht));

    SWAP(ht->tables[0], ht->tables[1], bucket *);
    SWAP(ht->used[0], ht->used[1], size_t);
    SWAP(ht->bucket_exp[0], ht->bucket_exp[1], int8_t);
    SWAP(ht->child_buckets[0], ht->child_buckets[1], size_t);
}

/* Swaps the tables and frees the old table. */
static void rehashingCompleted(hashtable *ht) {
    if (ht->type->rehashingCompleted) ht->type->rehashingCompleted(ht);
    if (ht->tables[0]) {
        zfree(ht->tables[0]);
        if (ht->type->trackMemUsage) {
            ht->type->trackMemUsage(ht, -sizeof(bucket) * numBuckets(ht->bucket_exp[0]));
        }
    }

    swapTables(ht);
    resetTable(ht, 1);
    ht->rehash_idx = -1;