diff mbox series

[ovs-dev,02/13] util: add safe multi-variable iterators

Message ID 20220124103445.2459400-3-amorenoz@redhat.com
State Superseded
Headers show
Series Fix undefined behavior in loop macros | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed

Commit Message

Adrian Moreno Jan. 24, 2022, 10:34 a.m. UTC
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(+)
diff mbox series

Patch

diff --git a/include/openvswitch/util.h b/include/openvswitch/util.h
index f72438fdf..9cb70a567 100644
--- a/include/openvswitch/util.h
+++ b/include/openvswitch/util.h
@@ -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)