[Jython-checkins] jython: memoryview: cache the hash

jeff.allen jython-checkins at python.org
Mon Oct 14 23:54:37 CEST 2013


http://hg.python.org/jython/rev/512a3f3cb6e2
changeset:   7134:512a3f3cb6e2
user:        Jeff Allen <ja.py at farowl.co.uk>
date:        Mon Oct 14 22:03:06 2013 +0100
summary:
  memoryview: cache the hash
The hash, once used, must survive release() in case the mv has been used as a key.

files:
  Lib/test/test_memoryview.py           |   3 +-
  src/org/python/core/PyMemoryView.java |  27 ++++++++++-----
  2 files changed, 19 insertions(+), 11 deletions(-)


diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py
--- a/Lib/test/test_memoryview.py
+++ b/Lib/test/test_memoryview.py
@@ -310,8 +310,7 @@
         self.assertEqual(hash(m), hash(b"abcdef"))
         # Releasing the memoryview keeps the stored hash value (as with weakrefs)
         m.release()
-        # XXX Hashing a released view always an error in Jython: should it be?
-        # self.assertEqual(hash(m), hash(b"abcdef"))
+        self.assertEqual(hash(m), hash(b"abcdef"))
 
         # Hashing a memoryview for the first time after it is released
         # results in an error (as with weakrefs).
diff --git a/src/org/python/core/PyMemoryView.java b/src/org/python/core/PyMemoryView.java
--- a/src/org/python/core/PyMemoryView.java
+++ b/src/org/python/core/PyMemoryView.java
@@ -33,6 +33,9 @@
     private PyObject strides;
     /** Cache the result of getting suboffsets here. */
     private PyObject suboffsets;
+    /** Hash value cached (so we still know it after {@link #release()} is called. */
+    private int hashCache;
+    private boolean hashCacheValid = false;
 
     /**
      * Construct a PyMemoryView from a PyBuffer interface. The buffer so obtained will be writable
@@ -203,12 +206,18 @@
 
     @ExposedMethod
     final int memoryview___hash__() {
-        checkNotReleased();
-        if (backing.isReadonly()) {
-            return backing.toString().hashCode();
-        } else {
-            throw Py.ValueError("cannot hash writable memoryview object");
+        if (!hashCacheValid) {
+            // We'll have to calculate it: only possible if not released
+            checkNotReleased();
+            // And if not mutable
+            if (backing.isReadonly()) {
+                hashCache = backing.toString().hashCode();
+                hashCacheValid = true;
+            } else {
+                throw Py.ValueError("cannot hash writable memoryview object");
+            }
         }
+        return hashCache;
     }
 
     /*
@@ -299,8 +308,8 @@
      * values, and there is no concept of a released <code>memoryview</code>. In Python 3,
      * <code>memoryview</code> objects are not ordered but may be tested for equality: a
      * <code>memoryview</code> is always equal to itself, and distinct <code>memoryview</code>
-     * objects are equal if they are not released, and view equal bytes. This method supports
-     * the Python 2.7 model, and should probably not survive into Jython 3.
+     * objects are equal if they are not released, and view equal bytes. This method supports the
+     * Python 2.7 model, and should probably not survive into Jython 3.
      *
      * @param b
      * @return 1, 0 or -1 as this>b, this==b, or this<b respectively, or -2 if the comparison is
@@ -346,8 +355,8 @@
      * values, and there is no concept of a released <code>memoryview</code>. In Python 3,
      * <code>memoryview</code> objects are not ordered but may be tested for equality: a
      * <code>memoryview</code> is always equal to itself, and distinct <code>memoryview</code>
-     * objects are equal if they are not released, and view equal bytes. This method supports
-     * a compromise between of the two and should be rationalised in Jython 3.
+     * objects are equal if they are not released, and view equal bytes. This method supports a
+     * compromise between of the two and should be rationalised in Jython 3.
      *
      * @param b
      * @return 0 if this==b, or +1 or -1 if this!=b, or -2 if the comparison is not implemented

-- 
Repository URL: http://hg.python.org/jython


More information about the Jython-checkins mailing list