rcx

library of miscellaneous bits of C code
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

commit c011f3fb3c6bd74c63ebcf0084e7cb4c79cc5f3e
parent f24c14b23fd8acb7346e51470c82dab2ace6d447
Author: Robert Russell <robertrussell.72001@gmail.com>
Date:   Mon, 25 Sep 2023 23:09:40 -0700

Rework interface to table data structure

There are three main ways to use a generic data structure:
0. Fully privately, i.e., type defs, function decls, and function
   defs are all in a source file. For this, use static.h.
1. Mostly privately, i.e., type defs are in some header (so that
   they can be fields in structs as part of some API), but function
   decls and defs are in a source file. For this, use priv-hdr.h
   in the header and priv-src.h in the source file.
2. Publicly, i.e., type defs and function decls are in some header,
   but function defs are in a source file. For this, use pub-hdr.h
   in the header and pub-src.h in the source file.
All 5 of these files just include main.h after setting some flags,
so a user can also include main.h directly for more control.

Of course, the same changes need to be made to lists, dicts, and
sets (and deques will also use this interface once I change them
from the old generics implementation technique).

Diffstat:
MMakefile | 17++++++++++-------
Minc/dict/impl/table.h | 4++--
Minc/set/impl/table.h | 4++--
Dinc/table/declare.h | 13-------------
Dinc/table/define.h | 15---------------
Ainc/table/impl/clean.h | 24++++++++++++++++++++++++
Dinc/table/impl/declare.h | 43-------------------------------------------
Ainc/table/impl/decls.h | 20++++++++++++++++++++
Rinc/table/impl/define.h -> inc/table/impl/defs.h | 0
Dinc/table/impl/macro.h | 84-------------------------------------------------------------------------------
Ainc/table/impl/macros.h | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainc/table/impl/types.h | 16++++++++++++++++
Dinc/table/impl/unmacro.h | 20--------------------
Ainc/table/main.h | 28++++++++++++++++++++++++++++
Ainc/table/priv-hdr.h | 3+++
Ainc/table/priv-src.h | 4++++
Ainc/table/pub-hdr.h | 3+++
Ainc/table/pub-src.h | 2++
Minc/table/static.h | 23+++++------------------
Msrc/dict/impl/table.c | 4++--
Msrc/set/impl/table.c | 4++--
21 files changed, 215 insertions(+), 208 deletions(-)

