sharedbox 0.5.0__tar.gz → 0.6.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 (274) hide show
  1. {sharedbox-0.5.0 → sharedbox-0.6.0}/.github/dependabot.yml +2 -0
  2. sharedbox-0.6.0/.github/pull_request_template.md +3 -0
  3. sharedbox-0.6.0/.github/workflows/check-changelog.yaml +47 -0
  4. {sharedbox-0.5.0 → sharedbox-0.6.0}/.github/workflows/ci.yaml +33 -3
  5. sharedbox-0.6.0/.github/workflows/ops.yaml +90 -0
  6. sharedbox-0.6.0/.github/workflows/prepare-release.yaml +78 -0
  7. sharedbox-0.6.0/.github/workflows/streams.yaml +85 -0
  8. {sharedbox-0.5.0 → sharedbox-0.6.0}/.gitignore +2 -1
  9. {sharedbox-0.5.0 → sharedbox-0.6.0}/CHANGELOG.md +133 -2
  10. {sharedbox-0.5.0 → sharedbox-0.6.0}/CLAUDE.md +117 -55
  11. {sharedbox-0.5.0 → sharedbox-0.6.0}/CMakeLists.txt +1 -0
  12. {sharedbox-0.5.0 → sharedbox-0.6.0}/PKG-INFO +38 -25
  13. {sharedbox-0.5.0 → sharedbox-0.6.0}/README.md +36 -23
  14. sharedbox-0.6.0/benchmarks/test_bench_stream.py +31 -0
  15. sharedbox-0.6.0/docs/assets/benchmarks/ops.json +1 -0
  16. sharedbox-0.6.0/docs/assets/benchmarks/roundtrip.json +1 -0
  17. sharedbox-0.6.0/docs/assets/benchmarks/stream-matrix.json +1 -0
  18. sharedbox-0.6.0/docs/assets/benchmarks/stream-throughput.json +1 -0
  19. sharedbox-0.6.0/docs/examples/change_several_fields_at_once.py +44 -0
  20. sharedbox-0.6.0/docs/examples/clean_up_segments.py +38 -0
  21. sharedbox-0.6.0/docs/examples/follow_a_whole_reference_graph.py +46 -0
  22. sharedbox-0.6.0/docs/examples/name_a_box.py +45 -0
  23. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/examples/send_a_box_to_another_process.py +14 -14
  24. sharedbox-0.6.0/docs/examples/send_items_through_a_stream.py +129 -0
  25. sharedbox-0.6.0/docs/examples/set_defaults_and_check_values.py +79 -0
  26. sharedbox-0.6.0/docs/examples/store_arrays.py +52 -0
  27. sharedbox-0.6.0/docs/examples/store_collections.py +40 -0
  28. sharedbox-0.6.0/docs/examples/store_records.py +53 -0
  29. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/examples/store_text_and_bytes.py +14 -14
  30. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/closing-and-lifetime.md +15 -15
  31. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/field-types.md +1 -1
  32. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/glossary.md +40 -1
  33. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/how-a-box-is-stored.md +41 -39
  34. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/limits.md +5 -6
  35. sharedbox-0.6.0/docs/explanation/performance.md +221 -0
  36. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/references.md +24 -24
  37. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/waiting-for-changes.md +35 -26
  38. sharedbox-0.6.0/docs/explanation/when-to-use-sharedbox.md +59 -0
  39. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/accept-a-box-in-c.md +6 -6
  40. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/accept-a-box-in-cpp.md +24 -24
  41. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/change-several-fields-at-once.md +3 -3
  42. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/clean-up-segments.md +3 -3
  43. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/commits-and-prs.md +32 -11
  44. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/follow-a-whole-reference-graph.md +8 -8
  45. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/index.md +5 -2
  46. sharedbox-0.6.0/docs/how-to/make-a-release.md +76 -0
  47. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/name-a-box.md +5 -3
  48. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/open-a-box-from-a-program.md +5 -5
  49. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/run-benchmarks.md +61 -17
  50. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/send-a-box-to-another-process.md +3 -3
  51. sharedbox-0.6.0/docs/how-to/send-items-through-a-stream.md +287 -0
  52. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/store-arrays.md +51 -23
  53. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/write-docs.md +2 -2
  54. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/index.md +64 -59
  55. sharedbox-0.6.0/docs/javascripts/charts.js +88 -0
  56. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/api/arrays.md +2 -2
  57. sharedbox-0.6.0/docs/reference/api/errors.md +73 -0
  58. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/api/events.md +8 -1
  59. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/api/index.md +2 -1
  60. sharedbox-0.6.0/docs/reference/api/streams.md +44 -0
  61. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/cpp-and-c-api.md +8 -5
  62. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/segment-layout.md +670 -182
  63. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/tutorials/index.md +1 -1
  64. sharedbox-0.6.0/docs/tutorials/mailbox.py +102 -0
  65. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/tutorials/react-to-changes.md +29 -29
  66. sharedbox-0.6.0/docs/tutorials/refer-to-another-box.md +106 -0
  67. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/tutorials/share-a-record.md +21 -21
  68. sharedbox-0.6.0/include/sharedbox/box.hpp +1140 -0
  69. sharedbox-0.5.0/include/sharedbox/sharedbox.hpp → sharedbox-0.6.0/include/sharedbox/core.hpp +648 -1549
  70. sharedbox-0.6.0/include/sharedbox/sharedbox.hpp +21 -0
  71. {sharedbox-0.5.0 → sharedbox-0.6.0}/include/sharedbox/sharedbox_c.cpp +13 -13
  72. {sharedbox-0.5.0 → sharedbox-0.6.0}/include/sharedbox/sharedbox_c.h +5 -0
  73. sharedbox-0.6.0/include/sharedbox/stream.hpp +1038 -0
  74. {sharedbox-0.5.0 → sharedbox-0.6.0}/pyproject.toml +41 -3
  75. sharedbox-0.6.0/scripts/release_notes.py +52 -0
  76. sharedbox-0.6.0/scripts/stream_compare.py +101 -0
  77. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/__init__.py +30 -1
  78. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_arrays.py +9 -2
  79. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_box.py +41 -19
  80. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_events.py +71 -100
  81. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_layout.py +50 -6
  82. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native/codec.cpp +3 -1
  83. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native/module.cpp +7 -28
  84. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native/segment.cpp +41 -41
  85. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native/segment.hpp +9 -5
  86. sharedbox-0.6.0/src/sharedbox/_native/stream.cpp +668 -0
  87. sharedbox-0.6.0/src/sharedbox/_native/stream.hpp +10 -0
  88. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native/types.cpp +222 -9
  89. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native/types.hpp +41 -0
  90. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native.pyi +127 -17
  91. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_refs.py +10 -6
  92. sharedbox-0.6.0/src/sharedbox/_stream.py +1591 -0
  93. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_types.py +85 -6
  94. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_version.py +3 -3
  95. sharedbox-0.6.0/src/sharedbox/benchmarks/__init__.py +3 -0
  96. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/benchmarks/_app.py +40 -6
  97. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/benchmarks/ops.py +41 -0
  98. sharedbox-0.6.0/src/sharedbox/benchmarks/plot.py +331 -0
  99. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/benchmarks/roundtrip.py +51 -2
  100. sharedbox-0.6.0/src/sharedbox/benchmarks/stream.py +906 -0
  101. sharedbox-0.6.0/src/sharedbox/py.typed +0 -0
  102. {sharedbox-0.5.0 → sharedbox-0.6.0}/stubtest-allowlist.txt +12 -1
  103. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/conftest.py +7 -3
  104. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/CMakeLists.txt +6 -2
  105. sharedbox-0.6.0/tests/cpp/bench_stream.cpp +83 -0
  106. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/compile_fail.cpp +1 -1
  107. sharedbox-0.6.0/tests/cpp/test_core_alone.cpp +10 -0
  108. sharedbox-0.6.0/tests/cpp/test_layout3.cpp +187 -0
  109. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_lock.cpp +8 -8
  110. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_mapping.cpp +76 -53
  111. sharedbox-0.6.0/tests/cpp/test_result.cpp +171 -0
  112. sharedbox-0.6.0/tests/cpp/test_slots.cpp +302 -0
  113. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_small_shm.cpp +1 -2
  114. sharedbox-0.6.0/tests/cpp/test_stream.cpp +965 -0
  115. sharedbox-0.6.0/tests/cpp/test_stream_layout.cpp +155 -0
  116. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_types.cpp +6 -30
  117. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_values.cpp +15 -15
  118. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_wait.cpp +80 -5
  119. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_write_in_place.cpp +3 -3
  120. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/crossproc.py +16 -1
  121. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/forged_open.py +25 -9
  122. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/forged_types.py +5 -4
  123. sharedbox-0.6.0/tests/os_names.py +8 -0
  124. sharedbox-0.6.0/tests/streamproc.py +179 -0
  125. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/stress/stress_helpers.py +3 -3
  126. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/stress/test_stress_read_into.py +1 -1
  127. sharedbox-0.6.0/tests/test_benchbox_all.py +62 -0
  128. sharedbox-0.6.0/tests/test_benchbox_plot.py +154 -0
  129. sharedbox-0.6.0/tests/test_benchbox_roundtrip.py +8 -0
  130. sharedbox-0.6.0/tests/test_benchbox_stream.py +149 -0
  131. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_box.py +34 -1
  132. sharedbox-0.6.0/tests/test_box_sync_async.py +62 -0
  133. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_capsule.py +12 -6
  134. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_doc_tutorials.py +11 -9
  135. sharedbox-0.6.0/tests/test_events_future.py +281 -0
  136. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_fields.py +2 -1
  137. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_fork.py +1 -9
  138. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_layout.py +2 -2
  139. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_native_segment.py +85 -50
  140. sharedbox-0.6.0/tests/test_native_stream.py +383 -0
  141. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_native_types.py +0 -20
  142. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_native_waiters.py +5 -4
  143. sharedbox-0.6.0/tests/test_properties_stream.py +121 -0
  144. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_refs.py +49 -3
  145. sharedbox-0.6.0/tests/test_stream.py +627 -0
  146. sharedbox-0.6.0/tests/test_stream_async.py +480 -0
  147. sharedbox-0.6.0/tests/test_stream_events.py +488 -0
  148. sharedbox-0.6.0/tests/test_stream_fork.py +72 -0
  149. sharedbox-0.6.0/tests/test_stream_processes.py +268 -0
  150. sharedbox-0.6.0/tests/test_stream_writing.py +350 -0
  151. sharedbox-0.6.0/tests/test_types_arrays.py +569 -0
  152. sharedbox-0.6.0/tests/type_checks/array_types.py +20 -0
  153. sharedbox-0.6.0/tests/type_checks/stream_types.py +58 -0
  154. {sharedbox-0.5.0 → sharedbox-0.6.0}/uv.lock +43 -547
  155. {sharedbox-0.5.0 → sharedbox-0.6.0}/zensical.toml +5 -1
  156. sharedbox-0.5.0/.claude/settings.json +0 -33
  157. sharedbox-0.5.0/docs/assets/benchmarks/ops-dark.svg +0 -1209
  158. sharedbox-0.5.0/docs/assets/benchmarks/ops-light.svg +0 -1209
  159. sharedbox-0.5.0/docs/assets/benchmarks/roundtrip-dark.svg +0 -334
  160. sharedbox-0.5.0/docs/assets/benchmarks/roundtrip-light.svg +0 -334
  161. sharedbox-0.5.0/docs/examples/change_several_fields_at_once.py +0 -44
  162. sharedbox-0.5.0/docs/examples/clean_up_segments.py +0 -38
  163. sharedbox-0.5.0/docs/examples/follow_a_whole_reference_graph.py +0 -46
  164. sharedbox-0.5.0/docs/examples/name_a_box.py +0 -45
  165. sharedbox-0.5.0/docs/examples/set_defaults_and_check_values.py +0 -79
  166. sharedbox-0.5.0/docs/examples/store_arrays.py +0 -52
  167. sharedbox-0.5.0/docs/examples/store_collections.py +0 -39
  168. sharedbox-0.5.0/docs/examples/store_records.py +0 -52
  169. sharedbox-0.5.0/docs/explanation/performance.md +0 -82
  170. sharedbox-0.5.0/docs/explanation/when-to-use-sharedbox.md +0 -46
  171. sharedbox-0.5.0/docs/how-to/make-a-release.md +0 -88
  172. sharedbox-0.5.0/docs/reference/api/errors.md +0 -43
  173. sharedbox-0.5.0/docs/tutorials/motor.py +0 -102
  174. sharedbox-0.5.0/docs/tutorials/refer-to-another-box.md +0 -104
  175. sharedbox-0.5.0/src/sharedbox/benchmarks/__init__.py +0 -5
  176. sharedbox-0.5.0/src/sharedbox/benchmarks/plot.py +0 -161
  177. sharedbox-0.5.0/tests/cpp/test_layout2.cpp +0 -126
  178. sharedbox-0.5.0/tests/cpp/test_result.cpp +0 -121
  179. sharedbox-0.5.0/tests/cpp/test_slots.cpp +0 -157
  180. sharedbox-0.5.0/tests/test_benchbox_plot.py +0 -63
  181. sharedbox-0.5.0/tests/test_layout_v1.py +0 -50
  182. sharedbox-0.5.0/tests/test_types_arrays.py +0 -212
  183. {sharedbox-0.5.0 → sharedbox-0.6.0}/.clang-format +0 -0
  184. {sharedbox-0.5.0 → sharedbox-0.6.0}/.github/workflows/check-docs.yaml +0 -0
  185. {sharedbox-0.5.0 → sharedbox-0.6.0}/.github/workflows/codspeed.yml +0 -0
  186. {sharedbox-0.5.0 → sharedbox-0.6.0}/.github/workflows/contention.yaml +0 -0
  187. {sharedbox-0.5.0 → sharedbox-0.6.0}/.github/workflows/publish-docs.yaml +0 -0
  188. {sharedbox-0.5.0 → sharedbox-0.6.0}/LICENSE +0 -0
  189. {sharedbox-0.5.0 → sharedbox-0.6.0}/benchmarks/test_bench_box.py +0 -0
  190. /sharedbox-0.5.0/src/sharedbox/py.typed → /sharedbox-0.6.0/changelog.d/.gitkeep +0 -0
  191. {sharedbox-0.5.0 → sharedbox-0.6.0}/cmake/sharedbox-config.cmake +0 -0
  192. {sharedbox-0.5.0 → sharedbox-0.6.0}/cmake/sharedbox-require-cxx.cmake +0 -0
  193. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/diagrams/style.d2 +0 -0
  194. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/checking-a-process-is-alive.md +0 -0
  195. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/how-the-module-is-built.md +0 -0
  196. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/index.md +0 -0
  197. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/explanation/reading-and-writing.md +0 -0
  198. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/ai-contribution-policy.md +0 -0
  199. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/build-docs.md +0 -0
  200. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/contribute.md +0 -0
  201. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/install-sharedbox.md +0 -0
  202. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/run-commit-checks.md +0 -0
  203. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/run-tests.md +0 -0
  204. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/set-defaults-and-check-values.md +0 -0
  205. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/set-up-development.md +0 -0
  206. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/store-collections.md +0 -0
  207. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/store-records.md +0 -0
  208. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/how-to/store-text-and-bytes.md +0 -0
  209. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/api/box.md +0 -0
  210. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/api/library-authors.md +0 -0
  211. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/api/references.md +0 -0
  212. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/changelog.md +0 -0
  213. {sharedbox-0.5.0 → sharedbox-0.6.0}/docs/reference/index.md +0 -0
  214. {sharedbox-0.5.0 → sharedbox-0.6.0}/includes/abbreviations.md +0 -0
  215. {sharedbox-0.5.0 → sharedbox-0.6.0}/prek.toml +0 -0
  216. {sharedbox-0.5.0 → sharedbox-0.6.0}/scripts/check_xrefs.py +0 -0
  217. {sharedbox-0.5.0 → sharedbox-0.6.0}/scripts/vscode_setup.py +0 -0
  218. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_follow.py +0 -0
  219. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native/codec.hpp +0 -0
  220. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native/scalars.cpp +0 -0
  221. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/_native/scalars.hpp +0 -0
  222. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/benchmarks/__main__.py +0 -0
  223. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/benchmarks/cli.py +0 -0
  224. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/benchmarks/contention.py +0 -0
  225. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/benchmarks/size.py +0 -0
  226. {sharedbox-0.5.0 → sharedbox-0.6.0}/src/sharedbox/benchmarks/size_diff.py +0 -0
  227. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/consumer/CMakeLists.txt +0 -0
  228. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/consumer/consumer.c +0 -0
  229. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/table_builder.hpp +0 -0
  230. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_atomics.cpp +0 -0
  231. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_c_smoke.c +0 -0
  232. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_c_smoke_box.cpp +0 -0
  233. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_fork.cpp +0 -0
  234. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/test_windows_h.cpp +0 -0
  235. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/cpp/unique.hpp +0 -0
  236. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/refs_future.py +0 -0
  237. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/stress/test_stress_contention.py +0 -0
  238. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/stress/test_stress_crashes.py +0 -0
  239. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/stress/test_stress_follow.py +0 -0
  240. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/stress/test_stress_lock_timeout.py +0 -0
  241. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/stress/test_stress_memory.py +0 -0
  242. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/stress/test_stress_waiters.py +0 -0
  243. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/stress/test_stress_watchers.py +0 -0
  244. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_benchbox_contention.py +0 -0
  245. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_doc_examples.py +0 -0
  246. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_events_async.py +0 -0
  247. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_events_bytes.py +0 -0
  248. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_events_signals.py +0 -0
  249. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_events_sync.py +0 -0
  250. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_exit.py +0 -0
  251. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_follow.py +0 -0
  252. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_native_codec.py +0 -0
  253. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_native_liveness.py +0 -0
  254. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_native_wait.py +0 -0
  255. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_properties_codec.py +0 -0
  256. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_properties_forged.py +0 -0
  257. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_properties_layout.py +0 -0
  258. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_properties_stateful.py +0 -0
  259. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_properties_types.py +0 -0
  260. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_read_into.py +0 -0
  261. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_refs_lazy.py +0 -0
  262. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_types_arrays_bfloat16.py +0 -0
  263. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_types_arrays_torch.py +0 -0
  264. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_types_choices.py +0 -0
  265. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_types_collections.py +0 -0
  266. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_types_records.py +0 -0
  267. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_types_records_attrs.py +0 -0
  268. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_types_records_msgspec.py +0 -0
  269. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_types_scalars.py +0 -0
  270. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_types_unions.py +0 -0
  271. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_value_reuse.py +0 -0
  272. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/test_writing.py +0 -0
  273. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/type_checks/box_types.py +0 -0
  274. {sharedbox-0.5.0 → sharedbox-0.6.0}/tests/type_checks/events_types.py +0 -0
