rwlocker 3.2__tar.gz → 3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rwlocker
3
- Version: 3.2
3
+ Version: 3.3
4
4
  Summary: Advanced, High-Performance, and State-Machine Based Synchronous/Asynchronous Read-Write Locks.
5
5
  Author-email: TahsinCr <TahsinCrs@gmail.com>
6
6
  License: MIT
@@ -71,13 +71,13 @@ Standard `Condition` structures in the library wake up all waiting threads/tasks
71
71
  * **Smart Proxy Architecture:** Intuitive usage of `with` and `async with` context managers via `.read` and `.write` proxies.
72
72
  * **Atomic Downgrading:** The ability to instantly downgrade a Write lock to a Read lock (`downgrade()`) without completely releasing the lock, preventing other writers from slipping in.
73
73
  * **Safe Reentrancy:** O(1) memory pointer tracking allowing the same thread or task to repeatedly acquire a write lock without causing a Deadlock.
74
- * **Cancellation Safety:** Full resilience against task cancellations (`CancelledError`) in the `asyncio` environment. Cancelled tasks do not corrupt the system state and safely wake up waiting tasks.
75
- * **O(1) Condition Queuing (Stampede Protection):** Unlike standard libraries, it does not perform O(N) scanning on `notify_all()` calls. It wakes up hundreds of tasks instantly without choking the CPU.
76
- * **Smart Signaling:** The ability to accurately wake up only the exact number of tasks you need, such as `notify(n=5)`, without creating a "Thundering Herd" in the system.
77
- * **Flawless Cancellation Shielding:** If a task is cancelled from the outside (`CancelledError`) while waiting in an asynchronous `Condition.wait()`, the lock state is never corrupted. The lock is safely re-acquired and passed on to other waiters.
78
- * **100% Drop-in Replacement:** You can inject your advanced locks (`RWLockFair`, etc.) directly into third-party libraries (SQLAlchemy, requests, FastAPI, etc.) expecting standard `threading.Lock` or `asyncio.Lock` instances without making any code changes. Standard API calls (e.g., `lock.acquire()`) are automatically and safely routed to the `.write` (exclusive) proxy.
79
- * **"Happy Path" Performance Isolation:** A next-generation, OS-Interrupt-resilient micro-queue architecture that completely bypasses O(N) cost cleanup operations upon successful lock wake-ups, completing the process with zero CPU overhead.
80
- * **Standard Adapters:** `Lock`, `Condition`, `AsyncLock`, and `AsyncCondition` standard wrapper classes for dependency injections where advanced RWLock features are not required but the same architectural signature (`.read`, `.write`) is desired.
74
+ * **Pure O(1) Condition Variables:** Unlike standard `Condition` structures, it does not iterate through the waiting list one by one during `notify_all()` calls (bypassing O(N) scanning costs). Thanks to its customized C-level micro-queue architecture, it wakes up thousands of tasks instantly without causing a "Cache Stampede" and choking the CPU.
75
+ * **Asynchronous Cancellation Safety & Shielding:** Full resilience against task cancellations (`CancelledError`) in the `asyncio` environment. If a task is cancelled while waiting for a lock or inside `Condition.wait()`, the system state is never corrupted. The lock is safely recovered, no "zombie" waiters are left behind, and wait queues remain perfectly clean.
76
+ * **100% Drop-in Replacement:** You can inject your advanced locks (`RWLockFair`, etc.) and conditions (`RWCondition`, etc.) directly into third-party libraries (SQLAlchemy, requests, FastAPI, etc.) expecting standard `threading.Lock`, `asyncio.Lock`, `threading.Condition`, or `asyncio.Condition` instances without making any code changes. Standard API calls (e.g., `lock.acquire()`, `cond.wait()`) are automatically and safely routed to the `.write` (exclusive) proxy.
77
+ * **"Happy Path" Performance Isolation:** A next-generation architecture that completely bypasses O(N) cost garbage cleanup operations upon successful lock and queue wake-ups. It provides absolute protection against OS-Interrupts and timeouts while completing successful wake-ups with zero CPU overhead.
78
+ * **Standard Adapters:** Includes standard wrappers for Dependency Injection workflows where you want to maintain the exact same architectural signature (`.read` and `.write`) but do not require advanced lock strategies.
79
+ * *Lock Adapters:* `Lock` (Thread), `AsyncLock` (Asyncio)
80
+ * *Condition Adapters:* `Condition` (Thread), `AsyncCondition` (Asyncio)
81
81
 