diff --git a/Makefile b/Makefile @@ -27,14 +27,17 @@ TABLE_DEPS =\ inc/rand.h\ inc/simd.h\ inc/string.h\ - inc/table/declare.h\ - inc/table/define.h\ + inc/table/pub-hdr.h\ + inc/table/pub-src.h\ + inc/table/priv-hdr.h\ + inc/table/priv-src.h\ + inc/table/static.h\ + inc/table/impl/macros.h\ inc/table/impl/common.h\ - inc/table/impl/declare.h\ - inc/table/impl/define.h\ - inc/table/impl/macro.h\ - inc/table/impl/unmacro.h\ - inc/table/static.h + inc/table/impl/types.h\ + inc/table/impl/decls.h\ + inc/table/impl/defs.h\ + inc/table/impl/clean.h librcx.a: $(SRC:.c=.o) $(AR) -rcs $@ $(SRC:.c=.o) diff --git a/inc/dict/impl/table.h b/inc/dict/impl/table.h @@ -1,3 +1,3 @@ #define TABLE_SPEC_NAME RDictTableSpec #define TABLE_METHOD(name) r_dict_table_##name -#include "../../table/declare.h" -\ No newline at end of file +#include "../../table/pub-hdr.h" +\ No newline at end of file diff --git a/inc/set/impl/table.h b/inc/set/impl/table.h @@ -1,4 +1,4 @@ #define TABLE_VSIZE 0 #define TABLE_SPEC_NAME RSetTableSpec #define TABLE_METHOD(name) r_set_table_##name -#include "../../table/declare.h" -\ No newline at end of file +#include "../../table/pub-hdr.h" +\ No newline at end of file diff --git a/inc/table/declare.h b/inc/table/declare.h @@ -1,13 +0,0 @@ -#include <errno.h> -#include <stdbool.h> -#include <string.h> - -#include "../alloc.h" -#include "../def.h" -#include "../rand.h" -#include "../string.h" - -#include "impl/macro.h" -#include "impl/common.h" -#include "impl/declare.h" -#include "impl/unmacro.h" diff --git a/inc/table/define.h b/inc/table/define.h @@ -1,15 +0,0 @@ -#include <errno.h> -#include <stdbool.h> -#include <string.h> - -#include "../alloc.h" -#include "../bits.h" -#include "../debug.h" -#include "../def.h" -#include "../internal/util.h" -#include "../rand.h" -#include "../string.h" - -#include "impl/macro.h" -#include "impl/define.h" -#include "impl/unmacro.h" diff --git a/inc/table/impl/clean.h b/inc/table/impl/clean.h @@ -0,0 +1,24 @@ +#undef TABLE_LF_DEN +#undef TABLE_LF_NUM +#undef TABLE_PAGE_LEN +#undef TABLE_PAGE_LEN_BITS +#undef TABLE_METHOD +#undef TABLE_SPEC +#undef TABLE_SPEC_PARAM +#undef TABLE_SPEC_NAME +#undef TABLE_FREE_FIELD +#undef TABLE_FREE +#undef TABLE_ALLOCZ_FIELD +#undef TABLE_ALLOCZ +#undef TABLE_HASH_FIELD +#undef TABLE_HASH +#undef TABLE_EQ_FIELD +#undef TABLE_EQ +#undef TABLE_VSIZE_FIELD +#undef TABLE_VSIZE +#undef TABLE_KSIZE_FIELD +#undef TABLE_KSIZE +#undef TABLE_STATIC +#undef TABLE_DEFS +#undef TABLE_DECLS +#undef TABLE_TYPES diff --git a/inc/table/impl/declare.h b/inc/table/impl/declare.h @@ -1,43 +0,0 @@ -#ifdef TABLE_SPEC -/* The spec(ification) struct is for passing around settings specific to a - * table instantiation. Fields are omitted or included according to whether - * certain TABLE_... macros are assigned non-default values when a table is - * specialized; see macro.h for details. */ -/* TODO: Add PAGE_LEN and LF_{NUM,DEN} to the spec struct so that they are - * controllable at run-time? */ -typedef struct { - TABLE_KSIZE_FIELD - TABLE_VSIZE_FIELD - TABLE_EQ_FIELD - TABLE_HASH_FIELD - TABLE_ALLOCZ_FIELD - TABLE_FREE_FIELD -} TABLE_SPEC_NAME; -#endif - -/* TODO: Add methods for shrinking the table and reserving space? */ - -#ifndef TABLE_STATIC -#define TABLE_STATIC -#endif - -TABLE_STATIC UNUSED int TABLE_METHOD(init)(RTable *t, usize hint TABLE_SPEC_PARAM); -TABLE_STATIC UNUSED int TABLE_METHOD(acc)(RTable *t, void **v, void *k, u64 h TABLE_SPEC_PARAM); -TABLE_STATIC UNUSED int TABLE_METHOD(ins)(RTable *t, void **v, void *k, u64 h TABLE_SPEC_PARAM); -TABLE_STATIC UNUSED int TABLE_METHOD(del)(RTable *t, void **v, void *k, u64 h TABLE_SPEC_PARAM); -TABLE_STATIC UNUSED void TABLE_METHOD(clr)(RTable *t TABLE_SPEC_PARAM); - -#undef TABLE_STATIC - -static inline UNUSED void -TABLE_METHOD(free)(RTable *t TABLE_SPEC_PARAM) { - int e = errno; - TABLE_FREE(t->mem); - t->data = 0; /* Ensure hard error on use after free. */ - errno = e; -} - -static inline UNUSED usize -TABLE_METHOD(len)(RTable *t TABLE_SPEC_PARAM) { - return t->count; -} diff --git a/inc/table/impl/decls.h b/inc/table/impl/decls.h @@ -0,0 +1,20 @@ +/* TODO: Add methods for shrinking the table and reserving space? */ + +TABLE_STATIC UNUSED int TABLE_METHOD(init)(RTable *t, usize hint TABLE_SPEC_PARAM); +TABLE_STATIC UNUSED int TABLE_METHOD(acc)(RTable *t, void **v, void *k, u64 h TABLE_SPEC_PARAM); +TABLE_STATIC UNUSED int TABLE_METHOD(ins)(RTable *t, void **v, void *k, u64 h TABLE_SPEC_PARAM); +TABLE_STATIC UNUSED int TABLE_METHOD(del)(RTable *t, void **v, void *k, u64 h TABLE_SPEC_PARAM); +TABLE_STATIC UNUSED void TABLE_METHOD(clr)(RTable *t TABLE_SPEC_PARAM); + +static inline UNUSED void +TABLE_METHOD(free)(RTable *t TABLE_SPEC_PARAM) { + int e = errno; + TABLE_FREE(t->mem); + t->data = 0; /* Ensure hard error on use after free. */ + errno = e; +} + +static inline UNUSED usize +TABLE_METHOD(len)(RTable *t TABLE_SPEC_PARAM) { + return t->count; +} diff --git a/inc/table/impl/define.h b/inc/table/impl/defs.h diff --git a/inc/table/impl/macro.h b/inc/table/impl/macro.h @@ -1,84 +0,0 @@ -#ifndef TABLE_KSIZE -#define TABLE_KSIZE s_->ksize -#define TABLE_KSIZE_FIELD usize ksize; -#define TABLE_USE_SPEC -#else -#define TABLE_KSIZE_FIELD -#endif - -#ifndef TABLE_VSIZE -#define TABLE_VSIZE s_->vsize -#define TABLE_VSIZE_FIELD usize vsize; -#define TABLE_USE_SPEC -#else -#define TABLE_VSIZE_FIELD -#endif - -#ifndef TABLE_EQ -#define TABLE_EQ s_->eq -#define TABLE_EQ_FIELD RTableEqFunc eq; -#define TABLE_USE_SPEC -#else -#define TABLE_EQ_FIELD -#endif - -#ifndef TABLE_HASH -#define TABLE_HASH s_->hash -#define TABLE_HASH_FIELD RTableHashFunc hash; -#define TABLE_USE_SPEC -#else -#define TABLE_HASH_FIELD -#endif - -#ifndef TABLE_ALLOCZ -#define TABLE_ALLOCZ s_->allocz -#define TABLE_ALLOCZ_FIELD RTableAlloczFunc allocz; -#define TABLE_USE_SPEC -#else -#define TABLE_ALLOCZ_FIELD -#endif - -#ifndef TABLE_FREE -#define TABLE_FREE s_->free -#define TABLE_FREE_FIELD RTableFreeFunc free; -#define TABLE_USE_SPEC -#else -#define TABLE_FREE_FIELD -#endif - -#ifdef TABLE_USE_SPEC -#ifndef TABLE_SPEC_NAME -#error "rcx/table: TABLE_SPEC_NAME must be defined" -#endif -#define TABLE_SPEC_PARAM , TABLE_SPEC_NAME *s_ -#define TABLE_SPEC , s_ -#undef TABLE_USE_SPEC -#endif - -#ifndef TABLE_METHOD -#define TABLE_METHOD(name) name -#endif - -/* PAGE_LEN_BITS should be chosen such that PAGE_LEN * KSIZE and - * PAGE_LEN * VSIZE are both divisible by alignof(K) and by alignof(V). - * The default basically guarantees this on 64 bit machines, but one might - * experience improved caching performance for large keys or values by - * decreasing PAGE_LEN (because lower PAGE_LEN causes corresponding keys and - * values to be closer in memory). See define.h for more details. */ - -#ifndef TABLE_PAGE_LEN_BITS -#define TABLE_PAGE_LEN_BITS 3u -#endif - -#define TABLE_PAGE_LEN (1u << (TABLE_PAGE_LEN_BITS)) - -/* The dict size doubles when count + ntombs exceeds the proportion of the - * dict size indicated by LF_NUM and LF_DEN. See exceeds_lf in define.h. */ - -#ifndef TABLE_LF_NUM -#define TABLE_LF_NUM 3u -#endif - -#ifndef TABLE_LF_DEN -#define TABLE_LF_DEN 4u -#endif diff --git a/inc/table/impl/macros.h b/inc/table/impl/macros.h @@ -0,0 +1,92 @@ +#ifdef TABLE_STATIC +#undef TABLE_STATIC +#define TABLE_STATIC static +#else +#define TABLE_STATIC +#endif + +#ifndef TABLE_KSIZE +#define TABLE_KSIZE r_spec_->ksize +#define TABLE_KSIZE_FIELD usize ksize; +#define TABLE_USE_SPEC +#else +#define TABLE_KSIZE_FIELD +#endif + +#ifndef TABLE_VSIZE +#define TABLE_VSIZE r_spec_->vsize +#define TABLE_VSIZE_FIELD usize vsize; +#define TABLE_USE_SPEC +#else +#define TABLE_VSIZE_FIELD +#endif + +#ifndef TABLE_EQ +#define TABLE_EQ r_spec_->eq +#define TABLE_EQ_FIELD RTableEqFunc eq; +#define TABLE_USE_SPEC +#else +#define TABLE_EQ_FIELD +#endif + +#ifndef TABLE_HASH +#define TABLE_HASH r_spec_->hash +#define TABLE_HASH_FIELD RTableHashFunc hash; +#define TABLE_USE_SPEC +#else +#define TABLE_HASH_FIELD +#endif + +#ifndef TABLE_ALLOCZ +#define TABLE_ALLOCZ r_spec_->allocz +#define TABLE_ALLOCZ_FIELD RTableAlloczFunc allocz; +#define TABLE_USE_SPEC +#else +#define TABLE_ALLOCZ_FIELD +#endif + +#ifndef TABLE_FREE +#define TABLE_FREE r_spec_->free +#define TABLE_FREE_FIELD RTableFreeFunc free; +#define TABLE_USE_SPEC +#else +#define TABLE_FREE_FIELD +#endif + +#ifdef TABLE_USE_SPEC +#ifndef TABLE_SPEC_NAME +#error "rcx/table: TABLE_SPEC_NAME must be defined" +#endif +#define TABLE_SPEC_PARAM , TABLE_SPEC_NAME *r_spec_ +#define TABLE_SPEC , r_spec_ +#undef TABLE_USE_SPEC +#endif + +#ifndef TABLE_METHOD +#define TABLE_METHOD(name) name +#endif + +/* PAGE_LEN_BITS should be chosen such that PAGE_LEN * KSIZE and + * PAGE_LEN * VSIZE are both divisible by alignof(K) and by alignof(V). + * The default basically guarantees this on 64 bit machines, but one might + * experience improved caching performance for large keys or values by + * decreasing PAGE_LEN (because lower PAGE_LEN causes corresponding keys and + * values to be closer in memory). See defs.h for more details. */ + +#ifndef TABLE_PAGE_LEN_BITS +#define TABLE_PAGE_LEN_BITS 3u +#endif + +#define TABLE_PAGE_LEN (1u << (TABLE_PAGE_LEN_BITS)) + +/* The dict size doubles when count + ntombs exceeds the proportion of the + * dict size indicated by LF_NUM and LF_DEN (which is 3/4 = 75% by default). + * See exceeds_lf in defs.h. */ + +#ifndef TABLE_LF_NUM +#define TABLE_LF_NUM 3u +#endif + +#ifndef TABLE_LF_DEN +#define TABLE_LF_DEN 4u +#endif diff --git a/inc/table/impl/types.h b/inc/table/impl/types.h @@ -0,0 +1,16 @@ +#ifdef TABLE_SPEC +/* The spec(ification) struct is for passing around settings specific to a + * table instantiation. Fields are omitted or included according to whether + * certain TABLE_... macros are assigned non-default values when a table is + * specialized; see macros.h for details. */ +/* TODO: Add PAGE_LEN and LF_{NUM,DEN} to the spec struct so that they are + * optionally controllable at run-time? */ +typedef struct { + TABLE_KSIZE_FIELD + TABLE_VSIZE_FIELD + TABLE_EQ_FIELD + TABLE_HASH_FIELD + TABLE_ALLOCZ_FIELD + TABLE_FREE_FIELD +} TABLE_SPEC_NAME; +#endif diff --git a/inc/table/impl/unmacro.h b/inc/table/impl/unmacro.h @@ -1,20 +0,0 @@ -#undef TABLE_LF_DEN -#undef TABLE_LF_NUM -#undef TABLE_PAGE_LEN -#undef TABLE_PAGE_LEN_BITS -#undef TABLE_METHOD -#undef TABLE_SPEC -#undef TABLE_SPEC_PARAM -#undef TABLE_SPEC_NAME -#undef TABLE_FREE_FIELD -#undef TABLE_FREE -#undef TABLE_ALLOCZ_FIELD -#undef TABLE_ALLOCZ -#undef TABLE_HASH_FIELD -#undef TABLE_HASH -#undef TABLE_EQ_FIELD -#undef TABLE_EQ -#undef TABLE_VSIZE_FIELD -#undef TABLE_VSIZE -#undef TABLE_KSIZE_FIELD -#undef TABLE_KSIZE diff --git a/inc/table/main.h b/inc/table/main.h @@ -0,0 +1,28 @@ +#include <stdbool.h> +#include <string.h> +#if defined(TABLE_DECLS) || defined(TABLE_DEFS) +#include <errno.h> +#endif + +#include "../alloc.h" +#include "../def.h" +#include "../rand.h" +#include "../string.h" +#ifdef TABLE_DEFS +#include "../bits.h" +#include "../debug.h" +#include "../internal/util.h" +#endif + +#include "impl/macros.h" +#include "impl/common.h" +#ifdef TABLE_TYPES +#include "impl/types.h" +#endif +#ifdef TABLE_DECLS +#include "impl/decls.h" +#endif +#ifdef TABLE_DEFS +#include "impl/defs.h" +#endif +#include "impl/clean.h" diff --git a/inc/table/priv-hdr.h b/inc/table/priv-hdr.h @@ -0,0 +1,3 @@ +#define TABLE_TYPES +#define TABLE_STATIC +#include "main.h" diff --git a/inc/table/priv-src.h b/inc/table/priv-src.h @@ -0,0 +1,4 @@ +#define TABLE_DECLS +#define TABLE_DEFS +#define TABLE_STATIC +#include "main.h" diff --git a/inc/table/pub-hdr.h b/inc/table/pub-hdr.h @@ -0,0 +1,3 @@ +#define TABLE_TYPES +#define TABLE_DECLS +#include "main.h" diff --git a/inc/table/pub-src.h b/inc/table/pub-src.h @@ -0,0 +1,2 @@ +#define TABLE_DEFS +#include "main.h" diff --git a/inc/table/static.h b/inc/table/static.h @@ -1,18 +1,5 @@ -#include <errno.h> -#include <stdbool.h> -#include <string.h> - -#include "../alloc.h" -#include "../bits.h" -#include "../debug.h" -#include "../def.h" -#include "../internal/util.h" -#include "../rand.h" -#include "../string.h" - -#include "impl/macro.h" -#include "impl/common.h" -#define TABLE_STATIC static -#include "impl/declare.h" -#include "impl/define.h" -#include "impl/unmacro.h" +#define TABLE_TYPES +#define TABLE_DECLS +#define TABLE_DEFS +#define TABLE_STATIC +#include "main.h" diff --git a/src/dict/impl/table.c b/src/dict/impl/table.c @@ -2,4 +2,4 @@ #define TABLE_SPEC_NAME RDictTableSpec #define TABLE_METHOD(name) r_dict_table_##name -#include "table/define.h" -\ No newline at end of file +#include "table/pub-src.h" +\ No newline at end of file diff --git a/src/set/impl/table.c b/src/set/impl/table.c @@ -3,4 +3,4 @@ #define TABLE_VSIZE 0 #define TABLE_SPEC_NAME RSetTableSpec #define TABLE_METHOD(name) r_set_table_##name -#include "table/define.h" -\ No newline at end of file +#include "table/pub-src.h" +\ No newline at end of file