[folks] Add fast-path iteration for SmallSet



commit 06f06a10a754b28b8ede2ec840cbadbc8afb7733
Author: Simon McVittie <simon mcvittie collabora co uk>
Date:   Thu Mar 28 14:46:55 2013 +0000

    Add fast-path iteration for SmallSet
    
    Bug: https://bugzilla.gnome.org/show_bug.cgi?id=687161
    Signed-off-by: Simon McVittie <simon mcvittie collabora co uk>
    Reviewed-by: Philip Withnall <philip tecnocode co uk>

 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(+), 0 deletions(-)
---
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<G> copy (Gee.Iterable<G> iterable,
         owned Gee.HashDataFunc<G>? item_hash = null,
         owned Gee.EqualDataFunc<G>? 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> (UInt.hash_static, UInt.equals_static);
+      var set_ = (!) (small as Set<UInt>);
+
+      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)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]