MCPcopy Create free account
hub / github.com/tox-dev/filelock / ReadWriteLock

Class ReadWriteLock

src/filelock/_read_write.py:247–721  ·  view source on GitHub ↗

Cross-process read-write lock backed by SQLite. Allows concurrent shared readers or a single exclusive writer. The lock is reentrant within the same mode (multiple ``acquire_read`` calls nest, as do multiple ``acquire_write`` calls from the same thread), but upgrading from read to

Source from the content-addressed store, hash-verified

245
246
247class ReadWriteLock(metaclass=_ReadWriteLockMeta):
248 """
249 Cross-process read-write lock backed by SQLite.
250
251 Allows concurrent shared readers or a single exclusive writer. The lock is reentrant within the same mode (multiple
252 ``acquire_read`` calls nest, as do multiple ``acquire_write`` calls from the same thread), but upgrading from read
253 to write or downgrading from write to read raises :class:`RuntimeError`. Write locks are pinned to the thread that
254 acquired them.
255
256 By default, ``is_singleton=True``: calling ``ReadWriteLock(path)`` with the same resolved path returns the same
257 instance. The path is handed to :func:`sqlite3.connect` as given, so a ``.db`` extension is a convention rather
258 than a requirement; the filesystem must be one the active SQLite VFS supports.
259
260 :param lock_file: path to the SQLite database file used as the lock
261 :param timeout: maximum wait time in seconds; ``-1`` means block indefinitely
262 :param blocking: if ``False``, raise :class:`~filelock.Timeout` immediately when the lock is unavailable
263 :param is_singleton: if ``True``, reuse existing instances for the same resolved path
264
265 .. versionadded:: 3.21.0
266
267 """
268
269 _instances: WeakValueDictionary[pathlib.Path, ReadWriteLock] = WeakValueDictionary()
270 _instances_lock = threading.RLock()
271 _instances_pid = _GETPID()
272 _instances_under_construction: ClassVar[set[pathlib.Path]] = set()
273
274 def __init_subclass__(cls) -> None:
275 super().__init_subclass__()
276 cls._instances = WeakValueDictionary()
277 cls._instances_lock = threading.RLock()
278 cls._instances_pid = _GETPID()
279 cls._instances_under_construction = set()
280 _register_fork_class(cls)
281
282 @classmethod
283 def get_lock(
284 cls, lock_file: str | os.PathLike[str], timeout: float = -1, *, blocking: bool = True
285 ) -> ReadWriteLock:
286 """
287 Return the singleton :class:`ReadWriteLock` for *lock_file*.
288
289 :param lock_file: path to the SQLite database file used as the lock
290 :param timeout: maximum wait time in seconds; ``-1`` means block indefinitely
291 :param blocking: if ``False``, raise :class:`~filelock.Timeout` immediately when the lock is unavailable
292
293 :returns: the singleton lock instance
294
295 :raises ValueError: if an instance already exists for this path with different *timeout* or *blocking* values
296
297 """
298 return cls(lock_file, timeout, blocking=blocking)
299
300 def __init__(
301 self,
302 lock_file: str | os.PathLike[str],
303 timeout: float = -1,
304 *,

Calls

no outgoing calls