diff --git a/gee/Makefile.am b/gee/Makefile.am
index be270bf..ed97250 100644
--- a/gee/Makefile.am
+++ b/gee/Makefile.am
@@ -31,6 +31,7 @@ libgee_0_8_la_SOURCES = \
 	concurrentlist.vala \
 	deque.vala \
 	functions.vala \
+	glist.vala \
 	hashable.vala \
 	hashmap.vala \
 	hashmultimap.vala \
diff --git a/gee/glist.vala b/gee/glist.vala
new file mode 100644
index 0000000..6b59c1a
--- /dev/null
+++ b/gee/glist.vala
@@ -0,0 +1,326 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* iterable.vala
+ *
+ * Copyright (C) 2012 Daniel Espinosa
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Daniel Espinosa <despinosa@gnome.org>
+ */
+ 
+ namespace Gee {
+ 	/**
+ 	 * GList:
+ 	 * A BidirList and List implementation relaying a GLib.List<G>.
+ 	 *
+ 	 **/
+ 	public class GList<G> : AbstractBidirList<G>, Collection<G>, List<G>, BidirList<G>
+ 	{
+ 		private int nelements = -1;
+ 		private GLib.List<G> _list = new GLib.List<G> ();
+ 		
+ 		public GLib.List<G> list { get { return _list; } set { _list = value.copy (); } }
+ 		
+ 		/* AbstractBidirList */
+ 		public override BidirListIterator<G> bidir_list_iterator () {
+ 			return new GListIterator<G> (list) as BidirListIterator<G>;
+ 		}
+ 		
+ 		/* AbstractList */
+ 		public override ListIterator<G> list_iterator () {
+ 			return new GListIterator<G> (list);
+ 		}
+
+		public override new G? get (int index) {
+			return list.nth_data (index);
+		}
+
+		public override new void set (int index, G item) {
+			list.nth (index).data = item;
+		}
+
+		public override int index_of (G item) {
+			return list.index(item);
+		}
+
+		public override void insert (int index, G item) {
+			list.insert (item, index);
+			nelements = -1;
+		}
+
+		public override G remove_at (int index) {
+			unowned GLib.List<G> l = list.nth(index);
+			G d = l.data;
+			list.remove (l);
+			nelements = -1;
+			return d;
+		}
+
+		public override List<G>? slice (int start, int stop) {
+			var l = new GLib.List<G>();
+			for (int i = stop; i > start; i--) {
+				G e = list.nth(start + i).data;
+				l.prepend(e);
+			}
+			var ln = new GList<G> ();
+			ln.list = l;
+			return ln;
+		}
+		
+		/* AbstractCollection */
+		
+		public override int size { 
+			get {
+				if (nelements != -1)
+					return nelements;
+				else {
+					nelements = (int) list.length;
+					return nelements;
+				}
+			}
+		}
+
+		public override bool read_only { get { return false; } }
+
+		public override bool contains (G item) {
+			int i = list.index(item);
+			return i >= 0 ? true : false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public override bool add (G item) {
+			list.prepend (item);
+			nelements = -1;
+			return list != null ? true : false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public override bool remove (G item) {
+			list.remove (item);
+			nelements = -1;
+			return list != null ? true : false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public override void clear () {
+			list.first ();
+			while (list != null) {
+				unowned GLib.List<G> n = list;
+				list.remove_link (n);
+			}
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public override Iterator<G> iterator () {
+			return new GListIterator<G> (list);
+		}
+ 	}
+ 	
+ 	public class GListIterator<G> : Object, Traversable<G>, Iterator<G>, ListIterator<G>, BidirIterator<G>, BidirListIterator<G>
+ 	{
+ 		private unowned GLib.List<G> l;
+ 		private unowned GLib.List<G> current;
+ 		private int i;
+ 		private bool _read_only;
+ 		
+ 		/* ListIterator */
+ 		
+ 		public GListIterator (GLib.List<G> list) {
+ 			l = list;
+ 			i = -1;
+ 			current = null;
+ 		}
+ 		
+ 		public new void set (G item) {
+ 			if (current != null) {
+	 			current.data = item;
+	 			this.next ();
+	 		}
+ 		}
+
+		public void add (G item) {
+			i++;
+			l.insert (item, i);
+			current = l;
+		}
+
+		public int index () {
+			return i;
+		}
+		
+		/* Iterator */
+		
+		/**
+		 * Advances to the next element in the iteration.
+		 *
+		 * @return ``true`` if the iterator has a next element
+		 */
+		public bool next () {
+			if (this.has_next ()) {
+				if (current == null && i >= 0) {
+					current = l.nth (++i);
+					return current != null ? true : false;
+				}
+				else {
+					current = current.next;
+					i++;
+					return current != null ? true : false;
+				}
+			}
+			else
+				return false;
+		}
+
+		/**
+		 * Checks whether there is a next element in the iteration.
+		 *
+		 * @return ``true`` if the iterator has a next element
+		 */
+		public bool has_next () {
+			bool r = false;
+			if (current != null && i >= 0) {
+				if (current.next != null)
+					r = true;
+			}
+			else if (current == null && i<0 && l != null)
+				r = true;
+			
+			return r;
+		}
+
+		/**
+		 * Returns the current element in the iteration.
+		 *
+		 * @return the current element in the iteration
+		 */
+		public new G get () {
+			return current == null ? null : current.data;
+		}
+
+		/**
+		 * Removes the current element in the iteration. The cursor is set in an
+		 * in-between state. Both {@link get} and {@link remove} will fail until
+		 * the next move of the cursor (calling {@link next}).
+		 */
+		public void remove () {
+			if (current != null) {
+				l.remove (l.nth (i));
+				i--;
+				current = null;
+			}
+		}
+	
+		/**
+		 * Determines wheather the call to {@link get} is legal. It is false at the
+		 * beginning and after {@link remove} call and true otherwise.
+		 */
+		public bool valid { get { return current == null ? false : true; } }
+	
+		/**
+		 * Determines wheather the call to {@link remove} is legal assuming the
+		 * iterator is valid. The value must not change in runtime hence the user
+		 * of iterator may cache it.
+		 */
+		public bool read_only { get { return _read_only; } }
+		
+		/* BidirIterator */
+		
+		/**
+		 * Rewinds to the previous element in the iteration.
+		 *
+		 * @return ``true`` if the iterator has a previous element
+		 */
+		public bool previous () {
+			if (this.has_previous ()) {
+				if (current == null && i >= 0) {
+					current = l.nth (--i);
+					return current != null ? true : false;
+				}
+				else {
+					current = current.prev;
+					i--;
+					return current != null ? true : false;
+				}
+			}
+			else
+				return false;
+		}
+
+		/**
+		 * Checks whether there is a previous element in the iteration.
+		 *
+		 * @return ``true`` if the iterator has a previous element
+		 */
+		public bool has_previous () {
+			bool r = false;
+			if (current == null || i < 0)
+				r = false;
+			else if (current != null && i > 0)
+				if ( current.prev != null)
+					r = true;
+			return r;
+		}
+
+		/**
+		 * Rewinds to the first element in the iteration.
+		 *
+		 * @return ``true`` if the iterator has a first element
+		 */
+		public bool first () {
+			current = l.first ();
+			i = 0;
+			return current != null ? true : false;
+		}
+
+		/**
+		 * Advances to the last element in the iteration.
+		 *
+		 * @return ``true`` if the iterator has a last element
+		 */
+		public bool last () {
+			current = l.last ();
+			i = (int) l.length ();
+			return current != null ? true : false;
+		}
+		
+		/* BidirListIterator */
+		
+		public void insert (G item) {
+			l.prepend (item);
+			current = l.next;
+		}
+		
+		/* Traversable */
+		
+		public new bool foreach (ForallFunc<G> f) {
+			var r = this.get ();
+			bool ret = f(r);
+			if (ret && this.next ())
+				return true;
+			else
+				return false; 
+		}
+ 	}
+ 	
+ }
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 105292e..ed66b7b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -15,6 +15,7 @@ tests_SOURCES = \
        testconcurrentlist.vala \
        testdeque.vala \
        testfunctions.vala \
+       testglist.vala \
        testhashmap.vala \
        testhashmultimap.vala \
        testhashmultiset.vala \
diff --git a/tests/testglist.vala b/tests/testglist.vala
new file mode 100644
index 0000000..ed9c12a
--- /dev/null
+++ b/tests/testglist.vala
@@ -0,0 +1,138 @@
+/* testglist.vala
+ *
+ * Copyright (C) 2012  Daniel Espinosa
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Daniel Espinosa <despinosa@gnome.org>
+ */
+
+using Gee;
+using GLib;
+
+public class GListTests : BidirListTests {
+
+	public GListTests () {
+		base ("GList");
+		add_test ("[GList] selected functions", test_selected_functions);
+		add_test ("[GList] small sort (insertion)", test_small_sort);
+		add_test ("[GList] big sort (timsort)", test_big_sort);
+		add_test ("[GList] typed to_array calls", test_typed_to_array);
+	}
+
+	private static const int BIG_SORT_SIZE = 1000000;
+
+	public override void set_up () {
+		test_collection = new GList<string> ();
+	}
+
+	public void test_selected_functions () {
+		var test_list = test_collection as GList<string>;
+
+		// Check the collection exists
+		assert (test_list != null);
+	}
+
+	private void test_small_sort () {
+		var test_list = test_collection as GList<string>;
+
+		// Check the collection exists
+		assert (test_list != null);
+
+		test_list.add ("one");
+		test_list.add ("two");
+		test_list.add ("three");
+		test_list.add ("four");
+		test_list.add ("five");
+		test_list.add ("six");
+		test_list.add ("seven");
+		test_list.add ("eight");
+		test_list.add ("nine");
+		test_list.add ("ten");
+		test_list.add ("eleven");
+		test_list.add ("twelve");
+
+		test_list.sort ();
+
+		assert (test_list.get (0) == "eight");
+		assert (test_list.get (1) == "eleven");
+		assert (test_list.get (2) == "five");
+		assert (test_list.get (3) == "four");
+		assert (test_list.get (4) == "nine");
+		assert (test_list.get (5) == "one");
+		assert (test_list.get (6) == "seven");
+		assert (test_list.get (7) == "six");
+		assert (test_list.get (8) == "ten");
+		assert (test_list.get (9) == "three");
+		assert (test_list.get (10) == "twelve");
+		assert (test_list.get (11) == "two");
+	}
+
+	private void test_big_sort () {
+		Gee.List<int32> big_test_list = new GList<int32> ();
+		for (int i = 0; i < BIG_SORT_SIZE; i++) {
+			big_test_list.add (GLib.Random.int_range (1, BIG_SORT_SIZE - 1));
+		}
+
+		big_test_list.sort ();
+
+		for (int i = 1; i < BIG_SORT_SIZE; i++) {
+			assert (big_test_list[i - 1] <= big_test_list[i]);
+		}
+	}
+
+	private void test_typed_to_array () {
+		// Test with a bool collection
+		Gee.List<bool> bool_list = new GList<bool> ();
+		assert (bool_list.add (true));
+		assert (bool_list.add (true));
+		assert (bool_list.add (false));
+
+		bool[] bool_array = bool_list.to_array ();
+		int index = 0;
+		foreach (bool element in bool_list) {
+			assert (element == bool_array[index++]);
+		}
+
+		// Test with an int collection
+		Gee.List<int> int_list = new GList<int> ();
+		assert (int_list.add (1));
+		assert (int_list.add (2));
+		assert (int_list.add (3));
+
+		int[] int_array = int_list.to_array ();
+		index = 0;
+		foreach (int element in int_list) {
+			assert (element == int_array[index++]);
+		}
+
+		// Test with a double collection
+		Gee.List<double?> double_list = new GList<double?> ();
+		assert (double_list.add (1.0d));
+		assert (double_list.add (1.5d));
+		assert (double_list.add (2.0d));
+
+#if VALA_0_16
+		double?[] double_array = double_list.to_array ();
+#else
+		double[] double_array = double_list.to_array ();
+#endif
+		index = 0;
+		foreach (double element in double_list) {
+			assert (element == double_array[index++]);
+		}
+	}
+}
diff --git a/tests/testmain.vala b/tests/testmain.vala
index 20068e4..31f6039 100644
--- a/tests/testmain.vala
+++ b/tests/testmain.vala
@@ -44,6 +44,7 @@ void main (string[] args) {
 	TestSuite.get_root ().add_suite (new TreeMultiMapTests ().get_suite ());
 	TestSuite.get_root ().add_suite (new TreeMultiSetTests ().get_suite ());
 	TestSuite.get_root ().add_suite (new TreeSetTests ().get_suite ());
+	TestSuite.get_root ().add_suite (new GListTests ().get_suite ());
 
 	Test.run ();
 }
