[h5py] 343/455: Implement new caching/locking system

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:49 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to annotated tag 1.3.0
in repository h5py.

commit 4dd370a270cfacaf404c79a2a389701f62f86857
Author: andrewcollette <andrew.collette at gmail.com>
Date:   Tue Jan 5 05:28:52 2010 +0000

    Implement new caching/locking system
---
 h5py/highlevel.py | 68 ++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 45 insertions(+), 23 deletions(-)

diff --git a/h5py/highlevel.py b/h5py/highlevel.py
index ab27a8c..58c53a3 100644
--- a/h5py/highlevel.py
+++ b/h5py/highlevel.py
@@ -43,6 +43,32 @@ import h5py.selections as sel
 
 config = h5.get_config()
 
+def _memo_property(meth):
+    """ Convenience decorator for memoized properties.
+
+    Intended for read-only, unchanging properties.  Instead of caching values
+    on the instance directly (i.e. self._value = value), stores in a weak-key
+    dictionary as dct[self] = value.
+
+    In addition to not polluting the instance dict, it provides a way to cache
+    values across instances; any two instances which hash to the same value
+    and compare equal will return the same value when the property is read.
+    This allows the sharing of things like file modes and per-file locks,
+    which are tied to the underlying file and not any particular instance.
+
+    Caveats:
+    1. A strong reference is held to the value, so returning self is a bad idea
+    2. Can't initialize the value in a constructor, unlike self._value caching
+    """
+    import functools
+    dct = weakref.WeakKeyDictionary()
+    def wrap(self):
+        if self not in dct:
+            return dct.setdefault(self, meth(self))
+        return dct[self]
+    functools.update_wrapper(wrap, meth)
+    return property(wrap)
+
 def _hbasename(name):
     """ Basename function with more readable handling of trailing slashes"""
     name = pp.basename(pp.normpath(name))
@@ -96,19 +122,21 @@ class HLObject(object):
             name = h5r.get_name(self.ref)
         return name
 
-    @property
+    @_memo_property
     def attrs(self):
         """Provides access to HDF5 attributes. See AttributeManager."""
-        return self._attrs
+        return AttributeManager(self)
 
+    @_memo_property
+    def _file(self):
+        fid = h5i.get_file_id(self.id)
+        return File(None, bind=fid)
+ 
     @property
     def file(self):
         """Return a File instance associated with this object"""
         if isinstance(self, File):
             return self
-        if not hasattr(self, '_file'):
-            fid = h5i.get_file_id(self.id)
-            self._file = File(None, bind=fid)
         return self._file
 
     @property
@@ -240,8 +268,6 @@ class Group(HLObject, _DictCompat):
                 self.id = h5g.create(parent_object.id, name)
             else:
                 self.id = h5g.open(parent_object.id, name)
-
-            self._attrs = AttributeManager(self)
     
     def __setitem__(self, name, obj):
         """ Add an object to the group.  The name must not already be in use.
@@ -634,20 +660,14 @@ class File(Group):
             memb_size:  Maximum file size (default is 2**31-1).
     """
 
-    # We store locks by file hash, rather than manually associating them
-    # with particular File instances.
-    _locks = weakref.WeakKeyDictionary()
-
-    @property
+    @_memo_property
     def _lock(self):
         """ Get an RLock for this file, creating it if necessary.  Locks are
         linked to the "real" underlying HDF5 file, regardless of the number
         of File instances.
         """
-        lock = self._locks.get(self)
-        if lock is None:
-            return self._locks.setdefault(self, threading.RLock())
-        return lock
+        import threading
+        return threading.RLock()
 
     @property
     def filename(self):
@@ -664,10 +684,15 @@ class File(Group):
         except (UnicodeError, LookupError):
             return name
 
-    @property
+    @_memo_property
     def mode(self):
         """Python mode used to open file"""
-        return self._mode
+        if hasattr(self, '_mode'):
+            return self._mode
+        if not config.API_18:
+            return None
+        intent = self.fid.get_intent()
+        return {h5f.ACC_RDONLY: 'r', h5f.ACC_RDWR: 'r+'}.get(intent)
 
     @property
     def driver(self):
@@ -875,9 +900,9 @@ class Dataset(HLObject):
             dims = space.get_simple_extent_dims(True)
             return tuple(x if x != h5s.UNLIMITED else None for x in dims)
 
-    @property
+    @_memo_property
     def regionref(self):
-        return self._regionproxy
+        return _RegionProxy(self)
 
     def __init__(self, group, name,
                     shape=None, dtype=None, data=None,
@@ -984,8 +1009,6 @@ class Dataset(HLObject):
                 if data is not None:
                     self.id.write(h5s.ALL, h5s.ALL, data)
 
-            self._attrs = AttributeManager(self)
-            self._regionproxy = _RegionProxy(self)
             plist = self.id.get_create_plist()
             self._filters = filters.get_filters(plist)
             if plist.get_layout() == h5d.CHUNKED:
@@ -1410,7 +1433,6 @@ class Datatype(HLObject):
         """
         with grp._lock:
             self.id = h5t.open(grp.id, name)
-            self._attrs = AttributeManager(self)
 
     def __repr__(self):
         with self._lock:

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/h5py.git



More information about the debian-science-commits mailing list