summaryrefslogtreecommitdiff
path: root/cffi/backend_ctypes.py
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2016-09-03 20:04:31 +0200
committerArmin Rigo <arigo@tunes.org>2016-09-03 20:04:31 +0200
commitd114114c36d8ffdb73321b810c8732fefdf80604 (patch)
tree9ce8d6fa3bbb422608b1759b4ccaf6fb045b1bb4 /cffi/backend_ctypes.py
parent95559d143194836d781945e40b8ff0914b684315 (diff)
downloadcffi-d114114c36d8ffdb73321b810c8732fefdf80604.tar.gz
Issue #282: probable test and fix
Diffstat (limited to 'cffi/backend_ctypes.py')
-rw-r--r--cffi/backend_ctypes.py38
1 files changed, 22 insertions, 16 deletions
diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
index b2579b3..ed2e6cd 100644
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -997,29 +997,35 @@ class CTypesBackend(object):
assert onerror is None # XXX not implemented
return BType(source, error)
+ _weakref_cache_ref = None
+
def gcp(self, cdata, destructor):
- BType = self.typeof(cdata)
+ if self._weakref_cache_ref is None:
+ import weakref
+ class MyRef(weakref.ref):
+ def __eq__(self, other):
+ return self() is other()
+ def __ne__(self, other):
+ return self() is not other()
+ self._weakref_cache_ref = {}, MyRef
+ weak_cache, MyRef = self._weakref_cache_ref
if destructor is None:
- if not (hasattr(BType, '_gcp_type') and
- BType._gcp_type is BType):
+ try:
+ del weak_cache[MyRef(cdata)]
+ except KeyError:
raise TypeError("Can remove destructor only on a object "
"previously returned by ffi.gc()")
- cdata._destructor = None
return None
- try:
- gcp_type = BType._gcp_type
- except AttributeError:
- class CTypesDataGcp(BType):
- __slots__ = ['_orig', '_destructor']
- def __del__(self):
- if self._destructor is not None:
- self._destructor(self._orig)
- gcp_type = BType._gcp_type = CTypesDataGcp
- new_cdata = self.cast(gcp_type, cdata)
- new_cdata._orig = cdata
- new_cdata._destructor = destructor
+ def remove(k):
+ cdata, destructor = weak_cache.pop(k, (None, None))
+ if destructor is not None:
+ destructor(cdata)
+
+ new_cdata = self.cast(self.typeof(cdata), cdata)
+ assert new_cdata is not cdata
+ weak_cache[MyRef(new_cdata, remove)] = (cdata, destructor)
return new_cdata
typeof = type