82
82
  ### 🛡️ Lock Strategies
83
83
 
@@ -87,7 +87,8 @@ You can select the right lock strategy based on your system's bottleneck profile
87
87
  | --- | --- | --- | --- |
88
88
  | **Writer-Preferring** | `RWLockWrite` / `AsyncRWLockWrite` | Forbids new readers from entering if there is a waiting writer. Prevents writer starvation. | To prevent writers from being overwhelmed in read-heavy systems. |
89
89
  | **Reader-Preferring** | `RWLockRead` / `AsyncRWLockRead` | Continuously allows new readers in, even if writers are waiting. Provides maximum parallelism. | In cache structures where write operations are very rare or non-critical. |
90
- | **Fair** | `RWLockFair` / `AsyncRWLockFair` | Grants access alternately between readers and writers (interleaving). Prevents starvation for both sides. | In high-frequency, bidirectional traffic (MAVLink, WebSockets, etc.). |
90
+ | **Reader-Phase Fair** | `RWLockReaderPhaseFair` / `AsyncRWLockReaderPhaseFair` | Alternates between reader and writer phases, but late readers may still join an already-open reader phase for higher read throughput. | When you want bounded fairness without fully freezing each reader batch. |
91
+ | **Fair** | `RWLockFair` / `AsyncRWLockFair` | Freezes each reader phase at phase start so late readers cannot cut in front of an already-queued writer. Prevents starvation for both sides with stricter ordering. | In high-frequency, bidirectional traffic (MAVLink, WebSockets, etc.) where deterministic writer latency matters. |
91
92
  > 💡 **Condition Compatibility:** The `RWCondition` and `AsyncRWCondition` classes in the library are designed to encapsulate all the lock strategies mentioned above (Dependency Injection). You can choose the lock that best fits your system and transform it into a state machine running at pure O(1) speed.
92
93
  <br/>
93
94
 
@@ -116,7 +117,7 @@ The performance results demonstrate `rwlocker`'s true potential during Network a
116
117
 
117
118
  **🖥️ Test Environment:** All tests were executed on an **Intel Core i7-12700H (2.4GHz)** processor running **EndeavourOS (Arch-based Linux)**, using **Python 3.14.3** and the experimental **Free-Threading (3.14.3t)** interpreters.
118
119
 
119
- **🧪 Methodology:** To ensure absolute precision and zero margin of error, all reader and writer entities (threads or async tasks) are spawned in advance and held at a starting line using a synchronization `Event`. Once the event triggers, they execute simultaneously. The workloads strictly follow an `IOBoundScenario` that enforces a precise `time.sleep(0.001)` or `asyncio.sleep(0.001)` delay to accurately simulate real network/database I/O latency.
120
+ **🧪 Methodology:** To ensure absolute precision and zero margin of error, all reader and writer entities (threads or async tasks) are spawned in advance and held at a starting line using a synchronization `Event`. Once the event triggers, they execute simultaneously. The workloads strictly follow an `IOBoundScenario` that enforces a precise `time.sleep(0.001)` or `asyncio.sleep(0.001)` delay across 10 consecutive iterations to accurately simulate real network/database I/O latency.
120
121
 
121
122
  ### 1. Read-Write Lock (RWLock) Benchmarks
122
123
 
