Commit acbcf3a7 authored by Tim Peters's avatar Tim Peters

Move WeakSet into ZODB.utils, so DB can use it too.

If nothing else, it highlights that the transaction package
got put in a wrong place (it and ZODB depend on each other).
parent a3d98800
...@@ -18,6 +18,7 @@ from struct import pack, unpack ...@@ -18,6 +18,7 @@ from struct import pack, unpack
from binascii import hexlify from binascii import hexlify
import cPickle import cPickle
import cStringIO import cStringIO
import weakref
from persistent.TimeStamp import TimeStamp from persistent.TimeStamp import TimeStamp
...@@ -34,6 +35,7 @@ __all__ = ['z64', ...@@ -34,6 +35,7 @@ __all__ = ['z64',
'positive_id', 'positive_id',
'get_refs', 'get_refs',
'readable_tid_repr', 'readable_tid_repr',
'WeakSet',
] ]
z64 = '\0'*8 z64 = '\0'*8
...@@ -164,3 +166,43 @@ def get_refs(pickle): ...@@ -164,3 +166,43 @@ def get_refs(pickle):
u.noload() # class info u.noload() # class info
u.noload() # instance state info u.noload() # instance state info
return refs return refs
# A simple implementation of weak sets, supplying just enough of Python's
# sets.Set interface for our needs.
class WeakSet(object):
"""A set of objects that doesn't keep its elements alive.
The objects in the set must be weakly referencable.
The objects need not be hashable, and need not support comparison.
Two objects are considered to be the same iff their id()s are equal.
When the only references to an object are weak references (including
those from WeakSets), the object can be garbage-collected, and
will vanish from any WeakSets it may be a member of at that time.
"""
def __init__(self):
# Map id(obj) to obj. By using ids as keys, we avoid requiring
# that the elements be hashable or comparable.
self.data = weakref.WeakValueDictionary()
def __len__(self):
return len(self.data)
# Same as a Set, add obj to the collection.
def add(self, obj):
self.data[id(obj)] = obj
# Same as a Set, remove obj from the collection, and raise
# KeyError if obj not in the collection.
def remove(self, obj):
del self.data[id(obj)]
# Return a list of all the objects in the collection.
# Because a weak dict is used internally, iteration
# is dicey (the underlying dict may change size during
# iteration, due to gc or activity from other threads).
# as_list() attempts to be safe.
def as_list(self):
return self.data.values()
...@@ -18,7 +18,6 @@ are associated with the right transaction. ...@@ -18,7 +18,6 @@ are associated with the right transaction.
""" """
import thread import thread
import weakref
from transaction._transaction import Transaction from transaction._transaction import Transaction
...@@ -28,48 +27,16 @@ from transaction._transaction import Transaction ...@@ -28,48 +27,16 @@ from transaction._transaction import Transaction
# practice not to explicitly close Connection objects, and keeping # practice not to explicitly close Connection objects, and keeping
# a Connection alive keeps a potentially huge number of other objects # a Connection alive keeps a potentially huge number of other objects
# alive (e.g., the cache, and everything reachable from it too). # alive (e.g., the cache, and everything reachable from it too).
# Therefore we use "weak sets" internally.
# #
# Therefore we use "weak sets" internally. The implementation here # Obscure: because of the __init__.py maze, we can't import WeakSet
# implements just enough of Python's sets.Set interface for our needs. # at top level here.
class WeakSet(object):
"""A set of objects that doesn't keep its elements alive.
The objects in the set must be weakly referencable.
The objects need not be hashable, and need not support comparison.
Two objects are considered to be the same iff their id()s are equal.
When the only references to an object are weak references (including
those from WeakSets), the object can be garbage-collected, and
will vanish from any WeakSets it may be a member of at that time.
"""
def __init__(self):
# Map id(obj) to obj. By using ids as keys, we avoid requiring
# that the elements be hashable or comparable.
self.data = weakref.WeakValueDictionary()
# Same as a Set, add obj to the collection.
def add(self, obj):
self.data[id(obj)] = obj
# Same as a Set, remove obj from the collection, and raise
# KeyError if obj not in the collection.
def remove(self, obj):
del self.data[id(obj)]
# Return a list of all the objects in the collection.
# Because a weak dict is used internally, iteration
# is dicey (the underlying dict may change size during
# iteration, due to gc or activity from other threads).
# as_list() attempts to be safe.
def as_list(self):
return self.data.values()
class TransactionManager(object): class TransactionManager(object):
def __init__(self): def __init__(self):
from ZODB.utils import WeakSet
self._txn = None self._txn = None
self._synchs = WeakSet() self._synchs = WeakSet()
...@@ -135,6 +102,8 @@ class ThreadTransactionManager(object): ...@@ -135,6 +102,8 @@ class ThreadTransactionManager(object):
del self._txns[tid] del self._txns[tid]
def registerSynch(self, synch): def registerSynch(self, synch):
from ZODB.utils import WeakSet
tid = thread.get_ident() tid = thread.get_ident()
ws = self._synchs.get(tid) ws = self._synchs.get(tid)
if ws is None: if ws is None:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment