]> granicus.if.org Git - python/commitdiff
Issue 23261: Clean-up the hack to store the set.pop() search finger in a hash field...
authorRaymond Hettinger <python@rcn.com>
Sun, 18 Jan 2015 21:12:42 +0000 (13:12 -0800)
committerRaymond Hettinger <python@rcn.com>
Sun, 18 Jan 2015 21:12:42 +0000 (13:12 -0800)
Include/setobject.h
Lib/test/test_sys.py
Objects/setobject.c

index 8f8e34f254688d63d3e853bc88a74b515cb0aee2..79124d0f6ed68fb540f17cd5d66ab6db28c90029 100644 (file)
@@ -14,9 +14,7 @@ extern "C" {
 2. Active:  key != NULL and key != dummy
 3. Dummy:   key == dummy
 
-Note: .pop() abuses the hash field of an Unused or Dummy slot to
-hold a search finger.  The hash field of Unused or Dummy slots has
-no meaning otherwise.
+The hash field of Unused or Dummy slots have no meaning.
 */
 
 #define PySet_MINSIZE 8
@@ -59,6 +57,7 @@ typedef struct _setobject {
     Py_hash_t hash;             /* Only used by frozenset objects */
     setentry smalltable[PySet_MINSIZE];
 
+    Py_ssize_t finger;          /* Search finger for pop() */
     PyObject *weakreflist;      /* List of weak references */
 } PySetObject;
 
index ec2eaf3babb758922db863aeed6d9de674f19a9b..2da987f3d6501bc9ca3b474105cdfaef2a0aac3c 100644 (file)
@@ -994,7 +994,7 @@ class SizeofTest(unittest.TestCase):
         # frozenset
         PySet_MINSIZE = 8
         samples = [[], range(10), range(50)]
-        s = size('3n2P' + PySet_MINSIZE*'nP' + 'nP')
+        s = size('3n2P' + PySet_MINSIZE*'nP' + '2nP')
         for sample in samples:
             minused = len(sample)
             if minused == 0: tmp = 1
index 4fba897b1f765fb929080eecd286c438595d54b3..9dc88c834ef58d814889c374c67c80726f686ffc 100644 (file)
@@ -668,32 +668,22 @@ set_pop(PySetObject *so)
         return NULL;
     }
 
-    /* Set entry to "the first" unused or dummy set entry.  We abuse
-     * the hash field of slot 0 to hold a search finger:
-     * If slot 0 has a value, use slot 0.
-     * Else slot 0 is being used to hold a search finger,
-     * and we use its hash value as the first index to look.
+    i = so->finger;
+    /* This may be a legit search finger, or it may be a once legit
+     * search finger that's out of bounds now (due to wrapping or
+     * resizing).  We simply make sure it's in bounds now.
      */
-    entry = &so->table[0];
-    if (entry->key == NULL || entry->key == dummy) {
-        i = entry->hash;
-        /* The hash field may be a real hash value, or it may be a
-         * legit search finger, or it may be a once-legit search
-         * finger that's out of bounds now because it wrapped around
-         * or the table shrunk -- simply make sure it's in bounds now.
-         */
-        if (i > so->mask || i < 1)
-            i = 1;              /* skip slot 0 */
-        while ((entry = &so->table[i])->key == NULL || entry->key==dummy) {
-            i++;
-            if (i > so->mask)
-                i = 1;
-        }
+    if (i > so->mask)
+        i = 0;
+    while ((entry = &so->table[i])->key == NULL || entry->key==dummy) {
+        i++;
+        if (i > so->mask)
+            i = 0;
     }
     key = entry->key;
     entry->key = dummy;
     so->used--;
-    so->table[0].hash = i + 1;  /* next place to start */
+    so->finger = i + 1;         /* next place to start */
     return key;
 }
 
@@ -1012,6 +1002,7 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
     so->table = so->smalltable;
     so->lookup = set_lookkey_unicode;
     so->hash = -1;
+    so->finger = 0;
     so->weakreflist = NULL;
 
     if (iterable != NULL) {