@@ -133,12 +134,12 @@ In the Read-Heavy scenario, standard C-based locks choke the system, whereas `rw
133
134
  Standard `Condition` variables iterate through all sleeping threads/tasks one by one `O(N)` during a broadcast (`notify_all`), causing massive CPU spikes and "Cache Stampedes". `rwlocker` completely eradicates this with its pure `O(1)` queueing architecture.
134
135
 
135
136
  **Synchronous (Thread) RWCondition Performance:**
136
- When 100 sleeping readers are awakened simultaneously, `rwlocker` processes them instantly without locking the OS. This architectural leap results in a mind-blowing **~45x speedup** compared to the standard library's `threading.Condition`.
137
+ When 100 sleeping readers are awakened simultaneously, `rwlocker` processes them instantly without locking the OS. This architectural leap results in a **~45x speedup** compared to the standard library's `threading.Condition`.
137
138
 
138
139
  **Asynchronous (Asyncio) RWCondition Performance:**
139
140
  In event-driven caching systems, waking up hundreds of waiting web requests simultaneously is a major bottleneck. The `AsyncRWCondition` completely bypasses standard asyncio constraints, reaching up to **~45x higher throughput** during massive broadcast scenarios, completely saving the loop from freezing.
140
141
 
141
- *(Note: All lock, adapter, and condition classes have passed a massive suite of **315 different unit tests** covering reentrancy, deadlock, timeout, OS interrupts, O(N) leaks, and cancellation safety scenarios with 0 errors, and this entire test suite was completed in just **13.2 seconds**.)*
142
+ *(Note: All lock, adapter, and condition classes have passed a massive suite of **412 different unit tests** covering reentrancy, deadlock, timeout, OS interrupts, O(N) leaks, and cancellation safety scenarios with 0 errors, and this entire test suite was completed in just **15.7 seconds**.)*
142
143
 
143
144
 
144
145
  <br/>
@@ -42,13 +42,13 @@ Standard `Condition` structures in the library wake up all waiting threads/tasks
42
42
  * **Smart Proxy Architecture:** Intuitive usage of `with` and `async with` context managers via `.read` and `.write` proxies.
43
43
  * **Atomic Downgrading:** The ability to instantly downgrade a Write lock to a Read lock (`downgrade()`) without completely releasing the lock, preventing other writers from slipping in.
44
44
  * **Safe Reentrancy:** O(1) memory pointer tracking allowing the same thread or task to repeatedly acquire a write lock without causing a Deadlock.
45
- * **Cancellation Safety:** Full resilience against task cancellations (`CancelledError`) in the `asyncio` environment. Cancelled tasks do not corrupt the system state and safely wake up waiting tasks.
46
- * **O(1) Condition Queuing (Stampede Protection):** Unlike standard libraries, it does not perform O(N) scanning on `notify_all()` calls. It wakes up hundreds of tasks instantly without choking the CPU.
47
- * **Smart Signaling:** The ability to accurately wake up only the exact number of tasks you need, such as `notify(n=5)`, without creating a "Thundering Herd" in the system.
48
- * **Flawless Cancellation Shielding:** If a task is cancelled from the outside (`CancelledError`) while waiting in an asynchronous `Condition.wait()`, the lock state is never corrupted. The lock is safely re-acquired and passed on to other waiters.
49
- * **100% Drop-in Replacement:** You can inject your advanced locks (`RWLockFair`, etc.) directly into third-party libraries (SQLAlchemy, requests, FastAPI, etc.) expecting standard `threading.Lock` or `asyncio.Lock` instances without making any code changes. Standard API calls (e.g., `lock.acquire()`) are automatically and safely routed to the `.write` (exclusive) proxy.
50
- * **"Happy Path" Performance Isolation:** A next-generation, OS-Interrupt-resilient micro-queue architecture that completely bypasses O(N) cost cleanup operations upon successful lock wake-ups, completing the process with zero CPU overhead.
51
- * **Standard Adapters:** `Lock`, `Condition`, `AsyncLock`, and `AsyncCondition` standard wrapper classes for dependency injections where advanced RWLock features are not required but the same architectural signature (`.read`, `.write`) is desired.
45
+ * **Pure O(1) Condition Variables:** Unlike standard `Condition` structures, it does not iterate through the waiting list one by one during `notify_all()` calls (bypassing O(N) scanning costs). Thanks to its customized C-level micro-queue architecture, it wakes up thousands of tasks instantly without causing a "Cache Stampede" and choking the CPU.
46
+ * **Asynchronous Cancellation Safety & Shielding:** Full resilience against task cancellations (`CancelledError`) in the `asyncio` environment. If a task is cancelled while waiting for a lock or inside `Condition.wait()`, the system state is never corrupted. The lock is safely recovered, no "zombie" waiters are left behind, and wait queues remain perfectly clean.
47
+ * **100% Drop-in Replacement:** You can inject your advanced locks (`RWLockFair`, etc.) and conditions (`RWCondition`, etc.) directly into third-party libraries (SQLAlchemy, requests, FastAPI, etc.) expecting standard `threading.Lock`, `asyncio.Lock`, `threading.Condition`, or `asyncio.Condition` instances without making any code changes. Standard API calls (e.g., `lock.acquire()`, `cond.wait()`) are automatically and safely routed to the `.write` (exclusive) proxy.
48
+ * **"Happy Path" Performance Isolation:** A next-generation architecture that completely bypasses O(N) cost garbage cleanup operations upon successful lock and queue wake-ups. It provides absolute protection against OS-Interrupts and timeouts while completing successful wake-ups with zero CPU overhead.
49
+ * **Standard Adapters:** Includes standard wrappers for Dependency Injection workflows where you want to maintain the exact same architectural signature (`.read` and `.write`) but do not require advanced lock strategies.
50
+ * *Lock Adapters:* `Lock` (Thread), `AsyncLock` (Asyncio)
51
+ * *Condition Adapters:* `Condition` (Thread), `AsyncCondition` (Asyncio)
52
52
 
53
53
  ### 🛡️ Lock Strategies
54
54
 
@@ -58,7 +58,8 @@ You can select the right lock strategy based on your system's bottleneck profile
58
58
  | --- | --- | --- | --- |
59
59
  | **Writer-Preferring** | `RWLockWrite` / `AsyncRWLockWrite` | Forbids new readers from entering if there is a waiting writer. Prevents writer starvation. | To prevent writers from being overwhelmed in read-heavy systems. |
60
60
  | **Reader-Preferring** | `RWLockRead` / `AsyncRWLockRead` | Continuously allows new readers in, even if writers are waiting. Provides maximum parallelism. | In cache structures where write operations are very rare or non-critical. |
61
- | **Fair** | `RWLockFair` / `AsyncRWLockFair` | Grants access alternately between readers and writers (interleaving). Prevents starvation for both sides. | In high-frequency, bidirectional traffic (MAVLink, WebSockets, etc.). |
61
+ | **Reader-Phase Fair** | `RWLockReaderPhaseFair` / `AsyncRWLockReaderPhaseFair` | Alternates between reader and writer phases, but late readers may still join an already-open reader phase for higher read throughput. | When you want bounded fairness without fully freezing each reader batch. |
62
+ | **Fair** | `RWLockFair` / `AsyncRWLockFair` | Freezes each reader phase at phase start so late readers cannot cut in front of an already-queued writer. Prevents starvation for both sides with stricter ordering. | In high-frequency, bidirectional traffic (MAVLink, WebSockets, etc.) where deterministic writer latency matters. |
62
63
  > 💡 **Condition Compatibility:** The `RWCondition` and `AsyncRWCondition` classes in the library are designed to encapsulate all the lock strategies mentioned above (Dependency Injection). You can choose the lock that best fits your system and transform it into a state machine running at pure O(1) speed.
63
64
  <br/>
64
65
 
@@ -87,7 +88,7 @@ The performance results demonstrate `rwlocker`'s true potential during Network a
87
88
 
88
89
  **🖥️ Test Environment:** All tests were executed on an **Intel Core i7-12700H (2.4GHz)** processor running **EndeavourOS (Arch-based Linux)**, using **Python 3.14.3** and the experimental **Free-Threading (3.14.3t)** interpreters.
89
90
 
90
- **🧪 Methodology:** To ensure absolute precision and zero margin of error, all reader and writer entities (threads or async tasks) are spawned in advance and held at a starting line using a synchronization `Event`. Once the event triggers, they execute simultaneously. The workloads strictly follow an `IOBoundScenario` that enforces a precise `time.sleep(0.001)` or `asyncio.sleep(0.001)` delay to accurately simulate real network/database I/O latency.
91
+ **🧪 Methodology:** To ensure absolute precision and zero margin of error, all reader and writer entities (threads or async tasks) are spawned in advance and held at a starting line using a synchronization `Event`. Once the event triggers, they execute simultaneously. The workloads strictly follow an `IOBoundScenario` that enforces a precise `time.sleep(0.001)` or `asyncio.sleep(0.001)` delay across 10 consecutive iterations to accurately simulate real network/database I/O latency.
91
92
 
92
93
  ### 1. Read-Write Lock (RWLock) Benchmarks
93
94
 
@@ -104,12 +105,12 @@ In the Read-Heavy scenario, standard C-based locks choke the system, whereas `rw
104
105
  Standard `Condition` variables iterate through all sleeping threads/tasks one by one `O(N)` during a broadcast (`notify_all`), causing massive CPU spikes and "Cache Stampedes". `rwlocker` completely eradicates this with its pure `O(1)` queueing architecture.
