]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: array - helper to swap array buffer ownership
authorPhil Carmody <phil@dovecot.fi>
Sat, 24 Jan 2015 00:15:45 +0000 (02:15 +0200)
committerPhil Carmody <phil@dovecot.fi>
Sat, 24 Jan 2015 00:15:45 +0000 (02:15 +0200)
Currently there's no simple way to create a replacement for an array,
and then atomically switch in that replacement. With this helper,
you can just exchange ownership of the two lists and then free the
new list (which now contains the old buffer).

Signed-off-by: Phil Carmody <phil@dovecot.fi>
src/lib/array.h
src/lib/test-array.c

index 865567bf487998dbdf12ec1cd238cca2267d8ce1..6efbdc6b04c561ea7e3c3200cfd6bdba2433d313 100644 (file)
@@ -271,6 +271,22 @@ array_copy(struct array *dest, unsigned int dest_idx,
                    count * dest->element_size);
 }
 
+/* Exchange ownership of two arrays, which should have been allocated
+   from the same pool/context. Useful for updating an array with a
+   replacement. */
+static inline void
+array_swap_i(struct array *array1, struct array *array2)
+{
+       buffer_t *buffer = array1->buffer;
+
+       i_assert(array1->element_size == array2->element_size);
+       array1->buffer = array2->buffer;
+       array2->buffer = buffer;
+}
+#define array_swap(array1, array2)                                     \
+       array_swap_i(&(array1)->arr + ARRAY_TYPES_CHECK(array1, array2), \
+                    &(array2)->arr)
+
 bool array_cmp_i(const struct array *array1,
                 const struct array *array2) ATTR_PURE;
 #define array_cmp(array1, array2) \
index f4c4fa4ca3c5609fd125c67253f4beb9e4580360..ba049750f5fb5e980b9ef15aef6989b90e054ebd 100644 (file)
@@ -32,6 +32,28 @@ static void test_array_foreach(void)
        test_end();
 }
 
+static void test_array_swap(void)
+{
+       ARRAY(struct foo) foos[3];
+       struct foo nfoo;
+       int i, j;
+
+       test_begin("array swap");
+       for (i = 1; i <= 3; i++) {
+               t_array_init(&foos[i-1], i);
+               for (j = 1; j <= 2*i+1; j++) {
+                       nfoo.a = nfoo.b = nfoo.c = j;
+                       array_append(&foos[i-1], &nfoo, 1);
+               }
+       }
+       for (i = 0; i < 1000; i++)
+               array_swap(&foos[rand()%3], &foos[rand()%3]);
+       /* Just want size 3, 5, and 7 in any order */
+       test_assert(array_count(&foos[0]) * array_count(&foos[1]) * array_count(&foos[2]) == 3*5*7);
+       test_assert(array_count(&foos[0]) + array_count(&foos[1]) + array_count(&foos[2]) == 3+5+7);
+       test_end();
+}
+
 static int test_int_compare(const int *key, const int *elem)
 {
        return (*key < *elem) ? -1 :
@@ -192,6 +214,7 @@ void test_array(void)
        test_array_reverse();
        test_array_cmp();
        test_array_cmp_str();
+       test_array_swap();
 }
 
 enum fatal_test_state fatal_array(int stage)