Asynchronous equivalent to threading.Condition. This class implements condition variable objects. A condition variable allows one or more tasks to wait until they are notified by another task. A new Lock object is created and used as the underlying lock.
| 177 | |
| 178 | |
| 179 | class Condition(_ContextManagerMixin, _LoopBoundMixin): |
| 180 | """Asynchronous equivalent to threading.Condition. |
| 181 | |
| 182 | This class implements condition variable objects. A condition variable |
| 183 | allows one or more tasks to wait until they are notified by another |
| 184 | task. |
| 185 | |
| 186 | A new Lock object is created and used as the underlying lock. |
| 187 | """ |
| 188 | |
| 189 | def __init__(self, lock: Optional[Lock] = None) -> None: |
| 190 | if lock is None: |
| 191 | lock = Lock() |
| 192 | |
| 193 | self._lock = lock |
| 194 | # Export the lock's locked(), acquire() and release() methods. |
| 195 | self.locked = lock.locked |
| 196 | self.acquire = lock.acquire |
| 197 | self.release = lock.release |
| 198 | |
| 199 | self._waiters: collections.deque[Any] = collections.deque() |
| 200 | |
| 201 | def __repr__(self) -> str: |
| 202 | res = super().__repr__() |
| 203 | extra = "locked" if self.locked() else "unlocked" |
| 204 | if self._waiters: |
| 205 | extra = f"{extra}, waiters:{len(self._waiters)}" |
| 206 | return f"<{res[1:-1]} [{extra}]>" |
| 207 | |
| 208 | async def wait(self) -> bool: |
| 209 | """Wait until notified. |
| 210 | |
| 211 | If the calling task has not acquired the lock when this |
| 212 | method is called, a RuntimeError is raised. |
| 213 | |
| 214 | This method releases the underlying lock, and then blocks |
| 215 | until it is awakened by a notify() or notify_all() call for |
| 216 | the same condition variable in another task. Once |
| 217 | awakened, it re-acquires the lock and returns True. |
| 218 | |
| 219 | This method may return spuriously, |
| 220 | which is why the caller should always |
| 221 | re-check the state and be prepared to wait() again. |
| 222 | """ |
| 223 | if not self.locked(): |
| 224 | raise RuntimeError("cannot wait on un-acquired lock") |
| 225 | |
| 226 | fut = self._get_loop().create_future() |
| 227 | self.release() |
| 228 | try: |
| 229 | try: |
| 230 | self._waiters.append(fut) |
| 231 | try: |
| 232 | await fut |
| 233 | return True |
| 234 | finally: |
| 235 | self._waiters.remove(fut) |
| 236 |
no outgoing calls
no test coverage detected