105
106
 
106
107
  **Synchronous (Thread) RWCondition Performance:**
107
- When 100 sleeping readers are awakened simultaneously, `rwlocker` processes them instantly without locking the OS. This architectural leap results in a mind-blowing **~45x speedup** compared to the standard library's `threading.Condition`.
108
+ When 100 sleeping readers are awakened simultaneously, `rwlocker` processes them instantly without locking the OS. This architectural leap results in a **~45x speedup** compared to the standard library's `threading.Condition`.
108
109
 
109
110
  **Asynchronous (Asyncio) RWCondition Performance:**
110
111
  In event-driven caching systems, waking up hundreds of waiting web requests simultaneously is a major bottleneck. The `AsyncRWCondition` completely bypasses standard asyncio constraints, reaching up to **~45x higher throughput** during massive broadcast scenarios, completely saving the loop from freezing.
111
112
 
112
- *(Note: All lock, adapter, and condition classes have passed a massive suite of **315 different unit tests** covering reentrancy, deadlock, timeout, OS interrupts, O(N) leaks, and cancellation safety scenarios with 0 errors, and this entire test suite was completed in just **13.2 seconds**.)*
113
+ *(Note: All lock, adapter, and condition classes have passed a massive suite of **412 different unit tests** covering reentrancy, deadlock, timeout, OS interrupts, O(N) leaks, and cancellation safety scenarios with 0 errors, and this entire test suite was completed in just **15.7 seconds**.)*
113
114
 
