CHashPtr c;
volatile CHashNode *n;
bool found = false;
+ int cmp = 1;
/* Suppress garbage collection for target bucket. */
CHashTableSuppressGC(table, bucket);
/* Scan bucket. */
c = table->bucket[bucket].head;
- for (;;)
+ while (c != InvalidCHashPtr)
{
- int cmp;
-
- /* If we've reached the end of the bucket chain, stop. */
- if (c == InvalidCHashPtr)
- break;
-
/* Compare current node by hashcode, then by memcmp. */
n = CHashTableGetNode(table, c);
pg_read_barrier_depends();
cmp = -1;
/* Stop if we've passed the list position where the entry should be. */
- if (cmp > 0)
+ if (cmp >= 0)
break;
/* Fetch next-pointer. */
c = n->next;
+ }
- /* Is it the item we're looking for? */
- if (cmp == 0)
- {
- /*
- * If the pointer is marked, it will be followed (if at all) by
- * a node which is "later" than this one in terms of either
- * hashcode or memcmp ordering; we won't find a duplicate of the
- * current key. This is because a marked CHashPtr is never
- * further updated (or at least, not until after garbage
- * collection, which we've already prevented for this bucket),
- * so the successor element must have been present before this
- * one was deleted.
- */
- if (!CHashPtrIsMarked(c))
- {
- memcpy(((char *) entry) + table->desc.key_size,
- CHashNodeGetItem(n) + table->desc.key_size,
- table->desc.element_size - table->desc.key_size);
- found = true;
- }
- break;
- }
+ /*
+ * Is it the item we're looking for?
+ *
+ * If the pointer is marked, it will be followed (if at all) by
+ * a node which is "later" than this one in terms of either
+ * hashcode or memcmp ordering; we won't find a duplicate of the
+ * current key. This is because a marked CHashPtr is never
+ * further updated (or at least, not until after garbage
+ * collection, which we've already prevented for this bucket),
+ * so the successor element must have been present before this
+ * one was deleted.
+ */
+ if (cmp == 0 && !CHashPtrIsMarked(n->next))
+ {
+ memcpy(((char *) entry) + table->desc.key_size,
+ CHashNodeGetItem(n) + table->desc.key_size,
+ table->desc.element_size - table->desc.key_size);
+ found = true;
}
/* We're done. */
retry:
p = &table->bucket[bucket].head;
c = *p;
- for (;;)
+ while (c != InvalidCHashPtr)
{
int cmp;
- /*
- * We can't safely update a delete-marked pointer, so remove any
- * such pointers we find from the bucket chain. Sometimes, concurrent
- * activity may force us to restart the whole scan, but that should
- * be rare.
- */
- if (CHashPtrIsMarked(c) && CHashRemoveMarked(table, bucket, &c, p))
- goto retry;
-
- /* If we reach the end of the bucket chain, stop. */
- if (c == InvalidCHashPtr)
- break;
-
/* Compare current node by hashcode, then by memcmp. */
n = CHashTableGetNode(table, c);
pg_read_barrier_depends();
/* Move to next node. */
p = &n->next;
c = *p;
+
+ /*
+ * We can't safely update a delete-marked pointer, so remove any
+ * such pointers we find from the bucket chain. Sometimes, concurrent
+ * activity may force us to restart the whole scan, but that should
+ * be rare.
+ */
+ if (CHashPtrIsMarked(c) && CHashRemoveMarked(table, bucket, &c, p))
+ goto retry;
}
if (!found)