From: Phil Carmody Date: Sat, 24 Jan 2015 00:15:45 +0000 (+0200) Subject: lib: array - helper to swap array buffer ownership X-Git-Tag: 2.2.16.rc1~106 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9a6250aecfe56f0970761806c16794c04330f46a;p=thirdparty%2Fdovecot%2Fcore.git lib: array - helper to swap array buffer ownership 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 --- diff --git a/src/lib/array.h b/src/lib/array.h index 865567bf48..6efbdc6b04 100644 --- a/src/lib/array.h +++ b/src/lib/array.h @@ -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) \ diff --git a/src/lib/test-array.c b/src/lib/test-array.c index f4c4fa4ca3..ba049750f5 100644 --- a/src/lib/test-array.c +++ b/src/lib/test-array.c @@ -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)