[h5py] 422/455: Threading fixes
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:57 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 ab54dcacfa7e32fd9dac6345ca5688f2d1ee2a35
Author: andrewcollette <andrew.collette at gmail.com>
Date: Sun Feb 21 22:43:58 2010 +0000
Threading fixes
---
h5py/h5e.pyx | 15 ++++++++----
h5py/highlevel.py | 53 ++++++++++++++++++++++++++++++++++++++---
h5py/tests/high/test_threads.py | 43 +++++++++++++++++++++++++++++++++
3 files changed, 103 insertions(+), 8 deletions(-)
diff --git a/h5py/h5e.pyx b/h5py/h5e.pyx
index 982504f..5b5d2d2 100644
--- a/h5py/h5e.pyx
+++ b/h5py/h5e.pyx
@@ -394,8 +394,8 @@ cpdef int register_thread() except -1:
raise RuntimeError("Failed to register HDF5 exception callback")
return 0
-cpdef int unregister_thread() except -1:
- """ ()
+cpdef int unregister_thread(bint silent=0) except -1:
+ """ (silent=False)
Unregister the current thread, turning off HDF5 exception support.
@@ -404,10 +404,15 @@ cpdef int unregister_thread() except -1:
with the HDF5 error subsystem as they wish. Call register_thread()
again to re-enable exception support.
- Does not affect any other thread. Safe to call more than once.
+ Does not affect any other thread. Safe to call more than once. If
+ "silent" is specified, uses a NULL error handler rather than H5Eprint.
"""
- if H5Eset_auto(H5Eprint, NULL) < 0:
- raise RuntimeError("Failed to unregister HDF5 exception callback")
+ if not silent:
+ if H5Eset_auto(H5Eprint, NULL) < 0:
+ raise RuntimeError("Failed to unregister HDF5 exception callback")
+ else:
+ if H5Eset_auto(NULL, NULL) < 0:
+ raise RuntimeError("Failed to unregister HDF5 exception callback")
return 0
cdef err_cookie disable_errors() except *:
diff --git a/h5py/highlevel.py b/h5py/highlevel.py
index afe5466..d8f529c 100644
--- a/h5py/highlevel.py
+++ b/h5py/highlevel.py
@@ -39,11 +39,14 @@ from h5py import h5, h5f, h5g, h5s, h5t, h5d, h5a, \
version, filters, _extras
import h5py.selections as sel
+from h5py.h5e import register_thread
+
config = h5.get_config()
phil = threading.RLock()
def is_hdf5(fname):
""" Determine if a file is valid HDF5 (False if it doesn't exist). """
+ register_thread()
fname = os.path.abspath(fname)
if os.path.isfile(fname):
@@ -88,6 +91,7 @@ class HLObject(object):
@property
def file(self):
"""Return a File instance associated with this object"""
+ register_thread()
fid = h5i.get_file_id(self.id)
return File(None, bind=fid)
@@ -116,6 +120,7 @@ class HLObject(object):
@property
def name(self):
"""Name of this object in the HDF5 file. Not necessarily unique."""
+ register_thread()
return h5i.get_name(self.id)
@_extras.cproperty('_attrs')
@@ -136,6 +141,7 @@ class HLObject(object):
@_extras.cproperty('_ref')
def ref(self):
""" An (opaque) HDF5 reference to this object """
+ register_thread()
return h5r.create(self.id, '.', h5r.OBJECT)
def __init__(self, oid):
@@ -144,11 +150,14 @@ class HLObject(object):
self._id = oid
def __nonzero__(self):
+ register_thread()
return self.id.__nonzero__()
def __hash__(self):
+ register_thread()
return hash(self.id)
def __eq__(self, other):
+ register_thread()
if hasattr(other, 'id'):
return self.id == other.id
return False
@@ -248,6 +257,7 @@ class Group(HLObject, _DictCompat):
It's recommended to use __getitem__ or create_group() rather than
calling the constructor directly.
"""
+ register_thread()
with phil:
if _rawid is not None:
id = _rawid
@@ -321,6 +331,7 @@ class Group(HLObject, _DictCompat):
values are stored as scalar datasets. Raise ValueError if we
can't understand the resulting array dtype.
"""
+ register_thread()
with phil:
if config.API_18:
self._set18(name, obj)
@@ -366,6 +377,7 @@ class Group(HLObject, _DictCompat):
def __getitem__(self, name):
""" Open an object attached to this group.
"""
+ register_thread()
with phil:
if isinstance(name, h5r.Reference):
@@ -377,18 +389,22 @@ class Group(HLObject, _DictCompat):
def __delitem__(self, name):
""" Delete (unlink) an item from this group. """
+ register_thread()
self.id.unlink(name)
def __len__(self):
""" Number of members attached to this group """
+ register_thread()
return self.id.get_num_objs()
def __contains__(self, name):
""" Test if a member name exists """
+ register_thread()
return name in self.id
def __iter__(self):
""" Iterate over member names """
+ register_thread()
return self.id.__iter__()
def create_group(self, name):
@@ -490,6 +506,7 @@ class Group(HLObject, _DictCompat):
If True, return SoftLink and ExternalLink instances instead
of the objects they point to.
"""
+ register_thread()
with phil:
if not name in self:
@@ -557,6 +574,7 @@ class Group(HLObject, _DictCompat):
['MyGroup', 'MyCopy']
"""
+ register_thread()
if not config.API_18:
raise NotImplementedError("This feature is only available with HDF5 1.8.0 and later")
@@ -604,6 +622,7 @@ class Group(HLObject, _DictCompat):
>>> list_of_names = []
>>> f.visit(list_of_names.append)
"""
+ register_thread()
if not config.API_18:
raise NotImplementedError("This feature is only available with HDF5 1.8.0 and later")
@@ -634,6 +653,7 @@ class Group(HLObject, _DictCompat):
>>> f = File('foo.hdf5')
>>> f.visititems(func)
"""
+ register_thread()
if not config.API_18:
raise NotImplementedError("This feature is only available with HDF5 1.8.0 and later")
@@ -702,6 +722,7 @@ class File(Group):
@property
def filename(self):
"""File name on disk"""
+ register_thread()
name = h5f.get_name(self.fid)
# Note the exception can happen in one of two ways:
# 1. The name doesn't comply with the file system encoding;
@@ -721,6 +742,7 @@ class File(Group):
@property
def mode(self):
"""Python mode used to open file"""
+ register_thread()
mode = self._modes.get(self)
if mode is None and config.API_18:
mode = {h5f.ACC_RDONLY: 'r', h5f.ACC_RDWR: 'r+'}.get(self.fid.get_intent())
@@ -729,6 +751,7 @@ class File(Group):
@property
def driver(self):
"""Low-level HDF5 file driver used to open file"""
+ register_thread()
drivers = {h5fd.SEC2: 'sec2', h5fd.STDIO: 'stdio',
h5fd.CORE: 'core', h5fd.FAMILY: 'family',
h5fd.WINDOWS: 'windows'}
@@ -753,6 +776,7 @@ class File(Group):
- 'core' mmap driver
- 'family' Multi-part file driver
"""
+ register_thread()
if "bind" in kwds:
self.fid = kwds["bind"]
else:
@@ -819,6 +843,7 @@ class File(Group):
def close(self):
""" Close this HDF5 file. All open objects will be invalidated.
"""
+ register_thread()
with phil:
while self.fid:
self.fid.close()
@@ -826,17 +851,20 @@ class File(Group):
def flush(self):
""" Tell the HDF5 library to flush its buffers.
"""
+ register_thread()
h5f.flush(self.fid)
def __enter__(self):
return self
def __exit__(self,*args):
+ register_thread()
with phil:
if self.id._valid:
self.close()
def __repr__(self):
+ register_thread()
if not self:
return "<Closed HDF5 file>"
return '<HDF5 file "%s" (mode %s, %s)>' % \
@@ -845,10 +873,12 @@ class File(Group):
def __hash__(self):
+ register_thread()
return hash(self.fid)
def __eq__(self, other):
# Python requires that objects which compare equal hash the same.
# Therefore comparison to generic Group objects is impossible
+ register_thread()
if hasattr(other, 'fid'):
return self.fid == other.fid
return False
@@ -859,7 +889,7 @@ class _RegionProxy(object):
self.id = dset.id
def __getitem__(self, args):
-
+ register_thread()
selection = sel.select(self.id.shape, args, dsid=self.id)
return h5r.create(self.id, '.', h5r.DATASET_REGION, selection._id)
@@ -881,6 +911,7 @@ class Dataset(HLObject):
def _g_shape(self):
"""Numpy-style shape tuple giving dataset dimensions"""
+ register_thread()
return self.id.shape
def _s_shape(self, shape):
@@ -891,6 +922,7 @@ class Dataset(HLObject):
@_extras.cproperty('_dtype')
def dtype(self):
"""Numpy dtype representing the datatype"""
+ register_thread()
return self.id.dtype
@property
@@ -913,6 +945,7 @@ class Dataset(HLObject):
@property
def chunks(self):
"""Dataset chunks (or None)"""
+ register_thread()
dcpl = self._dcpl
if dcpl.get_layout() == h5d.CHUNKED:
return dcpl.get_chunk()
@@ -943,6 +976,7 @@ class Dataset(HLObject):
@property
def maxshape(self):
+ register_thread()
with phil:
space = self.id.get_space()
dims = space.get_simple_extent_dims(True)
@@ -995,6 +1029,7 @@ class Dataset(HLObject):
provided, the constructor will guess an appropriate chunk shape.
Please note none of these are allowed for scalar datasets.
"""
+ register_thread()
with phil:
if _rawid is not None:
id = _rawid
@@ -1072,6 +1107,7 @@ class Dataset(HLObject):
grown or shrunk independently. The coordinates of existing data is
fixed.
"""
+ register_thread()
with phil:
if not config.API_18:
@@ -1138,6 +1174,7 @@ class Dataset(HLObject):
* Boolean "mask" array indexing
* Advanced dataspace selection via the "selections" module
"""
+ register_thread()
with phil:
args = args if isinstance(args, tuple) else (args,)
@@ -1191,6 +1228,7 @@ class Dataset(HLObject):
Classes from the "selections" module may also be used to index.
"""
+ register_thread()
with phil:
args = args if isinstance(args, tuple) else (args,)
@@ -1256,7 +1294,7 @@ class Dataset(HLObject):
Broadcasting is supported for simple indexing.
"""
-
+ register_thread()
if source_sel is None:
source_sel = sel.SimpleSelection(self.shape)
else:
@@ -1280,7 +1318,7 @@ class Dataset(HLObject):
Broadcasting is supported for simple indexing.
"""
-
+ register_thread()
if source_sel is None:
source_sel = sel.SimpleSelection(source.shape)
else:
@@ -1337,6 +1375,7 @@ class AttributeManager(_DictCompat):
def __getitem__(self, name):
""" Read the value of an attribute.
"""
+ register_thread()
with phil:
attr = h5a.open(self._id, name)
@@ -1361,6 +1400,7 @@ class AttributeManager(_DictCompat):
def __delitem__(self, name):
""" Delete an attribute (which must already exist). """
+ register_thread()
h5a.delete(self._id, name)
def create(self, name, data, shape=None, dtype=None):
@@ -1373,6 +1413,7 @@ class AttributeManager(_DictCompat):
dtype: Data type of the attribute. Overrides data.dtype if both
are given. Must be conversion-compatible with data.dtype.
"""
+ register_thread()
with phil:
if data is not None:
data = numpy.asarray(data, order='C', dtype=dtype)
@@ -1409,6 +1450,7 @@ class AttributeManager(_DictCompat):
If the attribute doesn't exist, it will be automatically created.
"""
+ register_thread()
with phil:
if not name in self:
self[name] = value
@@ -1426,10 +1468,12 @@ class AttributeManager(_DictCompat):
def __len__(self):
""" Number of attributes attached to the object. """
# I expect we will not have more than 2**32 attributes
+ register_thread()
return h5a.get_num_attrs(self._id)
def __iter__(self):
""" Iterate over the names of attributes. """
+ register_thread()
with phil:
attrlist = []
def iter_cb(name, *args):
@@ -1441,6 +1485,7 @@ class AttributeManager(_DictCompat):
def __contains__(self, name):
""" Determine if an attribute exists, by name. """
+ register_thread()
return h5a.exists(self._id, name)
def __repr__(self):
@@ -1463,11 +1508,13 @@ class Datatype(HLObject):
@property
def dtype(self):
"""Numpy dtype equivalent for this datatype"""
+ register_thread()
return self.id.dtype
def __init__(self, grp, name, _rawid=None):
""" Private constructor.
"""
+ register_thread()
with phil:
id = _rawid if _rawid is not None else h5t.open(grp.id, name)
HLObject.__init__(self, id)
diff --git a/h5py/tests/high/test_threads.py b/h5py/tests/high/test_threads.py
new file mode 100644
index 0000000..780f800
--- /dev/null
+++ b/h5py/tests/high/test_threads.py
@@ -0,0 +1,43 @@
+import sys
+import threading
+import h5py
+
+from h5py import tests
+
+class TestThreads(tests.HTest):
+
+ def test_exc(self):
+ """ (Threads) Exception support in non-native threads """
+
+ results = {}
+
+ def badfunc():
+
+ h5py.h5e.unregister_thread(silent=True)
+ try:
+ h5py.h5f.is_hdf5('missing')
+ except Exception:
+ results['badfunc'] = False
+ else:
+ results['badfunc'] = True
+
+ def goodfunc():
+ h5py.h5e.register_thread()
+ try:
+ h5py.h5f.is_hdf5('missing')
+ except IOError:
+ results['goodfunc'] = True
+ else:
+ results['goodfunc'] = False
+
+ t = threading.Thread(target=badfunc)
+ t.start()
+ t.join()
+ t = threading.Thread(target=goodfunc)
+ t.start()
+ t.join()
+ self.assert_(results['goodfunc'])
+ self.assert_(results['badfunc'])
+
+
+
--
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