From 06f06a10a754b28b8ede2ec840cbadbc8afb7733 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 28 Mar 2013 14:46:55 +0000 Subject: [PATCH] Add fast-path iteration for SmallSet Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687161 Signed-off-by: Simon McVittie Reviewed-by: Philip Withnall --- configure.ac | 2 ++ folks/folks-generics.vapi | 5 +++++ folks/small-set-internal.h | 13 +++++++++++++ tests/folks/small-set.vala | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+) diff --git a/configure.ac b/configure.ac index 2e284b3..a7c4da0 100644 --- a/configure.ac +++ b/configure.ac @@ -295,6 +295,8 @@ AS_IF([test "x$enable_vala" = "xyes"], [ # require GLib >= 2.24 so GLib.Array, etc. reffing is handled # automatically AM_VALAFLAGS="--target-glib=2.24" + # within the libfolks tree, select inline code paths + AM_VALAFLAGS="$AM_VALAFLAGS -D FOLKS_COMPILATION" AC_SUBST([AM_VALAFLAGS]) AC_SUBST([VAPIGENFLAGS]) AC_SUBST([VAPIDIR]) diff --git a/folks/folks-generics.vapi b/folks/folks-generics.vapi index cab90a0..867257f 100644 --- a/folks/folks-generics.vapi +++ b/folks/folks-generics.vapi @@ -39,6 +39,11 @@ namespace Folks internal static SmallSet copy (Gee.Iterable iterable, owned Gee.HashDataFunc? item_hash = null, owned Gee.EqualDataFunc? item_equals = null); + +#if FOLKS_COMPILATION + [CCode (cheader_filename = "folks/small-set-internal.h")] + public unowned G @get (int i); +#endif } } diff --git a/folks/small-set-internal.h b/folks/small-set-internal.h index aeda316..d18bd8f 100644 --- a/folks/small-set-internal.h +++ b/folks/small-set-internal.h @@ -74,6 +74,19 @@ struct _FolksSmallSet { FolksSmallSet *rw_version; }; +/* Syntactic sugar for iteration. The type must match the type + * of the size property, which is signed, because Vala. */ +static inline gconstpointer +folks_small_set_get (FolksSmallSet *self, + gint i) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (i >= 0, NULL); + g_return_val_if_fail ((guint) i < self->items->len, NULL); + + return g_ptr_array_index (self->items, i); +} + FolksSmallSet * _folks_small_set_new_take_array (GPtrArray *arr, GType item_type, diff --git a/tests/folks/small-set.vala b/tests/folks/small-set.vala index c2d2e2b..bfc5ff0 100644 --- a/tests/folks/small-set.vala +++ b/tests/folks/small-set.vala @@ -68,6 +68,7 @@ public class SmallSetTests : Folks.TestCase this.add_test ("direct", () => this.test_direct (false)); this.add_test ("string_hash", () => this.test_strings (true)); this.add_test ("string", () => this.test_strings (false)); + this.add_test ("cheating", this.test_cheating); } public void test_objects (bool use_hash) @@ -406,6 +407,42 @@ public class SmallSetTests : Folks.TestCase strings.add ("ham"); assert (strings.size == 2); } + + public void test_cheating () + { + var small = new SmallSet (UInt.hash_static, UInt.equals_static); + var set_ = (!) (small as Set); + + small.add (new UInt (1)); + small.add (new UInt (10)); + small.add (new UInt (100)); + small.add (new UInt (1000)); + small.add (new UInt (10000)); + + int i = 0; + set_.iterator ().foreach ((obj) => + { + /* Fast-path: get() provides indexed access */ + assert (small[i] == obj); + i++; + return true; + }); + assert (i == 5); + + /* Slow iteration: we don't know, syntactically, that set_ is a + * SmallSet, so we'll use the iterator */ + uint sum = 0; + foreach (var obj in set_) + sum += obj.u; + assert (sum == 11111); + + /* Fast iteration: we do know, syntactically, that small is a + * SmallSet, so we'll use indexed access */ + sum = 0; + foreach (unowned UInt obj in small) + sum += obj.u; + assert (sum == 11111); + } } public int main (string[] args) -- 2.7.4