128128#define SH_STAT SH_MAKE_NAME(stat)
129129
130130/* internal helper functions (no externally visible prototypes) */
131- #define SH_COMPUTE_PARAMETERS SH_MAKE_NAME(compute_parameters)
131+ #define SH_COMPUTE_SIZE SH_MAKE_NAME(compute_size)
132+ #define SH_UPDATE_PARAMETERS SH_MAKE_NAME(update_parameters)
132133#define SH_NEXT SH_MAKE_NAME(next)
133134#define SH_PREV SH_MAKE_NAME(prev)
134135#define SH_DISTANCE_FROM_OPTIMAL SH_MAKE_NAME(distance)
@@ -303,11 +304,11 @@ SH_SCOPE void SH_STAT(SH_TYPE * tb);
303304#endif
304305
305306/*
306- * Compute sizing parameters for hashtable. Called when creating and growing
307- * the hashtable .
307+ * Compute allocation size for hashtable. Result can be passed to
308+ * SH_UPDATE_PARAMETERS .
308309 */
309- static inline void
310- SH_COMPUTE_PARAMETERS ( SH_TYPE * tb , uint64 newsize )
310+ static inline uint64
311+ SH_COMPUTE_SIZE ( uint64 newsize )
311312{
312313 uint64 size ;
313314
@@ -325,6 +326,18 @@ SH_COMPUTE_PARAMETERS(SH_TYPE * tb, uint64 newsize)
325326 if (unlikely ((((uint64 ) sizeof (SH_ELEMENT_TYPE )) * size ) >= SIZE_MAX / 2 ))
326327 sh_error ("hash table too large" );
327328
329+ return size ;
330+ }
331+
332+ /*
333+ * Update sizing parameters for hashtable. Called when creating and growing
334+ * the hashtable.
335+ */
336+ static inline void
337+ SH_UPDATE_PARAMETERS (SH_TYPE * tb , uint64 newsize )
338+ {
339+ uint64 size = SH_COMPUTE_SIZE (newsize );
340+
328341 /* now set size */
329342 tb -> size = size ;
330343 tb -> sizemask = (uint32 ) (size - 1 );
@@ -446,10 +459,11 @@ SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data)
446459 /* increase nelements by fillfactor, want to store nelements elements */
447460 size = Min ((double ) SH_MAX_SIZE , ((double ) nelements ) / SH_FILLFACTOR );
448461
449- SH_COMPUTE_PARAMETERS ( tb , size );
462+ size = SH_COMPUTE_SIZE ( size );
450463
451- tb -> data = (SH_ELEMENT_TYPE * ) SH_ALLOCATE (tb , sizeof (SH_ELEMENT_TYPE ) * tb -> size );
464+ tb -> data = (SH_ELEMENT_TYPE * ) SH_ALLOCATE (tb , sizeof (SH_ELEMENT_TYPE ) * size );
452465
466+ SH_UPDATE_PARAMETERS (tb , size );
453467 return tb ;
454468}
455469
@@ -490,10 +504,15 @@ SH_GROW(SH_TYPE * tb, uint64 newsize)
490504 Assert (oldsize != SH_MAX_SIZE );
491505 Assert (oldsize < newsize );
492506
493- /* compute parameters for new table */
494- SH_COMPUTE_PARAMETERS (tb , newsize );
507+ newsize = SH_COMPUTE_SIZE (newsize );
495508
496- tb -> data = (SH_ELEMENT_TYPE * ) SH_ALLOCATE (tb , sizeof (SH_ELEMENT_TYPE ) * tb -> size );
509+ tb -> data = (SH_ELEMENT_TYPE * ) SH_ALLOCATE (tb , sizeof (SH_ELEMENT_TYPE ) * newsize );
510+
511+ /*
512+ * Update parameters for new table after allocation succeeds to avoid
513+ * inconsistent state on OOM.
514+ */
515+ SH_UPDATE_PARAMETERS (tb , newsize );
497516
498517 newdata = tb -> data ;
499518
@@ -1173,7 +1192,8 @@ SH_STAT(SH_TYPE * tb)
11731192#undef SH_STAT
11741193
11751194/* internal function names */
1176- #undef SH_COMPUTE_PARAMETERS
1195+ #undef SH_COMPUTE_SIZE
1196+ #undef SH_UPDATE_PARAMETERS
11771197#undef SH_COMPARE_KEYS
11781198#undef SH_INITIAL_BUCKET
11791199#undef SH_NEXT
0 commit comments