X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FLexical-Types.git;a=blobdiff_plain;f=ptable.h;h=4a6fe4da13c13f3a5b4054cabf6381fece4c505e;hp=5cd5a90f374e3b43c389e14abe5ef2b4df950862;hb=bc16ea8dc7913595c3d1379136877fa6f7e7af2f;hpb=99eb2ccae4e9aee5fa8996755211028b9934722b diff --git a/ptable.h b/ptable.h index 5cd5a90..4a6fe4d 100644 --- a/ptable.h +++ b/ptable.h @@ -1,4 +1,4 @@ -/* This file is part of the Lexical-Types Perl module. +/* This file is part of the Lexical::Types Perl module. * See http://search.cpan.org/dist/Lexical-Types/ */ /* This is a pointer table implementation essentially copied from the ptr_table @@ -6,34 +6,107 @@ * shared across threads. * Copyright goes to the original authors, bug reports to me. */ +/* This header is designed to be included several times with different + * definitions for PTABLE_NAME and PTABLE_VAL_FREE(). */ + +#undef VOID2 +#ifdef __cplusplus +# define VOID2(T, P) static_cast(P) +#else +# define VOID2(T, P) (P) +#endif + +#undef pPTBLMS +#undef pPTBLMS_ +#undef aPTBLMS +#undef aPTBLMS_ + +/* Context for PerlMemShared_* functions */ + +#ifdef PERL_IMPLICIT_SYS +# define pPTBLMS pTHX +# define pPTBLMS_ pTHX_ +# define aPTBLMS aTHX +# define aPTBLMS_ aTHX_ +#else +# define pPTBLMS void +# define pPTBLMS_ +# define aPTBLMS +# define aPTBLMS_ +#endif + +#ifndef pPTBL +# define pPTBL pPTBLMS +#endif +#ifndef pPTBL_ +# define pPTBL_ pPTBLMS_ +#endif +#ifndef aPTBL +# define aPTBL aPTBLMS +#endif +#ifndef aPTBL_ +# define aPTBL_ aPTBLMS_ +#endif + +#ifndef PTABLE_NAME +# define PTABLE_NAME ptable +#endif + +#ifndef PTABLE_JOIN +# define PTABLE_PASTE(A, B) A ## B +# define PTABLE_JOIN(A, B) PTABLE_PASTE(A, B) +#endif + +#ifndef PTABLE_PREFIX +# define PTABLE_PREFIX(X) PTABLE_JOIN(PTABLE_NAME, X) +#endif + +#ifndef PTABLE_NEED_DELETE +# define PTABLE_NEED_DELETE 1 +#endif + +#ifndef PTABLE_NEED_WALK +# define PTABLE_NEED_WALK 1 +#endif + +#ifndef ptable_ent typedef struct ptable_ent { struct ptable_ent *next; const void * key; void * val; } ptable_ent; +#define ptable_ent ptable_ent +#endif /* !ptable_ent */ +#ifndef ptable typedef struct ptable { ptable_ent **ary; - UV max; - UV items; + size_t max; + size_t items; } ptable; +#define ptable ptable +#endif /* !ptable */ -#ifndef PTABLE_VAL_FREE -# define PTABLE_VAL_FREE(V) -#endif - -STATIC ptable *ptable_new(void) { - ptable *t = PerlMemShared_malloc(sizeof *t); - t->max = 127; - t->items = 0; - t->ary = PerlMemShared_calloc(t->max + 1, sizeof *t->ary); +#ifndef ptable_new +static ptable *ptable_new(pPTBLMS) { +#define ptable_new() ptable_new(aPTBLMS) + ptable *t = VOID2(ptable *, PerlMemShared_malloc(sizeof *t)); + t->max = 15; + t->items = 0; + t->ary = VOID2(ptable_ent **, + PerlMemShared_calloc(t->max + 1, sizeof *t->ary)); return t; } +#endif /* !ptable_new */ -#define PTABLE_HASH(ptr) \ - ((PTR2UV(ptr) >> 3) ^ (PTR2UV(ptr) >> (3 + 7)) ^ (PTR2UV(ptr) >> (3 + 17))) +#ifndef PTABLE_HASH +# define PTABLE_HASH(ptr) \ + ((PTR2UV(ptr) >> 3) ^ (PTR2UV(ptr) >> (3 + 7)) ^ (PTR2UV(ptr) >> (3 + 17))) +#endif -STATIC ptable_ent *ptable_find(const ptable * const t, const void * const key) { +#ifndef ptable_find +static ptable_ent *ptable_find(const ptable * const t, const void * const key) { +#define ptable_find ptable_find ptable_ent *ent; const UV hash = PTABLE_HASH(key); @@ -45,20 +118,26 @@ STATIC ptable_ent *ptable_find(const ptable * const t, const void * const key) { return NULL; } +#endif /* !ptable_find */ -STATIC void *ptable_fetch(const ptable * const t, const void * const key) { +#ifndef ptable_fetch +static void *ptable_fetch(const ptable * const t, const void * const key) { +#define ptable_fetch ptable_fetch const ptable_ent *const ent = ptable_find(t, key); return ent ? ent->val : NULL; } +#endif /* !ptable_fetch */ -STATIC void ptable_split(ptable * const t) { +#ifndef ptable_split +static void ptable_split(pPTBLMS_ ptable * const t) { +#define ptable_split(T) ptable_split(aPTBLMS_ (T)) ptable_ent **ary = t->ary; - const UV oldsize = t->max + 1; - UV newsize = oldsize * 2; - UV i; + const size_t oldsize = t->max + 1; + size_t newsize = oldsize * 2; + size_t i; - ary = PerlMemShared_realloc(ary, newsize * sizeof(*ary)); + ary = VOID2(ptable_ent **, PerlMemShared_realloc(ary, newsize * sizeof(*ary))); Zero(&ary[oldsize], newsize - oldsize, sizeof(*ary)); t->max = --newsize; t->ary = ary; @@ -79,17 +158,20 @@ STATIC void ptable_split(ptable * const t) { } } } +#endif /* !ptable_split */ -STATIC void ptable_store(ptable * const t, const void * const key, void * const val) { +static void PTABLE_PREFIX(_store)(pPTBL_ ptable * const t, const void * const key, void * const val) { ptable_ent *ent = ptable_find(t, key); if (ent) { +#ifdef PTABLE_VAL_FREE void *oldval = ent->val; PTABLE_VAL_FREE(oldval); +#endif ent->val = val; - } else { - const UV i = PTABLE_HASH(key) & t->max; - ent = PerlMemShared_malloc(sizeof *ent); + } else if (val) { + const size_t i = PTABLE_HASH(key) & t->max; + ent = VOID2(ptable_ent *, PerlMemShared_malloc(sizeof *ent)); ent->key = key; ent->val = val; ent->next = t->ary[i]; @@ -100,21 +182,65 @@ STATIC void ptable_store(ptable * const t, const void * const key, void * const } } -#if 0 +#if PTABLE_NEED_DELETE + +static void PTABLE_PREFIX(_delete)(pPTBL_ ptable * const t, const void * const key) { + ptable_ent *prev, *ent; + const size_t i = PTABLE_HASH(key) & t->max; + + prev = NULL; + ent = t->ary[i]; + for (; ent; prev = ent, ent = ent->next) { + if (ent->key == key) + break; + } + + if (ent) { + if (prev) + prev->next = ent->next; + else + t->ary[i] = ent->next; +#ifdef PTABLE_VAL_FREE + PTABLE_VAL_FREE(ent->val); +#endif + PerlMemShared_free(ent); + } +} + +#endif /* PTABLE_NEED_DELETE */ + +#if PTABLE_NEED_WALK && !defined(ptable_walk) + +static void ptable_walk(pTHX_ ptable * const t, void (*cb)(pTHX_ ptable_ent *ent, void *userdata), void *userdata) { +#define ptable_walk(T, CB, UD) ptable_walk(aTHX_ (T), (CB), (UD)) + if (t && t->items) { + register ptable_ent ** const array = t->ary; + size_t i = t->max; + do { + ptable_ent *entry; + for (entry = array[i]; entry; entry = entry->next) + if (entry->val) + cb(aTHX_ entry, userdata); + } while (i--); + } +} + +#endif /* PTABLE_NEED_WALK && !defined(ptable_walk) */ -STATIC void ptable_clear(ptable * const t) { +static void PTABLE_PREFIX(_clear)(pPTBL_ ptable * const t) { if (t && t->items) { register ptable_ent ** const array = t->ary; - UV i = t->max; + size_t i = t->max; do { ptable_ent *entry = array[i]; while (entry) { - ptable_ent * const oentry = entry; - void *val = oentry->val; - entry = entry->next; - PTABLE_VAL_FREE(val); + ptable_ent * const nentry = entry->next; +#ifdef PTABLE_VAL_FREE + PTABLE_VAL_FREE(entry->val); +#endif PerlMemShared_free(entry); + entry = nentry; } array[i] = NULL; } while (i--); @@ -123,12 +249,21 @@ STATIC void ptable_clear(ptable * const t) { } } -STATIC void ptable_free(ptable * const t) { +static void PTABLE_PREFIX(_free)(pPTBL_ ptable * const t) { if (!t) return; - ptable_clear(t); + PTABLE_PREFIX(_clear)(aPTBL_ t); PerlMemShared_free(t->ary); PerlMemShared_free(t); } -#endif +#undef pPTBL +#undef pPTBL_ +#undef aPTBL +#undef aPTBL_ + +#undef PTABLE_NAME +#undef PTABLE_VAL_FREE + +#undef PTABLE_NEED_DELETE +#undef PTABLE_NEED_WALK