v13-0002-Make-simplehash-easy-to-use-in-shmem.patch
application/x-patch
Filename: v13-0002-Make-simplehash-easy-to-use-in-shmem.patch
Type: application/x-patch
Part: 1
Patch
Format: format-patch
Series: patch v13-0002
Subject: Make simplehash easy to use in shmem.
| File | + | − |
|---|---|---|
| src/include/lib/simplehash.h | 52 | 4 |
From 3441027b9ac2f135dea7ec155503be9d6331dfc1 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 27 Mar 2021 08:34:58 +1300
Subject: [PATCH v13 2/5] Make simplehash easy to use in shmem.
Allow "in-place" creation of a simplehash hash table of fixed size,
suitable for use in shared memory. No calling out to allocators, and no
ability to grow.
---
src/include/lib/simplehash.h | 56 +++++++++++++++++++++++++++++++++---
1 file changed, 52 insertions(+), 4 deletions(-)
diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h
index 395be1ca9a..32d3fa58fe 100644
--- a/src/include/lib/simplehash.h
+++ b/src/include/lib/simplehash.h
@@ -120,6 +120,7 @@
#define SH_ALLOCATE SH_MAKE_NAME(allocate)
#define SH_FREE SH_MAKE_NAME(free)
#define SH_STAT SH_MAKE_NAME(stat)
+#define SH_ESTIMATE_SIZE SH_MAKE_NAME(estimate_size)
/* internal helper functions (no externally visible prototypes) */
#define SH_COMPUTE_PARAMETERS SH_MAKE_NAME(compute_parameters)
@@ -153,16 +154,22 @@ typedef struct SH_TYPE
/* boundary after which to grow hashtable */
uint32 grow_threshold;
+#ifndef SH_IN_PLACE
/* hash buckets */
SH_ELEMENT_TYPE *data;
+#endif
-#ifndef SH_RAW_ALLOCATOR
+#if !defined(SH_RAW_ALLOCATOR) && !defined(SH_IN_PLACE)
/* memory context to use for allocations */
MemoryContext ctx;
#endif
/* user defined data, useful for callbacks */
void *private_data;
+
+#ifdef SH_IN_PLACE
+ SH_ELEMENT_TYPE data[FLEXIBLE_ARRAY_MEMBER];
+#endif
} SH_TYPE;
typedef enum SH_STATUS
@@ -182,6 +189,11 @@ typedef struct SH_ITERATOR
#ifdef SH_RAW_ALLOCATOR
/* <prefix>_hash <prefix>_create(uint32 nelements, void *private_data) */
SH_SCOPE SH_TYPE *SH_CREATE(uint32 nelements, void *private_data);
+#elif defined(SH_IN_PLACE)
+/* size_t <prefix>_estimate_size(uint32 nelements) */
+SH_SCOPE size_t SH_ESTIMATE_SIZE(uint32 nelements);
+/* void <prefix>_create(<prefix>_hash *place, uint32 nelements, void *private_data) */
+SH_SCOPE void SH_CREATE(SH_TYPE *place, uint32 nelements, void *private_data);
#else
/*
* <prefix>_hash <prefix>_create(MemoryContext ctx, uint32 nelements,
@@ -191,14 +203,18 @@ SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements,
void *private_data);
#endif
+#ifndef SH_IN_PLACE
/* void <prefix>_destroy(<prefix>_hash *tb) */
SH_SCOPE void SH_DESTROY(SH_TYPE * tb);
+#endif
/* void <prefix>_reset(<prefix>_hash *tb) */
SH_SCOPE void SH_RESET(SH_TYPE * tb);
+#ifndef SH_IN_PLACE
/* void <prefix>_grow(<prefix>_hash *tb) */
SH_SCOPE void SH_GROW(SH_TYPE * tb, uint32 newsize);
+#endif
/* <element> *<prefix>_insert(<prefix>_hash *tb, <key> key, bool *found) */
SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE * tb, SH_KEY_TYPE key, bool *found);
@@ -241,7 +257,7 @@ SH_SCOPE void SH_STAT(SH_TYPE * tb);
/* generate implementation of the hash table */
#ifdef SH_DEFINE
-#ifndef SH_RAW_ALLOCATOR
+#if !defined(SH_RAW_ALLOCATOR) && !defined(SH_IN_PLACE)
#include "utils/memutils.h"
#endif
@@ -383,11 +399,13 @@ SH_ENTRY_HASH(SH_TYPE * tb, SH_ELEMENT_TYPE * entry)
#endif
}
+#ifndef SH_IN_PLACE
/* default memory allocator function */
static inline void *SH_ALLOCATE(SH_TYPE * type, Size size);
static inline void SH_FREE(SH_TYPE * type, void *pointer);
+#endif
-#ifndef SH_USE_NONDEFAULT_ALLOCATOR
+#if !defined(SH_USE_NONDEFAULT_ALLOCATOR) && !defined(SH_IN_PLACE)
/* default memory allocator function */
static inline void *
@@ -410,6 +428,22 @@ SH_FREE(SH_TYPE * type, void *pointer)
#endif
+#ifdef SH_IN_PLACE
+/*
+ * Compute the amount of memory required for a fixed sized in-place hash table.
+ */
+SH_SCOPE size_t
+SH_ESTIMATE_SIZE(uint32 nelements)
+{
+ size_t size;
+
+ size = Max(nelements, 2);
+ size = pg_nextpower2_64(size);
+
+ return offsetof(SH_TYPE, data) + sizeof(SH_ELEMENT_TYPE) * size;
+}
+#endif
+
/*
* Create a hash table with enough space for `nelements` distinct members.
* Memory for the hash table is allocated from the passed-in context. If
@@ -422,6 +456,9 @@ SH_FREE(SH_TYPE * type, void *pointer)
#ifdef SH_RAW_ALLOCATOR
SH_SCOPE SH_TYPE *
SH_CREATE(uint32 nelements, void *private_data)
+#elif defined(SH_IN_PLACE)
+SH_SCOPE void
+SH_CREATE(SH_TYPE *place, uint32 nelements, void *private_data)
#else
SH_SCOPE SH_TYPE *
SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data)
@@ -432,6 +469,8 @@ SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data)
#ifdef SH_RAW_ALLOCATOR
tb = SH_RAW_ALLOCATOR(sizeof(SH_TYPE));
+#elif defined(SH_IN_PLACE)
+ tb = place;
#else
tb = MemoryContextAllocZero(ctx, sizeof(SH_TYPE));
tb->ctx = ctx;
@@ -443,11 +482,15 @@ SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data)
SH_COMPUTE_PARAMETERS(tb, size);
+#if defined(SH_IN_PLACE)
+ memset(&tb->data, 0, sizeof(SH_ELEMENT_TYPE) * tb->size);
+#else
tb->data = SH_ALLOCATE(tb, sizeof(SH_ELEMENT_TYPE) * tb->size);
-
return tb;
+#endif
}
+#ifndef SH_IN_PLACE
/* destroy a previously created hash table */
SH_SCOPE void
SH_DESTROY(SH_TYPE * tb)
@@ -455,6 +498,7 @@ SH_DESTROY(SH_TYPE * tb)
SH_FREE(tb, tb->data);
pfree(tb);
}
+#endif
/* reset the contents of a previously created hash table */
SH_SCOPE void
@@ -464,6 +508,7 @@ SH_RESET(SH_TYPE * tb)
tb->members = 0;
}
+#ifndef SH_IN_PLACE
/*
* Grow a hash table to at least `newsize` buckets.
*
@@ -576,6 +621,7 @@ SH_GROW(SH_TYPE * tb, uint32 newsize)
SH_FREE(tb, olddata);
}
+#endif
/*
* This is a separate static inline function, so it can be reliably be inlined
@@ -592,6 +638,7 @@ SH_INSERT_HASH_INTERNAL(SH_TYPE * tb, SH_KEY_TYPE key, uint32 hash, bool *found)
restart:
insertdist = 0;
+#ifndef SH_IN_PLACE
/*
* We do the grow check even if the key is actually present, to avoid
* doing the check inside the loop. This also lets us avoid having to
@@ -614,6 +661,7 @@ restart:
SH_GROW(tb, tb->size * 2);
/* SH_STAT(tb); */
}
+#endif
/* perform insert, start bucket search at optimal location */
data = tb->data;
--
2.30.1