@@ -211,9 +211,14 @@ typedef struct slist_head
211211 * Used as state in slist_foreach(). To get the current element of the
212212 * iteration use the 'cur' member.
213213 *
214- * Do *not* manipulate the list while iterating!
215- *
216- * NB: this wouldn't really need to be an extra struct, we could use a
214+ * It's allowed to modify the list while iterating, with the exception of
215+ * deleting the iterator's current node; deletion of that node requires
216+ * care if the iteration is to be continued afterward.(Doing so and also
217+ * deleting or inserting adjacent list elements might misbehave; also, if
218+ * the user frees the current node's storage, continuing the iteration is
219+ * not safe.)
220+ *
221+ * NB: this wouldn't really need to be an extra struct, we could use an
217222 * slist_node * directly. We prefer a separate type for consistency.
218223 */
219224typedef struct slist_iter
@@ -224,15 +229,18 @@ typedef struct slist_iter
224229/*
225230 * Singly linked list iterator allowing some modifications while iterating.
226231 *
227- * Used as state in slist_foreach_modify().
232+ * Used as state in slist_foreach_modify(). To get the current element of the
233+ * iteration use the 'cur' member.
228234 *
229- * Iterations using this are allowed to remove the current node and to add
230- * more nodes ahead of the current node.
235+ * The only list modification allowed while iterating is to remove the current
236+ * node via slist_delete_current() (*not* slist_delete()).Insertion or
237+ * deletion of nodes adjacent to the current node would misbehave.
231238 */
232239typedef struct slist_mutable_iter
233240{
234241slist_node * cur ;/* current element */
235242slist_node * next ;/* next node we'll iterate to */
243+ slist_node * prev ;/* prev node, for deletions */
236244}slist_mutable_iter ;
237245
238246
@@ -243,7 +251,7 @@ typedef struct slist_mutable_iter
243251
244252/* Prototypes for functions too big to be inline */
245253
246- /* Caution: this is O(n) */
254+ /* Caution: this is O(n); consider using slist_delete_current() instead */
247255extern void slist_delete (slist_head * head ,slist_node * node );
248256
249257#ifdef ILIST_DEBUG
@@ -578,6 +586,7 @@ extern slist_node *slist_pop_head_node(slist_head *head);
578586extern bool slist_has_next (slist_head * head ,slist_node * node );
579587extern slist_node * slist_next_node (slist_head * head ,slist_node * node );
580588extern slist_node * slist_head_node (slist_head * head );
589+ extern void slist_delete_current (slist_mutable_iter * iter );
581590
582591/* slist macro support function */
583592extern void * slist_head_element_off (slist_head * head ,size_t off );
@@ -679,6 +688,29 @@ slist_head_node(slist_head *head)
679688{
680689return (slist_node * )slist_head_element_off (head ,0 );
681690}
691+
692+ /*
693+ * Delete the list element the iterator currently points to.
694+ *
695+ * Caution: this modifies iter->cur, so don't use that again in the current
696+ * loop iteration.
697+ */
698+ STATIC_IF_INLINE void
699+ slist_delete_current (slist_mutable_iter * iter )
700+ {
701+ /*
702+ * Update previous element's forward link. If the iteration is at the
703+ * first list element, iter->prev will point to the list header's "head"
704+ * field, so we don't need a special case for that.
705+ */
706+ iter -> prev -> next = iter -> next ;
707+
708+ /*
709+ * Reset cur to prev, so that prev will continue to point to the prior
710+ * valid list element after slist_foreach_modify() advances to the next.
711+ */
712+ iter -> cur = iter -> prev ;
713+ }
682714#endif /* PG_USE_INLINE || ILIST_INCLUDE_DEFINITIONS */
683715
684716/*
@@ -706,7 +738,12 @@ slist_head_node(slist_head *head)
706738 *
707739 * Access the current element with iter.cur.
708740 *
709- * It is *not* allowed to manipulate the list during iteration.
741+ * It's allowed to modify the list while iterating, with the exception of
742+ * deleting the iterator's current node; deletion of that node requires
743+ * care if the iteration is to be continued afterward.(Doing so and also
744+ * deleting or inserting adjacent list elements might misbehave; also, if
745+ * the user frees the current node's storage, continuing the iteration is
746+ * not safe.)
710747 */
711748#define slist_foreach (iter ,lhead )\
712749for (AssertVariableIsOfTypeMacro(iter, slist_iter),\
@@ -720,15 +757,18 @@ slist_head_node(slist_head *head)
720757 *
721758 * Access the current element with iter.cur.
722759 *
723- * Iterations using this are allowed to remove the current node and to add
724- * more nodes ahead of the current node.
760+ * The only list modification allowed while iterating is to remove the current
761+ * node via slist_delete_current() (*not* slist_delete()).Insertion or
762+ * deletion of nodes adjacent to the current node would misbehave.
725763 */
726764#define slist_foreach_modify (iter ,lhead )\
727765for (AssertVariableIsOfTypeMacro(iter, slist_mutable_iter),\
728766 AssertVariableIsOfTypeMacro(lhead, slist_head *),\
729- (iter).cur = (lhead)->head.next,\
767+ (iter).prev = &(lhead)->head,\
768+ (iter).cur = (iter).prev->next,\
730769 (iter).next = (iter).cur ? (iter).cur->next : NULL;\
731770 (iter).cur != NULL;\
771+ (iter).prev = (iter).cur,\
732772 (iter).cur = (iter).next,\
733773 (iter).next = (iter).next ? (iter).next->next : NULL)
734774