dovecot-2.2: lib: array - helper to swap array buffer ownership

dovecot at dovecot.org dovecot at dovecot.org
Sat Jan 24 00:18:06 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/7557234ac0f4
changeset: 18200:7557234ac0f4
user:      Phil Carmody <phil at dovecot.fi>
date:      Sat Jan 24 02:15:45 2015 +0200
description:
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 <phil at dovecot.fi>

diffstat:

 src/lib/array.h      |  16 ++++++++++++++++
 src/lib/test-array.c |  23 +++++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diffs (66 lines):

diff -r 111dcc2ca272 -r 7557234ac0f4 src/lib/array.h
--- a/src/lib/array.h	Fri Jan 23 23:19:24 2015 +0200
+++ b/src/lib/array.h	Sat Jan 24 02:15:45 2015 +0200
@@ -271,6 +271,22 @@
 		    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 -r 111dcc2ca272 -r 7557234ac0f4 src/lib/test-array.c
--- a/src/lib/test-array.c	Fri Jan 23 23:19:24 2015 +0200
+++ b/src/lib/test-array.c	Sat Jan 24 02:15:45 2015 +0200
@@ -32,6 +32,28 @@
 	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 @@
 	test_array_reverse();
 	test_array_cmp();
 	test_array_cmp_str();
+	test_array_swap();
 }
 
 enum fatal_test_state fatal_array(int stage)


More information about the dovecot-cvs mailing list