Data-HashMap

 view release on metacpan or  search on metacpan

hashmap_generic.h  view on Meta::CPAN

/*
 * hashmap_generic.h — macro template for the type-specialized maps.
 * Each hashmap_<variant>.h defines these before including it:
 *   HM_PREFIX / HM_NODE_TYPE / HM_MAP_TYPE    names
 *   HM_KEY_IS_INT                             integer keys, else string
 *   HM_VALUE_IS_STR | HM_VALUE_IS_SV          value kind, else integer
 *   HM_INT_TYPE / HM_INT_MIN / HM_INT_MAX     key width (default int64_t)
 *   HM_HAS_COUNTERS                           incr/decr (int values only)
 */

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* ---- Macro helpers ---- */

#define HM_PASTE2(a, b)  a##_##b
#define HM_PASTE(a, b)   HM_PASTE2(a, b)
#define HM_FN(name)      HM_PASTE(HM_PREFIX, name)

/* ---- Integer type defaults ---- */

#ifndef HM_INT_TYPE
#define HM_INT_TYPE  int64_t
#define HM_INT_MIN   INT64_MIN
#define HM_INT_MAX   INT64_MAX
#endif

/* ---- Branch prediction ---- */

#ifndef HM_LIKELY
#if defined(__GNUC__) || defined(__clang__)
#define HM_LIKELY(x)   __builtin_expect(!!(x), 1)
#define HM_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define HM_LIKELY(x)   (x)
#define HM_UNLIKELY(x) (x)
#endif
#endif

/* ---- TTL timestamp helper ---- */

/* Saturates; 0 is the no-expiry sentinel, so an exact 0 becomes 1. */
#ifndef HM_EXPIRY_AT_DEFINED
#define HM_EXPIRY_AT_DEFINED
static inline uint32_t hm_expiry_at(uint32_t ttl) {
    uint32_t now = (uint32_t)time(NULL);
    uint32_t e = now + ttl;
    if (e < now) e = UINT32_MAX;
    return e ? e : 1;
}
#endif

/* If idx has expired, expires it and returns false from the enclosing function. */
#ifndef HM_TTL_CHECK_EXPIRED_DEFINED
#define HM_TTL_CHECK_EXPIRED_DEFINED
#define HM_TTL_CHECK_EXPIRED(map, idx, may_compact) do { \
    if (HM_UNLIKELY((map)->expires_at && (map)->expires_at[idx]) && \
        (uint32_t)time(NULL) > (map)->expires_at[idx]) { \
        HM_FN(expire_at)((map), (idx), (may_compact)); \
        return false; \
    } \
} while (0)
#endif

#ifndef HM_MAYBE_COMPACT_DEFINED
#define HM_MAYBE_COMPACT_DEFINED
#define HM_MAYBE_COMPACT(map) do { \
    if ((map)->tombstones > (map)->capacity / 4 || \
        ((map)->size > 0 && (map)->tombstones > (map)->size && \
         (map)->tombstones > (map)->capacity / 8)) \
        HM_FN(compact)(map); \
} while (0)
#endif



( run in 1.465 second using v1.01-cache-2.11-cpan-1236ad508bc )