@@ -4,6 +4,7 @@ updates:
4
4
  directory: /
5
5
  schedule:
6
6
  interval: weekly
7
+ labels: [dependencies, skip-changelog]
7
8
  commit-message:
8
9
  prefix: ci
9
10
  groups:
@@ -14,6 +15,7 @@ updates:
14
15
  directory: /
15
16
  schedule:
16
17
  interval: weekly
18
+ labels: [dependencies, skip-changelog]
17
19
  commit-message:
18
20
  prefix: build
19
21
  include: scope
@@ -0,0 +1,3 @@
1
+ <!-- One bullet per change a reviewer can see, in the imperative. -->
2
+
3
+ - [ ] Added a file to `changelog.d/` for each change a user notices, or this pull request changes nothing a user notices and needs the `skip-changelog` label
@@ -0,0 +1,47 @@
1
+ name: Changelog
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, reopened, synchronize, labeled, unlabeled]
6
+
7
+ permissions:
8
+ contents: read
9
+ pull-requests: read
10
+
11
+ jobs:
12
+ entry:
13
+ name: Require a changelog entry
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Read the labels
17
+ id: labels
18
+ env:
19
+ GH_TOKEN: ${{ github.token }}
20
+ PR: ${{ github.event.pull_request.number }}
21
+ REPO: ${{ github.repository }}
22
+ run: |
23
+ # read now rather than from the event: a pull request opened with a
24
+ # label gets it a moment after its "opened" event fires
25
+ skip=$(gh pr view "$PR" --repo "$REPO" --json labels --jq 'any(.labels[]; .name == "skip-changelog")')
26
+ echo "skip=$skip" >> "$GITHUB_OUTPUT"
27
+ if [ "$skip" = "true" ]; then
28
+ echo "Labelled skip-changelog: no entry needed."
29
+ fi
30
+
31
+ - uses: actions/checkout@v7
32
+ if: steps.labels.outputs.skip != 'true'
33
+ with:
34
+ fetch-depth: 0
35
+
36
+ - name: Install uv
37
+ if: steps.labels.outputs.skip != 'true'
38
+ uses: astral-sh/setup-uv@v7
39
+
40
+ - name: Check for an entry in changelog.d
41
+ if: steps.labels.outputs.skip != 'true'
42
+ run: |
43
+ uvx towncrier==26.9.0 check --compare-with "origin/${{ github.base_ref }}" || {
44
+ echo "Add a file to changelog.d/ for each change, or ask for the skip-changelog label:"
45
+ echo "https://jacopoabramo.github.io/sharedbox/how-to/commits-and-prs/#changelog-entries"
46
+ exit 1
47
+ }
@@ -19,7 +19,7 @@ jobs:
19
19
  # local hooks in prek.toml call `uv run --locked --only-group lint ...`