114
115
 
115
116
  <br/>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rwlocker"
7
- version = "3.2"
7
+ version = "3.3"
8
8
  description = "Advanced, High-Performance, and State-Machine Based Synchronous/Asynchronous Read-Write Locks."
9
9
  readme = {file = "README-pypi.md", content-type = "text/markdown"}
10
10
  license = {text = "MIT"}
@@ -10,9 +10,9 @@ it guarantees strict data safety while maximizing read concurrency and
10
10
  preventing CPU/Event-Loop bottlenecks.
11
11
 
12
12
  Key Architectural Features:
13
- - **Multiple Scheduling Strategies**: Choose between Write-preferring,
14
- Read-preferring, and Fair (FIFO) algorithms to prevent starvation based
15
- on your specific workload.
13
+ - **Multiple Scheduling Strategies**: Choose between Write-preferring,
14
+ Read-preferring, Reader-Phase Fair, and Strict Fair algorithms to prevent
15
+ starvation based on your specific workload.
16
16
  - **O(1) Condition Queuing (Stampede Protection)**: Condition variables
17
17
  (`RWCondition`, `AsyncRWCondition`) utilize pure O(1) waiter queues
18
18
  to completely eliminate O(N) cache stampedes and event-loop blocking
@@ -36,15 +36,15 @@ Important Usage Notes & Gotchas:
36
36
  - **Reentrancy (`ReentrantWriter` variants)**: Reentrancy is STRICTLY supported for
37
37
  nested *write* operations by the same Thread/Task. It does NOT implicitly
38
38
  grant read locks. You must use `.downgrade()` if you need to read.
39
- - **Downgrade Performance Cost**: Calling `.downgrade()` registers the current
40
- Thread/Task ID into a tracking set. This adds a minor O(1) hash lookup cost
41
- during the subsequent `release()` operation. Standard operations remain O(0).
39
+ - **Downgrade Performance Cost**: Calling `.downgrade()` stores a single
40
+ downgrade-owner marker so the subsequent `release()` can safely route to
41
+ the read side. Standard fast paths remain allocation-free.
42
42
  - **Circular References**: Base lock classes hold references to their proxies,
43
43
  and proxies hold references back to the base. Memory is reclaimed via
44
44
  Python's cyclic GC. Do not rely on `__del__` for cleanup.
45
45
 
46
46
  Basic Example:
47
- >>> lock = RWLockFIFOReentrantWriter()
47
+ >>> lock = RWLockWriteReentrantWriter()
48
48
  >>> with lock.write:
49
49
  ... # Exclusive write access
50
50
  ... lock.write.downgrade()
@@ -64,4 +64,4 @@ Basic Example:
64
64
  from .thread_rwlock import *
65
65
  from .async_rwlock import *
66
66
 
67
- __version__ = '3.2'
67
+ __version__ = '3.3'