slick-queue-py 2.0.0__tar.gz → 2.3.0__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.
Files changed (47) hide show
  1. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/API_DIFFERENCES.md +35 -7
  2. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/CHANGELOG.md +349 -211
  3. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/PKG-INFO +108 -10
  4. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/README.md +107 -9
  5. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/slick_queue_py.egg-info/SOURCES.txt +2 -0
  6. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/slick_queue_py.py +351 -84
  7. slick_queue_py-2.3.0/tests/test_items_per_slot.py +484 -0
  8. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_modern_format.py +4 -2
  9. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_multi_producer.py +47 -10
  10. slick_queue_py-2.3.0/tests/test_segment_lifetime.py +410 -0
  11. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_traits.py +10 -14
  12. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/.github/FUNDING.yml +0 -0
  13. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/.github/workflows/ci.yml +0 -0
  14. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/.github/workflows/publish-conda.yml +0 -0
  15. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/.github/workflows/publish-pypi.yml +0 -0
  16. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/.github/workflows/publish-release.yml +0 -0
  17. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/.github/workflows/release.yml +0 -0
  18. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/.gitignore +0 -0
  19. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/.pypirc.template +0 -0
  20. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/BUILDING.md +0 -0
  21. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/CMakeLists.txt +0 -0
  22. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/LICENSE +0 -0
  23. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/MANIFEST.in +0 -0
  24. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/atomic_ops.py +0 -0
  25. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/atomic_ops_ext.cpp +0 -0
  26. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/conda.recipe/meta.yaml +0 -0
  27. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/pyproject.toml +0 -0
  28. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/requirements.txt +0 -0
  29. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/setup.cfg +0 -0
  30. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/setup.py +0 -0
  31. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/cleanup_shm.py +0 -0
  32. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/cpp_consumer.cpp +0 -0
  33. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/cpp_multi_producer.cpp +0 -0
  34. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/cpp_producer.cpp +0 -0
  35. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/cpp_read_last_tester.cpp +0 -0
  36. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/cpp_work_stealing_consumer.cpp +0 -0
  37. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/run_test.py +0 -0
  38. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_atomic_cursor.py +0 -0
  39. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_atomic_ops.py +0 -0
  40. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_interop.py +0 -0
  41. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_local_mode.py +0 -0
  42. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_loss_count.py +0 -0
  43. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_queue.py +0 -0
  44. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_read_last.py +0 -0
  45. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_read_last_interop.py +0 -0
  46. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_reset_detection.py +0 -0
  47. {slick_queue_py-2.0.0 → slick_queue_py-2.3.0}/tests/test_wrap_invariants.py +0 -0
@@ -2,7 +2,7 @@
2
2
 
3
3
  This document explains the intentional API differences between the C++ `slick::queue<T>` and Python `SlickQueue` implementations.
4
4
 
5
- Both track the same version line; this document describes slick-queue v2.0.0.
5
+ Both track the same version line; this document describes slick-queue v2.3.0.
6
6
 
7
7
  ## Core Compatibility
8
8
 
@@ -26,6 +26,9 @@ slick::queue<uint8_t> q(queue_name);
26
26
 
27
27
  // Local memory mode
28
28
  slick::queue<uint8_t> q(queue_size); // No shared memory
29
+
30
+ // Minimum of 64 items per reservation (one control slot per 64 items)
31
+ slick::queue<uint8_t> q(queue_size, 64, queue_name);
29
32
  ```
30
33
 
31
34
  **Python:**
@@ -38,10 +41,17 @@ q = SlickQueue(name=queue_name, element_size=element_size)
38
41
 
39
42
  # Local memory mode
40
43
  q = SlickQueue(size=queue_size, element_size=element_size) # No shared memory
44
+
45
+ # Minimum of 64 items per reservation (one control slot per 64 items)
46
+ q = SlickQueue(name=queue_name, size=queue_size, element_size=1, items_per_slot=64)
41
47
  ```
42
48
 
