[svn:parrot] r40218 - branches/orderedhash_revamp/src/pmc

bacek at svn.parrot.org bacek at svn.parrot.org
Wed Jul 22 23:14:20 UTC 2009


Author: bacek
Date: Wed Jul 22 23:14:19 2009
New Revision: 40218
URL: https://trac.parrot.org/parrot/changeset/40218

Log:
Initial draft how OrderedHash implementation can look like.

Modified:
   branches/orderedhash_revamp/src/pmc/orderedhash.pmc

Modified: branches/orderedhash_revamp/src/pmc/orderedhash.pmc
==============================================================================
--- branches/orderedhash_revamp/src/pmc/orderedhash.pmc	Wed Jul 22 08:28:14 2009	(r40217)
+++ branches/orderedhash_revamp/src/pmc/orderedhash.pmc	Wed Jul 22 23:14:19 2009	(r40218)
@@ -8,28 +8,66 @@
 
 =head1 DESCRIPTION
 
-C<OrderedHash> extends C<Hash> to provide the interfaces of C<array> and
-C<hash>. To achieve ordering, hash there are a few restrictions:
-C<delete_keyed> never removes items; they are just nulled.
-
-Please note that if values are set via integer idx, these indices have to be in
-strict order. Using C<push_xx> simplifies this task.  This creates a key
-"\1idx" for C<idx> and is therefore not fully transparent.
+C<OrderedHash> provide the interfaces of C<array> and
+C<hash>.
 
-There are two iterator interfaces:
+Some limitations:
 
 =over 4
 
-=item * retrieve values (in creation order)
+=item *
 
-Please note that after a C<delete_keyed> operation, iterating over
-values doesn't work any more.  You'll get an error 'No such key'.
+Keys are always STRING*.
 
-=item * retrieve keys (in creation order)
+=item *
+
+Values are always PMC*.
+
+=back
+
+To archive ordering for each item we store:
+
+=over 4
+
+=item * C<key>
+
+Original key
+
+=item * C<value>
+
+Original value
+
+=item * C<next>
+
+Pointer to next C<item>
+
+=item * C<prev>
+
+Pointer to previous C<item>
 
 =back
 
-See F<t/pmc/orderedhash.t>.
+OrderedHash stores next things:
+
+=over 4
+
+=item * C<hash>
+
+Lookup hash for values.
+
+=item * C<first>
+
+Pointer to first inserted value.
+
+=item * C<last>
+
+Pointer to last inserter value.
+
+=back
+
+See F<t/pmc/orderedhash.t> for test cases.
+
+Overall design heavily inspired by C<Tie::StoredOrderHash>.
 
 =head2 Methods
 
@@ -39,7 +77,51 @@
 
 */
 
-pmclass OrderedHash extends Hash need_ext provides array provides hash {
+/* To avoid creating OrderedHashItem PMC we reuse FixedPMCArray PMC */
+/* So, there is indexes to avoid using of "magick constants" */
+enum ORDERED_HASH_ITEM_PART {
+    ORDERED_HASH_ITEM_KEY   = 0,
+    ORDERED_HASH_ITEM_VALUE = 1,
+    ORDERED_HASH_ITEM_PREV  = 2,
+    ORDERED_HASH_ITEM_NEXT  = 3,
+    ORDERED_HASH_ITEM_MAX   = 4,
+};
+
+/* Create new stored item. FixedPMCArray of (key, value, prev, next). */
+static PMC*
+create_item(PARROT_INTERP, ARGIN(PMC *key), ARGIN(PMC *value)) {
+    PMC *ret = pmc_new(interp, enum_class_FixedPMCArray);
+    VTABLE_set_integer_native(interp, ret, ORDERED_HASH_ITEM_MAX);
+
+    VTABLE_set_pmc_keyed_int(interp, ret, ORDERED_HASH_ITEM_KEY, key);
+    VTABLE_set_pmc_keyed_int(interp, ret, ORDERED_HASH_ITEM_VALUE, value);
+    return ret;
+}
+
+pmclass OrderedHash need_ext provides array provides hash {
+    ATTR PMC*   hash;   /* key -> (value, prev, next) tuple */
+    ATTR PMC*   first;  /* Pointer to first inserted value  */
+    ATTR PMC*   last;   /* Pointer to last inserted value   */
+
+/*
+
+=item C<void init()>
+
+Create new instance of OrderedHash.
+
+=cut
+
+*/
+
+    VTABLE void init() {
+        Parrot_OrderedHash_attributes * const attrs =
+                mem_allocate_zeroed_typed(Parrot_OrderedHash_attributes);
+
+        PMC_data(SELF)  = attrs;
+        attrs->lookup   = pmc_new(INTERP, enum_class_Hash);
+
+        PObj_custom_mark_destroy_SETALL(SELF);
+    }
 
 /*
 
@@ -52,27 +134,18 @@
 */
 
     VTABLE void mark() {
-        Hash * const h = (Hash *)SELF.get_pointer();
-        INTVAL  i;
+        Parrot_OrderedHash_attributes * const attrs =
+                PARROT_ORDEREDHASH(SELF);
 
-        if (!h)
-            return;
+        if (attrs->lookup)
+            Parrot_gc_mark_PObj_alive(INTERP, attrs->lookup);
 
-        /* RT #53890 - keys can be NULL on purpose; move to src/hash.c ? */
-        for (i = h->mask; i >= 0; --i) {
-            HashBucket *b = h->bi[i];
-
-            while (b) {
-
-                if (b->key) {
-                    Parrot_gc_mark_PObj_alive(interp, (PObj *)b->key);
-                    if (b->value)
-                        Parrot_gc_mark_PObj_alive(interp, (PObj *)b->value);
-                }
+        /* Don't mark C<first> and C<last>. They are in lookup hash anyway */
+    }
 
-                b = b->next;
-            }
-        }
+
+    VTABLE void destroy() {
+        mem_sys_free(PMC_data(SELF));
     }
 
 /*


More information about the parrot-commits mailing list