20
20
  - uses: astral-sh/setup-uv@v7
21
21
 
22
- - uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0
22
+ - uses: j178/prek-action@44924fe9ef4a6f88253c4b6b1bf11c689d3ce53d # v3.1.0
23
23
  with:
24
24
  prek-version: "0.5.3"
25
25
 
@@ -88,7 +88,7 @@ jobs:
88
88
  - name: Create a box larger than a 16 MiB /dev/shm
89
89
  if: runner.os == 'Linux' && matrix.build == 'Release'
90
90
  run: |
91
- docker run --rm --shm-size=16m -v "$PWD":/src -w /src ubuntu:24.04 build-cpp/test_small_shm
91
+ sudo unshare --mount sh -c 'mount -t tmpfs -o size=16m tmpfs /dev/shm && build-cpp/test_small_shm'
92
92
 
93
93
  build_wheels:
94
94
  name: Build wheel for ${{ matrix.python }}-${{ matrix.platform_id }}
@@ -114,7 +114,7 @@ jobs:
114
114
  ref: ${{ github.event_name == 'release' && github.event.release.tag_name || '' }}
115
115
 
116
116
  - name: Build wheels
117
- uses: pypa/cibuildwheel@v4.2.1
117
+ uses: pypa/cibuildwheel@v4.3.2
118
118
  env:
119
119
  CIBW_BUILD: ${{ matrix.python }}-${{ matrix.platform_id }}
120
120
  CIBW_CONTAINER_ENGINE: "docker; create_args: --shm-size=1g"
@@ -248,6 +248,14 @@ jobs:
248
248
  fetch-depth: 0
249
249
  ref: ${{ github.event_name == 'release' && github.event.release.tag_name || '' }}
250
250
 
251
+ - name: Check the changelog has a section for a final release
252
+ env:
253
+ TAG: ${{ github.event.release.tag_name }}
254
+ run: |
255
+ if [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
256
+ python3 scripts/release_notes.py extract "${TAG#v}" > /dev/null
257
+ fi
258
+
251
259
  - name: Build SDist
252
260
  run: pipx run build --sdist
253
261
 
@@ -280,3 +288,25 @@ jobs:
280
288
  merge-multiple: true
281
289
 
282
290
  - uses: pypa/gh-action-pypi-publish@release/v1
291
+
292
+ # final releases only: a release candidate's entries stay in changelog.d
293
+ # for the final release's section
294
+ github_release:
295
+ name: Write the GitHub release notes
296
+ needs: [upload_pypi]
297
+ if: github.event_name == 'release' && !github.event.release.prerelease
298
+ runs-on: ubuntu-latest
299
+ permissions:
300
+ contents: write
301
+ steps:
302
+ - uses: actions/checkout@v7
303
+ with:
304
+ ref: ${{ github.event.release.tag_name }}
305
+
306
+ - name: Write the release's notes from its changelog section
307
+ env:
308
+ GH_TOKEN: ${{ github.token }}
309
+ TAG: ${{ github.event.release.tag_name }}
310
+ run: |
311
+ python3 scripts/release_notes.py extract "${TAG#v}" > notes.md
312
+ gh release edit "$TAG" --title "$TAG" --notes-file notes.md
@@ -0,0 +1,90 @@
1
+ name: Ops
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [ main ]
6
+ paths:
7
+ - include/sharedbox/**
8
+ - src/sharedbox/_native/**
9
+ - src/sharedbox/benchmarks/ops.py
10
+ - .github/workflows/ops.yaml
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ jobs:
17
+ ops:
18
+ name: Reads and writes against the base branch on Windows
19
+ runs-on: windows-latest
20
+ timeout-minutes: 60
21
+ steps:
22
+ - uses: actions/checkout@v7
23
+ with:
24
+ path: head
25
+ fetch-depth: 0
26
+
27
+ - uses: actions/checkout@v7
28
+ with:
29
+ ref: ${{ github.base_ref || 'main' }}
30
+ path: base
31
+ fetch-depth: 0
32
+
33
+ - uses: astral-sh/setup-uv@v7
34
+
35
+ - name: Install both
36
+ shell: bash
37
+ run: |
38
+ for side in base head; do
39
+ (cd "$side" && uv sync --frozen --python 3.11)
40
+ done
41
+
42
+ - name: Run benchbox ops, alternating base and head
43
+ shell: bash
44
+ run: |
45
+ mkdir results
46
+ for round in 1 2 3; do
47
+ for side in base head; do
48
+ for rows in int record; do
49
+ (cd "$side" && uv run --no-sync benchbox ops --fast \
50
+ --filter "*$rows/SharedBox" --json "../results/$side-$round-$rows.json")
51
+ done
52
+ done
53
+ done
54
+
55
+ - name: Compare the medians
56
+ shell: bash
57
+ run: |
58
+ cd head
59
+ uv run --no-sync python - ../results <<'EOF' | tee -a "$GITHUB_STEP_SUMMARY"
60
+ import statistics
61
+ import sys
62
+ from pathlib import Path
63
+
64
+ import pyperf
65
+ from sharedbox.benchmarks._app import machine
66
+
67
+ means: dict[tuple[str, str], list[float]] = {}
68
+ for path in sorted(Path(sys.argv[1]).glob("*.json")):
69
+ side = path.name.split("-")[0]
70
+ for bench in pyperf.BenchmarkSuite.load(str(path)).get_benchmarks():
71
+ means.setdefault((bench.get_name(), side), []).append(bench.mean())
72
+ print("### benchbox ops on Windows cp311, median of three rounds")
73
+ print()
74
+ print(machine())
75
+ print()
76
+ print("| benchmark | base | head | head / base |")
77
+ print("| --- | --- | --- | --- |")
78
+ for name in sorted({name for name, _ in means}):
79
+ base = statistics.median(means.get((name, "base"), [0.0]))
80
+ head = statistics.median(means.get((name, "head"), [0.0]))
81
+ # A row added or removed by the pull request has times on one side only.
82
+ cells = [f"{v * 1e9:.1f} ns" if v else "-" for v in (base, head)]
83
+ ratio = f"{head / base:.3f}" if base and head else "-"
84
+ print(f"| {name} | {cells[0]} | {cells[1]} | {ratio} |")
85
+ EOF
86
+
87
+ - uses: actions/upload-artifact@v7
88
+ with:
89
+ name: ops
90
+ path: results
@@ -0,0 +1,78 @@
1
+ name: Prepare release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ version:
7
+ description: "Version to release, such as 0.6.0, without the v"
8
+ required: true
9
+ type: string
10
+ dry_run:
11
+ description: "Only show the changelog section, in the run's summary"
12
+ required: false
13
+ type: boolean
14
+ default: false
15
+
16
+ permissions:
17
+ contents: write
18
+ pull-requests: write
19
+
20
+ jobs:
21
+ prepare:
22
+ name: Write the changelog section and open the release pull request
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - name: Check the version
26
+ env:
27
+ VERSION: ${{ inputs.version }}
28
+ run: |
29
+ if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
30
+ echo "The version must look like 0.6.0, without the v; got '$VERSION'."
31
+ echo "Tag a release candidate instead of preparing it."
32
+ exit 1
33
+ fi
34
+
35
+ - uses: actions/checkout@v7
36
+ with:
37
+ ref: main
38
+
39
+ - name: Check there is something to release
40
+ env:
41
+ VERSION: ${{ inputs.version }}
42
+ run: |
43
+ # towncrier refuses a version only when the whole heading matches,
44
+ # date included, so on a later day it would write a second section
45
+ if python3 scripts/release_notes.py extract "$VERSION" > /dev/null 2>&1; then
46
+ echo "The changelog already has a section for $VERSION."
47
+ exit 1
48
+ fi
49
+ if [ -z "$(find changelog.d -type f ! -name .gitkeep)" ]; then
50
+ echo "changelog.d holds no entries, so there is nothing to release."
51
+ exit 1
52
+ fi
53
+
54
+ - name: Install uv
55
+ uses: astral-sh/setup-uv@v7
56
+
57
+ - name: Write the section
58
+ env:
59
+ VERSION: ${{ inputs.version }}
60
+ run: |
61
+ git config user.name "github-actions[bot]"
62
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
63
+ uvx towncrier==26.9.0 build --yes --version "$VERSION" --date "$(date -u +%d-%m-%Y)"
64
+ python3 scripts/release_notes.py extract "$VERSION" > notes.md
65
+ cat notes.md >> "$GITHUB_STEP_SUMMARY"
66
+
67
+ - name: Open the release pull request
68
+ if: ${{ !inputs.dry_run }}
69
+ env:
70
+ VERSION: ${{ inputs.version }}
71
+ GH_TOKEN: ${{ github.token }}
72
+ run: |
73
+ branch="release/v$VERSION"
74
+ git switch -c "$branch"
75
+ git commit -m "docs: write the $VERSION changelog"
76
+ git push origin "$branch"
77
+ gh pr create --base main --head "$branch" --label skip-changelog \
78
+ --title "docs: write the $VERSION changelog" --body-file notes.md
@@ -0,0 +1,85 @@
1
+ name: Streams
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [ main ]
6
+ paths:
7
+ - include/sharedbox/stream.hpp
8
+ - include/sharedbox/core.hpp
9
+ - src/sharedbox/_stream.py
10
+ - src/sharedbox/_native/stream.cpp
11
+ - src/sharedbox/_native/types.cpp
12
+ - src/sharedbox/_native/codec.cpp
13
+ - src/sharedbox/benchmarks/stream.py
14
+ - scripts/stream_compare.py
15
+ - .github/workflows/streams.yaml
16
+ workflow_dispatch:
17
+ inputs:
18
+ base:
19
+ description: Commit, branch or tag to compare against
20
+ required: false
21
+ default: main
22
+
23
+ permissions:
24
+ contents: read
25
+
26
+ jobs:
27
+ streams:
28
+ name: Streams against the base on ${{ matrix.os }}
29
+ runs-on: ${{ matrix.os }}
30
+ timeout-minutes: 60
31
+ strategy:
32
+ fail-fast: false
33
+ matrix:
34
+ os: [ ubuntu-latest, windows-latest ]
35
+ steps:
36
+ - uses: actions/checkout@v7
37
+ with:
38
+ path: head
39
+ fetch-depth: 0
40
+ - uses: actions/checkout@v7
41
+ with:
42
+ ref: ${{ inputs.base || github.base_ref || 'main' }}
43
+ path: base
44
+ fetch-depth: 0
45
+ - uses: astral-sh/setup-uv@v7
46
+ - name: Install both
47
+ shell: bash
48
+ run: |
49
+ for side in base head; do
50
+ (cd "$side" && uv sync --frozen --python 3.12)
51
+ done
52
+ - name: Check the base has SharedStream
53
+ id: base
54
+ shell: bash
55
+ run: |
56
+ if (cd base && uv run --no-sync python -c "import sharedbox; sharedbox.SharedStream"); then
57
+ echo "sides=base head" >> "$GITHUB_OUTPUT"
58
+ else
59
+ echo "sides=head" >> "$GITHUB_OUTPUT"
60
+ echo "base has no SharedStream; head only" | tee -a "$GITHUB_STEP_SUMMARY"
61
+ fi
62
+ - name: Run the stream benchmarks, alternating
63
+ shell: bash
64
+ run: |
65
+ mkdir results
66
+ for round in 1 2 3; do
67
+ if [ "${{ steps.base.outputs.sides }}" != "head" ]; then
68
+ (cd base && uv run --no-sync python ../head/src/sharedbox/benchmarks/stream.py \
69
+ --short --table both --json "../results/base-$round.json") \
70
+ || echo "::warning::base round $round failed"
71
+ fi
72
+ (cd head && uv run --no-sync python ../head/src/sharedbox/benchmarks/stream.py \
73
+ --short --table both --json "../results/head-$round.json")
74
+ done
75
+ - name: Compare
76
+ if: ${{ !cancelled() }}
77
+ shell: bash
78
+ run: |
79
+ cd head
80
+ uv run --no-sync python ../head/scripts/stream_compare.py ../results | tee -a "$GITHUB_STEP_SUMMARY"
81
+ - uses: actions/upload-artifact@v7
82
+ if: ${{ !cancelled() }}
83
+ with:
84
+ name: streams-${{ matrix.os }}
85
+ path: results
@@ -20,9 +20,10 @@ wheelhouse/
20
20
 
21
21
  graphify-out/
22
22
 
23
- build-cpp/
23
+ build-cpp*/
24
24
 
25
25
  .hypothesis/
26
+ .claude/settings.json
26
27
  .claude/settings.local.json
27
28
 
28
29
  site/
@@ -7,7 +7,139 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  Dates are marked as `DD-MM-YYYY`
9
9
 
10
- ## [Unreleased]
10
+ <!-- towncrier release notes start -->
11
+
12
+ ## [0.6.0](https://github.com/jacopoabramo/sharedbox/releases/tag/v0.6.0) - 24-10-2026
13
+
14
+ ### Added
15
+
16
+ - `status::foreign` and `SBX_E_FOREIGN` (-12): the segment's magic is not
17
+ one this version knows. Python raises `SchemaMismatchError`. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
18
+ - `sharedbox::to_expected` and `sharedbox::from_expected`: convert a
19
+ `sharedbox::result` to a `std::expected` and back on C++23. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
20
+ - `KindMismatchError`, a `SchemaMismatchError` raised when a name holds a
21
+ segment of another kind; `status::kind_mismatch` and `SBX_E_KIND` (-11)
22
+ in `sharedbox.hpp` and `sharedbox_c.h`. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
23
+ - `sharedbox::stream`, `sharedbox::stream_sender` and `sharedbox::stream_reader`
24
+ in `stream.hpp`, included by `sharedbox.hpp`: a ring in shared memory with
25
+ one sender and up to `max_readers` readers, each reading
26
+ `read_mode::lossless`, `read_mode::lossy` or `read_mode::latest`, laid out
27
+ as stream layout 1.0. C++ only. `stream_sender::begin`, `publish` and
28
+ `abandon` reserve a slot, fill it in place and publish it or give it up. ([#48](https://github.com/jacopoabramo/sharedbox/pull/48))
29
+ - `status::busy` (-13), `status::ended` (-14) and `status::interrupted`
30
+ (-15), with `SBX_E_BUSY`, `SBX_E_ENDED` and `SBX_E_INTERRUPTED` in
31
+ `sharedbox_c.h`. ([#48](https://github.com/jacopoabramo/sharedbox/pull/48))
32
+ - `SharedStream`, `SharedSendStream` and `SharedReceiveStream`: send items of
33
+ any type a `SharedBox` field takes from one process to up to `max_readers`
34
+ readers, each reading `lossless`, `lossy` or `latest`, with blocking,
35
+ non-blocking and asyncio calls, `receive_into` into the caller's arrays and
36
+ `receive_future`, a `concurrent.futures.Future`. A stream passed to another
37
+ process arrives attached, or raises `SchemaMismatchError` if its name now
38
+ holds a stream created since, and `SharedStream.create` without a name gives
39
+ the stream a new one. The ends cannot be pickled; `SharedSendStream.stream`
40
+ and `SharedReceiveStream.stream` return their stream. ([#49](https://github.com/jacopoabramo/sharedbox/pull/49))
41
+ - `SharedReceiveStream.events`, a `ReceiveEvents` psygnal group whose
42
+ `received` and `ended` signals deliver a reader's items to callbacks. ([#49](https://github.com/jacopoabramo/sharedbox/pull/49))
43
+ - `WouldBlock`, `EndOfStream`, `StreamBusyError` and `StreamClosedError`. ([#49](https://github.com/jacopoabramo/sharedbox/pull/49))
44
+ - `SharedStreamStatistics` and `ReceiveStreamStatistics`, returned by
45
+ `SharedStream.statistics()`. ([#49](https://github.com/jacopoabramo/sharedbox/pull/49))
46
+ - `WaiterSlotsFullError` is exported from `sharedbox`; opening a reader
47
+ raises it when `max_readers` readers are open. ([#49](https://github.com/jacopoabramo/sharedbox/pull/49))
48
+ - `benchbox ops`: the row `watched write int`, a write while another process
49
+ has a watcher open. ([#50](https://github.com/jacopoabramo/sharedbox/pull/50))
50
+ - `sharedbox::handle::sleepers()`: the number of threads inside a wait on
51
+ the box, in any process. ([#51](https://github.com/jacopoabramo/sharedbox/pull/51))
52
+ - `benchbox stream`: items per second of `SharedStream` readers in each mode
53
+ against `mp.Queue` and a `SharedMemory` ring with a lock, and a table of
54
+ `send` and `asend` with `receive`, `async for` and `events.received`,
55
+ with the 50th, 90th and 99th percentile latency. `--short`, `--table`,
56
+ `--json` and `--markdown` are its options; `benchbox all` runs it and
57
+ writes `stream.json`. ([#53](https://github.com/jacopoabramo/sharedbox/pull/53))
58
+ - `Streams` workflow: `benchbox stream` on the base branch against the pull
59
+ request, with `scripts/stream_compare.py` writing the table. ([#53](https://github.com/jacopoabramo/sharedbox/pull/53))
60
+ - `benchbox roundtrip`: the row `SharedStream`. ([#53](https://github.com/jacopoabramo/sharedbox/pull/53))
61
+ - `benchmarks/test_bench_stream.py`: a CodSpeed benchmark of `send` plus
62
+ `receive_into`. ([#53](https://github.com/jacopoabramo/sharedbox/pull/53))
63
+ - `FieldWatch.future()`, returning a `FieldFuture`, a
64
+ `concurrent.futures.Future` of the next write to the field; `FieldFuture`
65
+ is exported from `sharedbox`. ([#55](https://github.com/jacopoabramo/sharedbox/pull/55))
66
+ - `field(shape=...)`: the sizes of an array field of a box.
67
+
68
+ ```python
69
+ class Grid(SharedBox):
70
+ cells: npt.NDArray[np.uint8] = np.zeros((4, 6), np.uint8)
71
+ weights: npt.NDArray[np.float32] = field(shape=(3,))
72
+ ```
73
+
74
+ A box array field also takes its sizes from a plain default array, so it
75
+ needs no `Shape` and, with a dtype in its annotation, no `DType`. ([#56](https://github.com/jacopoabramo/sharedbox/pull/56))
76
+ - `SharedSendStream.writing()` and `SharedSendStream.awriting()`, which yield a
77
+ `SendSlot`:
78
+
79
+ ```python
80
+ blank = Frame(0, np.empty((0, 0), np.uint16))
81
+ with sender.writing(blank) as slot:
82
+ slot.item.image.fill(0)
83
+ slot.send(replace(slot.item, index=1))
84
+ ```
85
+
86
+ `slot.item` is an item built from a template, with arrays over the next slot
87
+ to fill in place, and `slot.send(item)` publishes an item without copying the
88
+ arrays already in the slot. ([#58](https://github.com/jacopoabramo/sharedbox/pull/58))
89
+
90
+ ### Changed
91
+
92
+ - `sharedbox.hpp`: split into `core.hpp` and `box.hpp`, which it includes.
93
+ `sharedbox::result` is the library's own type on C++20 and C++23 alike,
94
+ and its `error()` is a `sharedbox::error` holding the status, the OS error
95
+ and what was found. The C++ names moved from `sharedbox::v2` to
96
+ `sharedbox::v3`. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
97
+ - `sharedbox::header`: the magic, versions, schema hash, creator, waiter
98
+ slot count and size moved into its first member, `common`, a
99
+ `sharedbox::common_header`; `layout_major` and `layout_minor` became
100
+ `common.kind_major` and `common.kind_minor`. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
101
+ - `sharedbox::error`: a `status::os` failure carries the OS error in
102
+ `error().os`; `errno` and `GetLastError()` no longer hold it reliably
103
+ when the call returns. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
104
+ - Segment layout: every segment starts with a common first line (magic,
105
+ core version, layout version of its kind, schema hash, creator), and
106
+ boxes use layout 3.0. A box made by 0.5 cannot be opened by 0.6, nor the
107
+ other way round. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
108
+ - `sharedbox::inspect`: returns `result<common_header>`. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
109
+ - `sharedbox::magic`: renamed `sharedbox::box_magic`. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
110
+ - `box_ref`: a reference field stores the name of its target in 240 bytes,
111
+ so the field takes 256 bytes. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
112
+ - `SharedBox` names: one or more segments of `[A-Za-z0-9_-]` joined by
113
+ `:`, up to 240 characters, such as `bl01:camera:det1:frames`. `.` is no
114
+ longer allowed. The shared memory is `/dev/shm/SBX:<name>` on Linux and
115
+ `Local\SBX:<name>` on Windows, and Windows waiter events end in `#w<i>`. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
116
+ - `SharedBox.attach`: a segment whose magic this version does not know,
117
+ such as a box made by 0.5, raises `SchemaMismatchError` at once, instead
118
+ of `SegmentNotFoundError` after the timeout. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
119
+ - `SharedBox` write: makes a wake call only when a thread is waiting on the
120
+ box. `sleepers`, at offset 84 of box layout 3.0, counts the threads inside
121
+ a wait. It adds 1 to `wake_word` only when `sleepers` is not 0. ([#51](https://github.com/jacopoabramo/sharedbox/pull/51))
122
+ - `sharedbox::waiter_slot`: 32 bytes, with `asleep_on`, at offset 24, the
123
+ offset of the count the slot's current wait added 1 to, and a reserved
124
+ word. Freeing the slot of a process killed inside a wait takes that
125
+ thread out of `sleepers` for a box, and out of `data_waiting` or
126
+ `space_waiting` for a stream. ([#51](https://github.com/jacopoabramo/sharedbox/pull/51))
127
+ - `benchbox plot`: writes plotly figure JSON (`charts/ops.json`,
128
+ `roundtrip.json`, `stream-throughput.json`, `stream-matrix.json`) instead
129
+ of SVG files. ([#53](https://github.com/jacopoabramo/sharedbox/pull/53))
130
+ - `benchmarks` extra and group: depend on `plotly` instead of `matplotlib`. ([#53](https://github.com/jacopoabramo/sharedbox/pull/53))
131
+ - Array fields: an annotation that names its number of dimensions, as in
132
+ `numpy.ndarray[tuple[int, int], numpy.dtype[numpy.uint8]]`, raises
133
+ `TypeError` when its `Shape` has another number, in a box, a record and a
134
+ stream item. ([#56](https://github.com/jacopoabramo/sharedbox/pull/56))
135
+ - Array fields: a default array whose shape differs from the field's `Shape`
136
+ raises `TypeError` instead of `ValueError` when the class is defined. ([#56](https://github.com/jacopoabramo/sharedbox/pull/56))
137
+
138
+ ### Removed
139
+
140
+ - Reading box layouts 1.0 and 2.0. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
141
+ - `sharedbox::oldest_layout_major`. ([#47](https://github.com/jacopoabramo/sharedbox/pull/47))
142
+
11
143
 
12
144
  ## [0.5.0] - 09-10-2026
13
145
 
@@ -330,7 +462,6 @@ stage.events.nested.connect(lambda path, new, old: print(path, new))
330
462
 
331
463
  - Initial release
332
464
 
333
- [Unreleased]: https://github.com/jacopoabramo/sharedbox/compare/v0.5.0...HEAD
334
465
  [0.5.0]: https://github.com/jacopoabramo/sharedbox/compare/v0.4.1...v0.5.0
335
466
  [0.4.1]: https://github.com/jacopoabramo/sharedbox/compare/v0.4.0...v0.4.1
336
467
  [0.4.0]: https://github.com/jacopoabramo/sharedbox/compare/v0.3.1...v0.4.0