Skip to content

RWLock

Read-write locks for sync and async code.

Read-write locks for both synchronous and asynchronous contexts.

AsyncRWLock

An async read-write lock allowing concurrent reads or exclusive writes.

Uses asyncio.Condition for coroutine-safe synchronization.

Source code in shutils/rwlock.py
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
class AsyncRWLock:
    """An async read-write lock allowing concurrent reads or exclusive writes.

    Uses ``asyncio.Condition`` for coroutine-safe synchronization.
    """

    def __init__(self):
        self._read_ready = asyncio.Condition()
        self._readers = 0

    def read(self):
        """Return an async context manager for acquiring and releasing the read lock."""
        return self.ReadLock(self)

    def write(self):
        """Return an async context manager for acquiring and releasing the write lock."""
        return self.WriteLock(self)

    class ReadLock:
        """Async context manager that acquires/releases a read lock."""

        def __init__(self, rwlock):
            self.rwlock = rwlock

        async def __aenter__(self):
            """Acquire the read lock on entering the context."""
            await self.rwlock._acquire_read()

        async def __aexit__(self, exc_type, exc_val, exc_tb):
            """Release the read lock on exiting the context."""
            await self.rwlock._release_read()

    class WriteLock:
        """Async context manager that acquires/releases a write lock."""

        def __init__(self, rwlock):
            self.rwlock = rwlock

        async def __aenter__(self):
            """Acquire the write lock on entering the context."""
            await self.rwlock._acquire_write()

        async def __aexit__(self, exc_type, exc_val, exc_tb):
            """Release the write lock on exiting the context."""
            await self.rwlock._release_write()

    async def _acquire_read(self):
        async with self._read_ready:
            self._readers += 1

    async def _release_read(self):
        async with self._read_ready:
            self._readers -= 1
            if self._readers == 0:
                self._read_ready.notify_all()

    async def _acquire_write(self):
        await self._read_ready.acquire()
        try:
            while self._readers > 0:
                await self._read_ready.wait()
        except:
            self._read_ready.release()
            raise

    async def _release_write(self):
        self._read_ready.release()

ReadLock

Async context manager that acquires/releases a read lock.

Source code in shutils/rwlock.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
class ReadLock:
    """Async context manager that acquires/releases a read lock."""

    def __init__(self, rwlock):
        self.rwlock = rwlock

    async def __aenter__(self):
        """Acquire the read lock on entering the context."""
        await self.rwlock._acquire_read()

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """Release the read lock on exiting the context."""
        await self.rwlock._release_read()

__aenter__() async

Acquire the read lock on entering the context.

Source code in shutils/rwlock.py
102
103
104
async def __aenter__(self):
    """Acquire the read lock on entering the context."""
    await self.rwlock._acquire_read()

__aexit__(exc_type, exc_val, exc_tb) async

Release the read lock on exiting the context.

Source code in shutils/rwlock.py
106
107
108
async def __aexit__(self, exc_type, exc_val, exc_tb):
    """Release the read lock on exiting the context."""
    await self.rwlock._release_read()

WriteLock

Async context manager that acquires/releases a write lock.

Source code in shutils/rwlock.py
110
111
112
113
114
115
116
117
118
119
120
121
122
class WriteLock:
    """Async context manager that acquires/releases a write lock."""

    def __init__(self, rwlock):
        self.rwlock = rwlock

    async def __aenter__(self):
        """Acquire the write lock on entering the context."""
        await self.rwlock._acquire_write()

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """Release the write lock on exiting the context."""
        await self.rwlock._release_write()

__aenter__() async

Acquire the write lock on entering the context.

Source code in shutils/rwlock.py
116
117
118
async def __aenter__(self):
    """Acquire the write lock on entering the context."""
    await self.rwlock._acquire_write()

__aexit__(exc_type, exc_val, exc_tb) async

Release the write lock on exiting the context.

Source code in shutils/rwlock.py
120
121
122
async def __aexit__(self, exc_type, exc_val, exc_tb):
    """Release the write lock on exiting the context."""
    await self.rwlock._release_write()

read()

Return an async context manager for acquiring and releasing the read lock.

Source code in shutils/rwlock.py
88
89
90
def read(self):
    """Return an async context manager for acquiring and releasing the read lock."""
    return self.ReadLock(self)

write()

Return an async context manager for acquiring and releasing the write lock.

