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 )