From 05dba45fb2e2e380db68b365158cd0c034a2086c Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 17 Aug 2024 00:57:47 +0530 Subject: [PATCH 1/2] avoid _IterationGuard for WeakSet, use copy of the set instead --- Lib/_weakrefset.py | 53 +++++++++------------------------------------- 1 file changed, 10 insertions(+), 43 deletions(-) diff --git a/Lib/_weakrefset.py b/Lib/_weakrefset.py index 489eec714e0d48..2071755d71dfc8 100644 --- a/Lib/_weakrefset.py +++ b/Lib/_weakrefset.py @@ -36,41 +36,26 @@ def __exit__(self, e, t, b): class WeakSet: def __init__(self, data=None): self.data = set() + def _remove(item, selfref=ref(self)): self = selfref() if self is not None: - if self._iterating: - self._pending_removals.append(item) - else: - self.data.discard(item) + self.data.discard(item) + self._remove = _remove - # A list of keys to be removed - self._pending_removals = [] - self._iterating = set() if data is not None: self.update(data) - def _commit_removals(self): - pop = self._pending_removals.pop - discard = self.data.discard - while True: - try: - item = pop() - except IndexError: - return - discard(item) - def __iter__(self): - with _IterationGuard(self): - for itemref in self.data: - item = itemref() - if item is not None: - # Caveat: the iterator will keep a strong reference to - # `item` until it is resumed or closed. - yield item + for itemref in self.data.copy(): + item = itemref() + if item is not None: + # Caveat: the iterator will keep a strong reference to + # `item` until it is resumed or closed. + yield item def __len__(self): - return len(self.data) - len(self._pending_removals) + return len(self.data) def __contains__(self, item): try: @@ -83,21 +68,15 @@ def __reduce__(self): return self.__class__, (list(self),), self.__getstate__() def add(self, item): - if self._pending_removals: - self._commit_removals() self.data.add(ref(item, self._remove)) def clear(self): - if self._pending_removals: - self._commit_removals() self.data.clear() def copy(self): return self.__class__(self) def pop(self): - if self._pending_removals: - self._commit_removals() while True: try: itemref = self.data.pop() @@ -108,18 +87,12 @@ def pop(self): return item def remove(self, item): - if self._pending_removals: - self._commit_removals() self.data.remove(ref(item)) def discard(self, item): - if self._pending_removals: - self._commit_removals() self.data.discard(ref(item)) def update(self, other): - if self._pending_removals: - self._commit_removals() for element in other: self.add(element) @@ -136,8 +109,6 @@ def difference(self, other): def difference_update(self, other): self.__isub__(other) def __isub__(self, other): - if self._pending_removals: - self._commit_removals() if self is other: self.data.clear() else: @@ -151,8 +122,6 @@ def intersection(self, other): def intersection_update(self, other): self.__iand__(other) def __iand__(self, other): - if self._pending_removals: - self._commit_removals() self.data.intersection_update(ref(item) for item in other) return self @@ -184,8 +153,6 @@ def symmetric_difference(self, other): def symmetric_difference_update(self, other): self.__ixor__(other) def __ixor__(self, other): - if self._pending_removals: - self._commit_removals() if self is other: self.data.clear() else: From 91c1df0c329b91609ad2881d0a87b97cd4b4c0e9 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:38:45 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2024-08-27-12-38-42.gh-issue-123089.vA7iFR.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2024-08-27-12-38-42.gh-issue-123089.vA7iFR.rst diff --git a/Misc/NEWS.d/next/Library/2024-08-27-12-38-42.gh-issue-123089.vA7iFR.rst b/Misc/NEWS.d/next/Library/2024-08-27-12-38-42.gh-issue-123089.vA7iFR.rst new file mode 100644 index 00000000000000..74cbdd551350f7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-27-12-38-42.gh-issue-123089.vA7iFR.rst @@ -0,0 +1 @@ +Make :class:`weakref.WeakSet` safe against concurrent mutations while it is being iterated. Patch by Kumar Aditya.