]> code.delx.au - pulseaudio/commitdiff
make iterating with pa_idxset_next() robust in regards to idxset modifications
authorLennart Poettering <lennart@poettering.net>
Tue, 3 Feb 2009 01:15:36 +0000 (02:15 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 3 Feb 2009 01:15:36 +0000 (02:15 +0100)
src/pulsecore/idxset.c

index 24a28db74aa48104c76e6bfc798a39d666ac7efc..352ac9777e2cc1adbb50d8d833ddbf3801d8ee9b 100644 (file)
@@ -386,8 +386,11 @@ void* pa_idxset_steal_first(pa_idxset *s, uint32_t *idx) {
 void* pa_idxset_first(pa_idxset *s, uint32_t *idx) {
     pa_assert(s);
 
-    if (!s->iterate_list_head)
+    if (!s->iterate_list_head) {
+        if (idx)
+            *idx = PA_IDXSET_INVALID;
         return NULL;
+    }
 
     if (idx)
         *idx = s->iterate_list_head->idx;
@@ -402,20 +405,41 @@ void *pa_idxset_next(pa_idxset *s, uint32_t *idx) {
     pa_assert(s);
     pa_assert(idx);
 
+    if (*idx == PA_IDXSET_INVALID)
+        return NULL;
+
     hash = *idx % NBUCKETS;
 
-    if (!(e = index_scan(s, hash, *idx)))
-        return NULL;
+    if ((e = index_scan(s, hash, *idx))) {
+
+        e = e->iterate_next;
+
+        if (e) {
+            *idx = e->idx;
+            return e->data;
+        } else {
+            *idx = PA_IDXSET_INVALID;
+            return NULL;
+        }
+
+    } else {
+
+        /* If the entry passed doesn't exist anymore we try to find
+         * the next following */
+
+        for ((*idx)++; *idx < s->current_index; (*idx)++) {
+
+            hash = *idx % NBUCKETS;
+
+            if ((e = index_scan(s, hash, *idx))) {
+                *idx = e->idx;
+                return e->data;
+            }
+        }
 
-    if (!e->iterate_next) {
         *idx = PA_IDXSET_INVALID;
         return NULL;
     }
-
-    e = e->iterate_next;
-
-    *idx = e->idx;
-    return e->data;
 }
 
 unsigned pa_idxset_size(pa_idxset*s) {