43
49
  **Rationale:** Python uses keyword arguments for clarity and supports both shared memory and local memory modes.
44
50
 
51
+ `items_per_slot` is the one place the opener differs: C++ `queue(name)` can only adopt the
52
+ segment's value, while Python's opener also accepts `items_per_slot=` and raises `ValueError`
53
+ if the segment disagrees. Omitting it adopts the segment's value, exactly as C++ does.
54
+
45
55
  ---
46
56
 
47
57
  ### 2. read() Method - Return Value vs. Reference Parameter
@@ -217,27 +227,44 @@ q[idx][:4] = struct.pack("<i", 42) # Manual packing
217
227
  {
218
228
  slick::queue<T> q(size, "name");
219
229
  // ... use queue ...
220
- } // Destructor automatically cleans up
230
+ q.remove_shm(); // Coordinator, once no peer will attach again; q's mapping stays valid
231
+ } // Destructor unmaps; it never removes the segment
232
+
233
+ slick::shm::shared_memory::remove("name"); // By name, without a queue - e.g. at startup
221
234
  ```
222
235
 
223
236
  **Python:**
224
237
  ```python
225
238
  # Option 1: Manual cleanup
226
- q = SlickQueue(name='name', size=size, element_size=elem_size, create=True)
239
+ q = SlickQueue(name='name', size=size, element_size=elem_size)
227
240
  try:
228
241
  # ... use queue ...
229
242
  finally:
230
243
  q.close()
231
- q.unlink() # Only call from creator process
244
+ q.unlink() # Only from the process that coordinates the queue's lifetime
232
245
 
233
- # Option 2: Context manager (recommended)
234
- with SlickQueue(name='name', size=size, element_size=elem_size, create=True) as q:
246
+ # Option 2: Context manager - closes, never unlinks
247
+ with SlickQueue(name='name', size=size, element_size=elem_size) as q:
235
248
  # ... use queue ...
236
- pass # Automatic cleanup
249
+ pass
250
+
251
+ SlickQueue.remove('name') # By name, without attaching - e.g. at startup
237
252
  ```
238
253
 
239
254
  **Rationale:** Python's garbage collection is non-deterministic, so explicit cleanup or context managers are needed.
240
255
 
256
+ Neither side deletes a segment on its own, matching C++ v2.3.0: not the C++ destructor, and not
257
+ Python's `close()`, context manager or process exit. Python keeps its segments out of
258
+ `multiprocessing`'s resource tracker for this, since the tracker would otherwise unlink them when
259
+ the process exits.
260
+
261
+ | C++ | Python |
262
+ |-----|--------|
263
+ | `remove_shm()` | `remove_shm()` - same contract, unlinks by name on every call |
264
+ | - | `unlink()` - unlinks once, valid after `close()`; a repeat is a no-op |
265
+ | `slick::shm::shared_memory::remove(name)` | `SlickQueue.remove(name)` - also accepts a `/`-prefixed name |
266
+ | `shm_name()` - `""` for a local queue | `get_shm_name()` - `None` for a local queue, `/`-prefixed on POSIX |
267
+
241
268
  ---
242
269
 
243
270
  ## Interoperability Examples
@@ -329,6 +356,7 @@ int main() {
329
356
  | Element access | Pointer | `memoryview` | Python memory safety |
330
357
  | Type safety | Templates | `struct` module | Language difference |
331
358
  | Cleanup | RAII (destructor) | Explicit or context manager | Python GC is non-deterministic |
359
+ | Segment removal | `remove_shm()` | `remove_shm()`, `unlink()`, `SlickQueue.remove()` | Neither side unlinks on its own |
332
360
  | `read()` data | `T*` into the ring | `bytes` copy | No safe raw pointers in Python |
333
361
  | Overwritten-in-flight data | Caller sees a volatile pointer | Copy may hold a newer record's bytes | Detect with `loss_count()` |
334
362
  | Feature configuration | `Traits` template parameter | `traits=` argument | Python has no templates |