128
128
#define SH_STAT SH_MAKE_NAME(stat)
129
129
130
130
/* 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)
132
133
#define SH_NEXT SH_MAKE_NAME(next)
133
134
#define SH_PREV SH_MAKE_NAME(prev)
134
135
#define SH_DISTANCE_FROM_OPTIMAL SH_MAKE_NAME(distance)
@@ -303,11 +304,11 @@ SH_SCOPE void SH_STAT(SH_TYPE * tb);
303
304
#endif
304
305
305
306
/*
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 .
308
309
*/
309
- static inline void
310
- SH_COMPUTE_PARAMETERS ( SH_TYPE * tb , uint64 newsize )
310
+ static inline uint64
311
+ SH_COMPUTE_SIZE ( uint64 newsize )
311
312
{
312
313
uint64 size ;
313
314
@@ -325,6 +326,18 @@ SH_COMPUTE_PARAMETERS(SH_TYPE * tb, uint64 newsize)
325
326
if (unlikely ((((uint64 ) sizeof (SH_ELEMENT_TYPE )) * size ) >= SIZE_MAX / 2 ))
326
327
sh_error ("hash table too large" );
327
328
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
+
328
341
/* now set size */
329
342
tb -> size = size ;
330
343
tb -> sizemask = (uint32 ) (size - 1 );
@@ -446,10 +459,11 @@ SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data)
446
459
/* increase nelements by fillfactor, want to store nelements elements */
447
460
size = Min ((double ) SH_MAX_SIZE , ((double ) nelements ) / SH_FILLFACTOR );
448
461
449
- SH_COMPUTE_PARAMETERS ( tb , size );
462
+ size = SH_COMPUTE_SIZE ( size );
450
463
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 );
452
465
466
+ SH_UPDATE_PARAMETERS (tb , size );
453
467
return tb ;
454
468
}
455
469
@@ -490,10 +504,15 @@ SH_GROW(SH_TYPE * tb, uint64 newsize)
490
504
Assert (oldsize != SH_MAX_SIZE );
491
505
Assert (oldsize < newsize );
492
506
493
- /* compute parameters for new table */
494
- SH_COMPUTE_PARAMETERS (tb , newsize );
507
+ newsize = SH_COMPUTE_SIZE (newsize );
495
508
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 );
497
516
498
517
newdata = tb -> data ;
499
518
@@ -1173,7 +1192,8 @@ SH_STAT(SH_TYPE * tb)
1173
1192
#undef SH_STAT
1174
1193
1175
1194
/* internal function names */
1176
- #undef SH_COMPUTE_PARAMETERS
1195
+ #undef SH_COMPUTE_SIZE
1196
+ #undef SH_UPDATE_PARAMETERS
1177
1197
#undef SH_COMPARE_KEYS
1178
1198
#undef SH_INITIAL_BUCKET
1179
1199
#undef SH_NEXT
0 commit comments