Commit e502e223 authored by Tim Peters's avatar Tim Peters

Give WeakSet a direct map() implementation.

This spares clients from having to do it themselves repeatedly.
A dubious consequences is that Transaction.__init__ now requires a
WeakSet of synchronizer objects (or None -- so it's not a
catastrophic requirement, just irksome).
parent 1e730a8c
......@@ -132,10 +132,7 @@ class _ConnectionPool(object):
# For every live connection c, invoke f(c).
def map(self, f):
for wr in self.all.as_weakref_list():
c = wr()
if c is not None:
f(c)
self.all.map(f)
class DB(object):
"""The Object Database
......
......@@ -221,6 +221,14 @@ class WeakSet(object):
def remove(self, obj):
del self.data[id(obj)]
# f is a one-argument function. Execute f(elt) for each elt in the
# set. f's return value is ignored.
def map(self, f):
for wr in self.as_weakref_list():
elt = wr()
if elt is not None:
f(elt)
# Return a list of weakrefs to 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
......
......@@ -43,12 +43,12 @@ class TransactionManager(object):
def begin(self):
if self._txn is not None:
self._txn.abort()
self._txn = Transaction(self._synchs.as_weakref_list(), self)
self._txn = Transaction(self._synchs, self)
return self._txn
def get(self):
if self._txn is None:
self._txn = Transaction(self._synchs.as_weakref_list(), self)
self._txn = Transaction(self._synchs, self)
return self._txn
def free(self, txn):
......@@ -71,8 +71,8 @@ class ThreadTransactionManager(object):
# _threads maps thread ids to transactions
self._txns = {}
# _synchs maps a thread id to a WeakSet of registered synchronizers.
# The set elements are passed to the Transaction constructor,
# because the latter needs to call the synchronizers when it commits.
# The WeakSet is passed to the Transaction constructor, because the
# latter needs to call the synchronizers when it commits.
self._synchs = {}
def begin(self):
......@@ -81,8 +81,6 @@ class ThreadTransactionManager(object):
if txn is not None:
txn.abort()
synchs = self._synchs.get(tid)
if synchs is not None:
synchs = synchs.as_weakref_list()
txn = self._txns[tid] = Transaction(synchs, self)
return txn
......@@ -91,8 +89,6 @@ class ThreadTransactionManager(object):
txn = self._txns.get(tid)
if txn is None:
synchs = self._synchs.get(tid)
if synchs is not None:
synchs = synchs.as_weakref_list()
txn = self._txns[tid] = Transaction(synchs, self)
return txn
......
......@@ -138,7 +138,6 @@ import sys
import thread
import warnings
import traceback
import weakref
from cStringIO import StringIO
# Sigh. In the maze of __init__.py's, ZODB.__init__.py takes 'get'
......@@ -173,8 +172,15 @@ class Transaction(object):
self.status = Status.ACTIVE
# List of resource managers, e.g. MultiObjectResourceAdapters.
self._resources = []
self._synchronizers = synchronizers or []
# Weak set of synchronizer objects to call.
if synchronizers is None:
from ZODB.utils import WeakSet
synchronizers = WeakSet()
self._synchronizers = synchronizers
self._manager = manager
# _adapters: Connection/_p_jar -> MultiObjectResourceAdapter[Sub]
self._adapters = {}
self._voted = {} # id(Connection) -> boolean, True if voted
......@@ -204,14 +210,6 @@ class Transaction(object):
# raised, incorporating this traceback.
self._failure_traceback = None
# Invoke f(synch) for each synch in self._synchronizers.
def _synch_map(self, f):
for wr in self._synchronizers:
assert isinstance(wr, weakref.ref)
synch = wr()
if synch is not None:
f(synch)
# Raise TransactionFailedError, due to commit()/join()/register()
# getting called when the current transaction has already suffered
# a commit failure.
......@@ -295,7 +293,7 @@ class Transaction(object):
self.commit(True)
if not subtransaction:
self._synch_map(lambda s: s.beforeCompletion(self))
self._synchronizers.map(lambda s: s.beforeCompletion(self))
self.status = Status.COMMITTING
try:
......@@ -319,7 +317,7 @@ class Transaction(object):
self.status = Status.COMMITTED
if self._manager:
self._manager.free(self)
self._synch_map(lambda s: s.afterCompletion(self))
self._synchronizers.map(lambda s: s.afterCompletion(self))
self.log.debug("commit")
def _commitResources(self, subtransaction):
......@@ -367,7 +365,7 @@ class Transaction(object):
self._cleanup(L)
finally:
if not subtransaction:
self._synch_map(lambda s: s.afterCompletion(self))
self._synchronizers.map(lambda s: s.afterCompletion(self))
raise t, v, tb
def _cleanup(self, L):
......@@ -433,7 +431,7 @@ class Transaction(object):
def abort(self, subtransaction=False):
if not subtransaction:
self._synch_map(lambda s: s.beforeCompletion(self))
self._synchronizers.map(lambda s: s.beforeCompletion(self))
if subtransaction and self._nonsub:
from ZODB.POSException import TransactionError
......@@ -463,7 +461,7 @@ class Transaction(object):
if not subtransaction:
if self._manager:
self._manager.free(self)
self._synch_map(lambda s: s.afterCompletion(self))
self._synchronizers.map(lambda s: s.afterCompletion(self))
self.log.debug("abort")
if tb is not 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