@@ -190,6 +190,39 @@ OVS_NO_RETURN void ovs_assert_failure(const char *, const char *, const char *);
#define UPDATE_MULTIVAR(EXPR, VAR) \
((EXPR), (VAR) = NULL)
+
+/* In the safe version of the multi-variable container iteration, the next
+ * value of the iterator is precalculated on the condition expression.
+ * This allows for the iterator to be freed inside the loop.
+ *
+ * The next value of the iterator is stored in a variable declared in the
+ * INIT_MULTIVAR_SAFE macro and its name is ITER_NEXT_VAR(OBJECT).
+ */
+#define ITER_NEXT_VAR(NAME) NAME ## __iterator__next__
+
+/* Safe initialization declares both iterators. */
+#define INIT_MULTIVAR_SAFE(VAR, MEMBER, POINTER) \
+ INIT_MULTIVAR_SAFE_EXP(VAR, MEMBER, POINTER, (void) 0)
+
+#define INIT_MULTIVAR_SAFE_EXP(VAR, MEMBER, POINTER, ...) \
+ OVS_TYPEOF(VAR->MEMBER) *ITER_VAR(VAR) = \
+ ( __VA_ARGS__ , (OVS_TYPEOF(&(VAR->MEMBER))) POINTER), \
+ *ITER_NEXT_VAR(VAR) = NULL
+
+/* Evaluate the condition expression and, if satisfied, update the _next_
+ * iterator with the NEXT_EXPR.
+ * Both EXPR and NEXT_EXPR should only use ITER_VAR(VAR) and
+ * ITER_NEXT_VAR(VAR).
+ */
+#define CONDITION_MULTIVAR_SAFE(EXPR, NEXT_EXPR, VAR, MEMBER) \
+ ((EXPR) ? \
+ (((VAR) = OBJECT_CONTAINING(ITER_VAR(VAR), VAR, MEMBER)), \
+ (NEXT_EXPR), 1) : \
+ (((VAR) = NULL), 0))
+
+#define UPDATE_MULTIVAR_SAFE(VAR) \
+ UPDATE_MULTIVAR(ITER_VAR(VAR) = ITER_NEXT_VAR(VAR), VAR)
+
/* Returns the number of elements in ARRAY. */
#define ARRAY_SIZE(ARRAY) __ARRAY_SIZE(ARRAY)
Safe version of multi-variable iterator helpers declare an internal variable to store the next value of the iterator temporarily. This eliminates the need to declare an external variable to store it, making loops more readable and less error prone. Signed-off-by: Adrian Moreno <amorenoz@redhat.com> --- include/openvswitch/util.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)