A context manager responsible to updating ``_blocking_on``.
| 154 | |
| 155 | |
| 156 | class _BlockingOnManager: |
| 157 | """A context manager responsible to updating ``_blocking_on``.""" |
| 158 | def __init__(self, thread_id, lock): |
| 159 | self.thread_id = thread_id |
| 160 | self.lock = lock |
| 161 | |
| 162 | def __enter__(self): |
| 163 | """Mark the running thread as waiting for self.lock. via _blocking_on.""" |
| 164 | # Interactions with _blocking_on are *not* protected by the global |
| 165 | # import lock here because each thread only touches the state that it |
| 166 | # owns (state keyed on its thread id). The global import lock is |
| 167 | # re-entrant (i.e., a single thread may take it more than once) so it |
| 168 | # wouldn't help us be correct in the face of re-entrancy either. |
| 169 | |
| 170 | self.blocked_on = _blocking_on.setdefault(self.thread_id, _List()) |
| 171 | self.blocked_on.append(self.lock) |
| 172 | |
| 173 | def __exit__(self, *args, **kwargs): |
| 174 | """Remove self.lock from this thread's _blocking_on list.""" |
| 175 | self.blocked_on.remove(self.lock) |
| 176 | |
| 177 | |
| 178 | class _DeadlockError(RuntimeError): |
no outgoing calls
no test coverage detected
searching dependent graphs…