| 161 | |
| 162 | |
| 163 | class _IterationGuard: |
| 164 | # This context manager registers itself in the current iterators of the |
| 165 | # weak container, such as to delay all removals until the context manager |
| 166 | # exits. |
| 167 | # This technique should be relatively thread-safe (since sets are). |
| 168 | |
| 169 | def __init__(self, weakcontainer): |
| 170 | # Don't create cycles |
| 171 | self.weakcontainer = IdentityWeakRef(weakcontainer) |
| 172 | |
| 173 | def __enter__(self): |
| 174 | w = self.weakcontainer() |
| 175 | if w is not None: |
| 176 | w._iterating.add(self) |
| 177 | return self |
| 178 | |
| 179 | def __exit__(self, e, t, b): |
| 180 | w = self.weakcontainer() |
| 181 | if w is not None: |
| 182 | s = w._iterating |
| 183 | s.remove(self) |
| 184 | if not s: |
| 185 | w._commit_removals() |