Source code in shutils/rwlock.py
92
93
94
def write(self):
    """Return an async context manager for acquiring and releasing the write lock."""
    return self.WriteLock(self)

RWLock

A thread-safe read-write lock allowing concurrent reads or exclusive writes.

Multiple readers can hold the lock simultaneously, but a writer requires exclusive access.

Source code in shutils/rwlock.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class RWLock:
    """A thread-safe read-write lock allowing concurrent reads or exclusive writes.

    Multiple readers can hold the lock simultaneously, but a writer requires
    exclusive access.
    """

    def __init__(self):
        self._read_ready = threading.Condition(threading.Lock())
        self._readers = 0

    def read(self):
        """Return a context manager for acquiring and releasing the read lock."""
        return self.ReadLock(self)

    def write(self):
        """Return a context manager for acquiring and releasing the write lock."""
        return self.WriteLock(self)

    class ReadLock:
        """Context manager that acquires/releases a read lock."""

        def __init__(self, rwlock):
            self.rwlock = rwlock

        def __enter__(self):
            """Acquire the read lock on entering the context."""
            self.rwlock._acquire_read()

        def __exit__(self, exc_type, exc_val, exc_tb):
            """Release the read lock on exiting the context."""
            self.rwlock._release_read()

    class WriteLock:
        """Context manager that acquires/releases a write lock."""

        def __init__(self, rwlock):
            self.rwlock = rwlock

        def __enter__(self):
            """Acquire the write lock on entering the context."""
            self.rwlock._acquire_write()

        def __exit__(self, exc_type, exc_val, exc_tb):
            """Release the write lock on exiting the context."""
            self.rwlock._release_write()

    def _acquire_read(self):
        with self._read_ready:
            self._readers += 1

    def _release_read(self):
        with self._read_ready:
            self._readers -= 1
            if self._readers == 0:
                self._read_ready.notify_all()

    def _acquire_write(self):
        self._read_ready.acquire()
        while self._readers > 0:
            self._read_ready.wait()

    def _release_write(self):
        self._read_ready.release()

ReadLock

Context manager that acquires/releases a read lock.

Source code in shutils/rwlock.py
31
32
33
34
35
36
37
38
39
40
41
42
43
class ReadLock:
    """Context manager that acquires/releases a read lock."""

    def __init__(self, rwlock):
        self.rwlock = rwlock

    def __enter__(self):
        """Acquire the read lock on entering the context."""
        self.rwlock._acquire_read()

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Release the read lock on exiting the context."""
        self.rwlock._release_read()

__enter__()

Acquire the read lock on entering the context.

Source code in shutils/rwlock.py
37
38
39
def __enter__(self):
    """Acquire the read lock on entering the context."""
    self.rwlock._acquire_read()

__exit__(exc_type, exc_val, exc_tb)

Release the read lock on exiting the context.

Source code in shutils/rwlock.py
41
42
43
def __exit__(self, exc_type, exc_val, exc_tb):
    """Release the read lock on exiting the context."""
    self.rwlock._release_read()

WriteLock

Context manager that acquires/releases a write lock.

Source code in shutils/rwlock.py
45
46
47
48
49
50
51
52
53
54
55
56
57
class WriteLock:
    """Context manager that acquires/releases a write lock."""

    def __init__(self, rwlock):
        self.rwlock = rwlock

    def __enter__(self):
        """Acquire the write lock on entering the context."""
        self.rwlock._acquire_write()

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Release the write lock on exiting the context."""
        self.rwlock._release_write()

__enter__()

Acquire the write lock on entering the context.

Source code in shutils/rwlock.py
51
52
53
def __enter__(self):
    """Acquire the write lock on entering the context."""
    self.rwlock._acquire_write()

__exit__(exc_type, exc_val, exc_tb)

Release the write lock on exiting the context.

Source code in shutils/rwlock.py
55
56
57
def __exit__(self, exc_type, exc_val, exc_tb):
    """Release the write lock on exiting the context."""
    self.rwlock._release_write()

read()

Return a context manager for acquiring and releasing the read lock.

Source code in shutils/rwlock.py
23
24
25
def read(self):
    """Return a context manager for acquiring and releasing the read lock."""
    return self.ReadLock(self)

write()

Return a context manager for acquiring and releasing the write lock.

Source code in shutils/rwlock.py
27
28
29
def write(self):
    """Return a context manager for acquiring and releasing the write lock."""
    return self.WriteLock(self)