sharedbox 0.4.1__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 (308) hide show
  1. {sharedbox-0.4.1 → 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.4.1 → sharedbox-0.6.0}/.github/workflows/ci.yaml +33 -3
  5. sharedbox-0.6.0/.github/workflows/contention.yaml +45 -0
  6. sharedbox-0.6.0/.github/workflows/ops.yaml +90 -0
  7. sharedbox-0.6.0/.github/workflows/prepare-release.yaml +78 -0
  8. sharedbox-0.6.0/.github/workflows/streams.yaml +85 -0
  9. {sharedbox-0.4.1 → sharedbox-0.6.0}/.gitignore +2 -1
  10. {sharedbox-0.4.1 → sharedbox-0.6.0}/CHANGELOG.md +173 -2
  11. {sharedbox-0.4.1 → sharedbox-0.6.0}/CLAUDE.md +129 -61
  12. {sharedbox-0.4.1 → sharedbox-0.6.0}/CMakeLists.txt +1 -0
  13. sharedbox-0.6.0/PKG-INFO +129 -0
  14. sharedbox-0.6.0/README.md +105 -0
  15. {sharedbox-0.4.1 → sharedbox-0.6.0}/benchmarks/test_bench_box.py +41 -0
  16. sharedbox-0.6.0/benchmarks/test_bench_stream.py +31 -0
  17. sharedbox-0.6.0/docs/assets/benchmarks/ops.json +1 -0
  18. sharedbox-0.6.0/docs/assets/benchmarks/roundtrip.json +1 -0
  19. sharedbox-0.6.0/docs/assets/benchmarks/stream-matrix.json +1 -0
  20. sharedbox-0.6.0/docs/assets/benchmarks/stream-throughput.json +1 -0
  21. sharedbox-0.6.0/docs/diagrams/style.d2 +61 -0
  22. sharedbox-0.6.0/docs/examples/change_several_fields_at_once.py +44 -0
  23. sharedbox-0.6.0/docs/examples/clean_up_segments.py +38 -0
  24. sharedbox-0.6.0/docs/examples/follow_a_whole_reference_graph.py +46 -0
  25. sharedbox-0.6.0/docs/examples/name_a_box.py +45 -0
  26. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/examples/send_a_box_to_another_process.py +14 -14
  27. sharedbox-0.6.0/docs/examples/send_items_through_a_stream.py +129 -0
  28. sharedbox-0.6.0/docs/examples/set_defaults_and_check_values.py +79 -0
  29. sharedbox-0.6.0/docs/examples/store_arrays.py +52 -0
  30. sharedbox-0.6.0/docs/examples/store_collections.py +40 -0
  31. sharedbox-0.6.0/docs/examples/store_records.py +53 -0
  32. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/examples/store_text_and_bytes.py +14 -14
  33. sharedbox-0.6.0/docs/explanation/checking-a-process-is-alive.md +89 -0
  34. sharedbox-0.6.0/docs/explanation/closing-and-lifetime.md +242 -0
  35. sharedbox-0.6.0/docs/explanation/field-types.md +141 -0
  36. sharedbox-0.6.0/docs/explanation/glossary.md +169 -0
  37. sharedbox-0.6.0/docs/explanation/how-a-box-is-stored.md +216 -0
  38. sharedbox-0.6.0/docs/explanation/how-the-module-is-built.md +96 -0
  39. sharedbox-0.6.0/docs/explanation/index.md +44 -0
  40. sharedbox-0.6.0/docs/explanation/limits.md +73 -0
  41. sharedbox-0.6.0/docs/explanation/performance.md +221 -0
  42. sharedbox-0.6.0/docs/explanation/reading-and-writing.md +272 -0
  43. sharedbox-0.6.0/docs/explanation/references.md +154 -0
  44. sharedbox-0.6.0/docs/explanation/waiting-for-changes.md +277 -0
  45. sharedbox-0.6.0/docs/explanation/when-to-use-sharedbox.md +59 -0
  46. sharedbox-0.6.0/docs/how-to/accept-a-box-in-c.md +95 -0
  47. sharedbox-0.6.0/docs/how-to/accept-a-box-in-cpp.md +192 -0
  48. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/build-docs.md +3 -0
  49. sharedbox-0.6.0/docs/how-to/change-several-fields-at-once.md +60 -0
  50. sharedbox-0.6.0/docs/how-to/clean-up-segments.md +93 -0
  51. sharedbox-0.6.0/docs/how-to/commits-and-prs.md +93 -0
  52. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/contribute.md +3 -2
  53. sharedbox-0.6.0/docs/how-to/follow-a-whole-reference-graph.md +73 -0
  54. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/index.md +10 -6
  55. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/install-sharedbox.md +9 -8
  56. sharedbox-0.6.0/docs/how-to/make-a-release.md +76 -0
  57. sharedbox-0.6.0/docs/how-to/name-a-box.md +85 -0
  58. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/open-a-box-from-a-program.md +18 -16
  59. sharedbox-0.6.0/docs/how-to/run-benchmarks.md +175 -0
  60. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/run-commit-checks.md +5 -4
  61. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/run-tests.md +7 -2
  62. sharedbox-0.6.0/docs/how-to/send-a-box-to-another-process.md +127 -0
  63. sharedbox-0.6.0/docs/how-to/send-items-through-a-stream.md +287 -0
  64. sharedbox-0.6.0/docs/how-to/set-defaults-and-check-values.md +84 -0
  65. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/set-up-development.md +3 -1
  66. sharedbox-0.6.0/docs/how-to/store-arrays.md +203 -0
  67. sharedbox-0.6.0/docs/how-to/store-collections.md +71 -0
  68. sharedbox-0.6.0/docs/how-to/store-records.md +79 -0
  69. sharedbox-0.6.0/docs/how-to/store-text-and-bytes.md +68 -0
  70. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/write-docs.md +70 -8
  71. sharedbox-0.6.0/docs/index.md +190 -0
  72. sharedbox-0.6.0/docs/javascripts/charts.js +88 -0
  73. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/reference/api/arrays.md +2 -2
  74. sharedbox-0.6.0/docs/reference/api/errors.md +73 -0
  75. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/reference/api/events.md +8 -1
  76. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/reference/api/index.md +2 -1
  77. sharedbox-0.6.0/docs/reference/api/streams.md +44 -0
  78. sharedbox-0.6.0/docs/reference/cpp-and-c-api.md +42 -0
  79. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/reference/index.md +4 -2
  80. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/reference/segment-layout.md +673 -181
  81. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/tutorials/index.md +6 -4
  82. sharedbox-0.6.0/docs/tutorials/mailbox.py +102 -0
  83. sharedbox-0.6.0/docs/tutorials/react-to-changes.md +149 -0
  84. sharedbox-0.6.0/docs/tutorials/refer-to-another-box.md +106 -0
  85. sharedbox-0.6.0/docs/tutorials/share-a-record.md +131 -0
  86. sharedbox-0.6.0/include/sharedbox/box.hpp +1140 -0
  87. sharedbox-0.4.1/include/sharedbox/sharedbox.hpp → sharedbox-0.6.0/include/sharedbox/core.hpp +650 -1517
  88. sharedbox-0.6.0/include/sharedbox/sharedbox.hpp +21 -0
  89. {sharedbox-0.4.1 → sharedbox-0.6.0}/include/sharedbox/sharedbox_c.cpp +13 -13
  90. {sharedbox-0.4.1 → sharedbox-0.6.0}/include/sharedbox/sharedbox_c.h +5 -0
  91. sharedbox-0.6.0/include/sharedbox/stream.hpp +1038 -0
  92. {sharedbox-0.4.1 → sharedbox-0.6.0}/pyproject.toml +42 -3
  93. sharedbox-0.6.0/scripts/release_notes.py +52 -0
  94. sharedbox-0.6.0/scripts/stream_compare.py +101 -0
  95. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/__init__.py +30 -1
  96. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_arrays.py +9 -2
  97. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_box.py +134 -29
  98. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_events.py +71 -100
  99. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_layout.py +56 -6
  100. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native/codec.cpp +3 -1
  101. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native/module.cpp +180 -35
  102. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native/segment.cpp +85 -42
  103. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native/segment.hpp +40 -5
  104. sharedbox-0.6.0/src/sharedbox/_native/stream.cpp +668 -0
  105. sharedbox-0.6.0/src/sharedbox/_native/stream.hpp +10 -0
  106. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native/types.cpp +347 -25
  107. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native/types.hpp +58 -2
  108. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native.pyi +183 -19
  109. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_refs.py +10 -6
  110. sharedbox-0.6.0/src/sharedbox/_stream.py +1591 -0
  111. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_types.py +119 -7
  112. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_version.py +3 -3
  113. sharedbox-0.6.0/src/sharedbox/benchmarks/__init__.py +3 -0
  114. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/benchmarks/_app.py +76 -6
  115. sharedbox-0.6.0/src/sharedbox/benchmarks/contention.py +324 -0
  116. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/benchmarks/ops.py +50 -0
  117. sharedbox-0.6.0/src/sharedbox/benchmarks/plot.py +331 -0
  118. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/benchmarks/roundtrip.py +51 -2
  119. sharedbox-0.6.0/src/sharedbox/benchmarks/stream.py +906 -0
  120. sharedbox-0.6.0/src/sharedbox/py.typed +0 -0
  121. sharedbox-0.6.0/stubtest-allowlist.txt +30 -0
  122. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/conftest.py +7 -3
  123. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/CMakeLists.txt +6 -2
  124. sharedbox-0.6.0/tests/cpp/bench_stream.cpp +83 -0
  125. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/compile_fail.cpp +1 -1
  126. sharedbox-0.6.0/tests/cpp/test_core_alone.cpp +10 -0
  127. sharedbox-0.6.0/tests/cpp/test_layout3.cpp +187 -0
  128. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_lock.cpp +8 -8
  129. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_mapping.cpp +76 -53
  130. sharedbox-0.6.0/tests/cpp/test_result.cpp +171 -0
  131. sharedbox-0.6.0/tests/cpp/test_slots.cpp +302 -0
  132. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_small_shm.cpp +1 -2
  133. sharedbox-0.6.0/tests/cpp/test_stream.cpp +965 -0
  134. sharedbox-0.6.0/tests/cpp/test_stream_layout.cpp +155 -0
  135. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_types.cpp +6 -30
  136. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_values.cpp +15 -15
  137. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_wait.cpp +80 -5
  138. sharedbox-0.6.0/tests/cpp/test_write_in_place.cpp +83 -0
  139. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/crossproc.py +16 -1
  140. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/forged_open.py +30 -10
  141. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/forged_types.py +5 -4
  142. sharedbox-0.6.0/tests/os_names.py +8 -0
  143. sharedbox-0.6.0/tests/streamproc.py +179 -0
  144. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/stress/stress_helpers.py +3 -3
  145. sharedbox-0.6.0/tests/stress/test_stress_read_into.py +61 -0
  146. sharedbox-0.6.0/tests/test_benchbox_all.py +62 -0
  147. sharedbox-0.6.0/tests/test_benchbox_contention.py +15 -0
  148. sharedbox-0.6.0/tests/test_benchbox_plot.py +154 -0
  149. sharedbox-0.6.0/tests/test_benchbox_roundtrip.py +8 -0
  150. sharedbox-0.6.0/tests/test_benchbox_stream.py +149 -0
  151. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_box.py +39 -5
  152. sharedbox-0.6.0/tests/test_box_sync_async.py +62 -0
  153. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_capsule.py +12 -6
  154. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_doc_tutorials.py +11 -9
  155. sharedbox-0.6.0/tests/test_events_future.py +281 -0
  156. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_fields.py +2 -1
  157. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_fork.py +35 -9
  158. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_layout.py +2 -2
  159. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_native_segment.py +85 -50
  160. sharedbox-0.6.0/tests/test_native_stream.py +383 -0
  161. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_native_types.py +0 -20
  162. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_native_waiters.py +5 -4
  163. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_properties_stateful.py +12 -1
  164. sharedbox-0.6.0/tests/test_properties_stream.py +121 -0
  165. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_properties_types.py +5 -2
  166. sharedbox-0.6.0/tests/test_read_into.py +197 -0
  167. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_refs.py +49 -3
  168. sharedbox-0.6.0/tests/test_stream.py +627 -0
  169. sharedbox-0.6.0/tests/test_stream_async.py +480 -0
  170. sharedbox-0.6.0/tests/test_stream_events.py +488 -0
  171. sharedbox-0.6.0/tests/test_stream_fork.py +72 -0
  172. sharedbox-0.6.0/tests/test_stream_processes.py +268 -0
  173. sharedbox-0.6.0/tests/test_stream_writing.py +350 -0
  174. sharedbox-0.6.0/tests/test_types_arrays.py +569 -0
  175. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_types_arrays_bfloat16.py +21 -0
  176. sharedbox-0.6.0/tests/test_types_records_attrs.py +83 -0
  177. sharedbox-0.6.0/tests/test_types_records_msgspec.py +92 -0
  178. sharedbox-0.6.0/tests/test_value_reuse.py +446 -0
  179. sharedbox-0.6.0/tests/test_writing.py +171 -0
  180. sharedbox-0.6.0/tests/type_checks/array_types.py +20 -0
  181. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/type_checks/box_types.py +21 -1
  182. sharedbox-0.6.0/tests/type_checks/stream_types.py +58 -0
  183. {sharedbox-0.4.1 → sharedbox-0.6.0}/uv.lock +75 -547
  184. {sharedbox-0.4.1 → sharedbox-0.6.0}/zensical.toml +6 -2
  185. sharedbox-0.4.1/.claude/settings.json +0 -33
  186. sharedbox-0.4.1/PKG-INFO +0 -90
  187. sharedbox-0.4.1/README.md +0 -66
  188. sharedbox-0.4.1/docs/assets/benchmarks/ops-dark.svg +0 -1209
  189. sharedbox-0.4.1/docs/assets/benchmarks/ops-light.svg +0 -1209
  190. sharedbox-0.4.1/docs/assets/benchmarks/roundtrip-dark.svg +0 -334
  191. sharedbox-0.4.1/docs/assets/benchmarks/roundtrip-light.svg +0 -334
  192. sharedbox-0.4.1/docs/examples/change_several_fields_at_once.py +0 -44
  193. sharedbox-0.4.1/docs/examples/clean_up_segments.py +0 -38
  194. sharedbox-0.4.1/docs/examples/follow_a_whole_reference_graph.py +0 -46
  195. sharedbox-0.4.1/docs/examples/name_a_box.py +0 -45
  196. sharedbox-0.4.1/docs/examples/set_defaults_and_check_values.py +0 -79
  197. sharedbox-0.4.1/docs/examples/store_arrays.py +0 -40
  198. sharedbox-0.4.1/docs/examples/store_collections.py +0 -39
  199. sharedbox-0.4.1/docs/examples/store_records.py +0 -52
  200. sharedbox-0.4.1/docs/explanation/checking-a-process-is-alive.md +0 -63
  201. sharedbox-0.4.1/docs/explanation/closing-and-lifetime.md +0 -136
  202. sharedbox-0.4.1/docs/explanation/field-types.md +0 -91
  203. sharedbox-0.4.1/docs/explanation/glossary.md +0 -114
  204. sharedbox-0.4.1/docs/explanation/how-a-box-is-stored.md +0 -145
  205. sharedbox-0.4.1/docs/explanation/how-the-module-is-built.md +0 -68
  206. sharedbox-0.4.1/docs/explanation/index.md +0 -44
  207. sharedbox-0.4.1/docs/explanation/limits.md +0 -63
  208. sharedbox-0.4.1/docs/explanation/performance.md +0 -78
  209. sharedbox-0.4.1/docs/explanation/reading-and-writing.md +0 -121
  210. sharedbox-0.4.1/docs/explanation/references.md +0 -79
  211. sharedbox-0.4.1/docs/explanation/waiting-for-changes.md +0 -184
  212. sharedbox-0.4.1/docs/explanation/when-to-use-sharedbox.md +0 -41
  213. sharedbox-0.4.1/docs/how-to/accept-a-box-in-c.md +0 -83
  214. sharedbox-0.4.1/docs/how-to/accept-a-box-in-cpp.md +0 -174
  215. sharedbox-0.4.1/docs/how-to/change-several-fields-at-once.md +0 -59
  216. sharedbox-0.4.1/docs/how-to/clean-up-segments.md +0 -82
  217. sharedbox-0.4.1/docs/how-to/commits-and-prs.md +0 -68
  218. sharedbox-0.4.1/docs/how-to/follow-a-whole-reference-graph.md +0 -70
  219. sharedbox-0.4.1/docs/how-to/make-a-release.md +0 -87
  220. sharedbox-0.4.1/docs/how-to/name-a-box.md +0 -76
  221. sharedbox-0.4.1/docs/how-to/run-benchmarks.md +0 -99
  222. sharedbox-0.4.1/docs/how-to/send-a-box-to-another-process.md +0 -69
  223. sharedbox-0.4.1/docs/how-to/set-defaults-and-check-values.md +0 -75
  224. sharedbox-0.4.1/docs/how-to/store-arrays.md +0 -58
  225. sharedbox-0.4.1/docs/how-to/store-collections.md +0 -59
  226. sharedbox-0.4.1/docs/how-to/store-records.md +0 -68
  227. sharedbox-0.4.1/docs/how-to/store-text-and-bytes.md +0 -66
  228. sharedbox-0.4.1/docs/index.md +0 -63
  229. sharedbox-0.4.1/docs/reference/api/errors.md +0 -43
  230. sharedbox-0.4.1/docs/reference/cpp-and-c-api.md +0 -36
  231. sharedbox-0.4.1/docs/tutorials/motor.py +0 -102
  232. sharedbox-0.4.1/docs/tutorials/react-to-changes.md +0 -130
  233. sharedbox-0.4.1/docs/tutorials/refer-to-another-box.md +0 -92
  234. sharedbox-0.4.1/docs/tutorials/share-a-record.md +0 -115
  235. sharedbox-0.4.1/src/sharedbox/benchmarks/__init__.py +0 -5
  236. sharedbox-0.4.1/src/sharedbox/benchmarks/plot.py +0 -161
  237. sharedbox-0.4.1/stubtest-allowlist.txt +0 -14
  238. sharedbox-0.4.1/tests/cpp/test_layout2.cpp +0 -126
  239. sharedbox-0.4.1/tests/cpp/test_result.cpp +0 -121
  240. sharedbox-0.4.1/tests/cpp/test_slots.cpp +0 -157
  241. sharedbox-0.4.1/tests/test_benchbox_plot.py +0 -63
  242. sharedbox-0.4.1/tests/test_layout_v1.py +0 -50
  243. sharedbox-0.4.1/tests/test_types_arrays.py +0 -212
  244. sharedbox-0.4.1/tests/test_types_records_attrs.py +0 -21
  245. sharedbox-0.4.1/tests/test_types_records_msgspec.py +0 -35
  246. {sharedbox-0.4.1 → sharedbox-0.6.0}/.clang-format +0 -0
  247. {sharedbox-0.4.1 → sharedbox-0.6.0}/.github/workflows/check-docs.yaml +0 -0
  248. {sharedbox-0.4.1 → sharedbox-0.6.0}/.github/workflows/codspeed.yml +0 -0
  249. {sharedbox-0.4.1 → sharedbox-0.6.0}/.github/workflows/publish-docs.yaml +0 -0
  250. {sharedbox-0.4.1 → sharedbox-0.6.0}/LICENSE +0 -0
  251. /sharedbox-0.4.1/src/sharedbox/py.typed → /sharedbox-0.6.0/changelog.d/.gitkeep +0 -0
  252. {sharedbox-0.4.1 → sharedbox-0.6.0}/cmake/sharedbox-config.cmake +0 -0
  253. {sharedbox-0.4.1 → sharedbox-0.6.0}/cmake/sharedbox-require-cxx.cmake +0 -0
  254. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/how-to/ai-contribution-policy.md +0 -0
  255. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/reference/api/box.md +0 -0
  256. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/reference/api/library-authors.md +0 -0
  257. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/reference/api/references.md +0 -0
  258. {sharedbox-0.4.1 → sharedbox-0.6.0}/docs/reference/changelog.md +0 -0
  259. {sharedbox-0.4.1 → sharedbox-0.6.0}/includes/abbreviations.md +0 -0
  260. {sharedbox-0.4.1 → sharedbox-0.6.0}/prek.toml +0 -0
  261. {sharedbox-0.4.1 → sharedbox-0.6.0}/scripts/check_xrefs.py +0 -0
  262. {sharedbox-0.4.1 → sharedbox-0.6.0}/scripts/vscode_setup.py +0 -0
  263. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_follow.py +0 -0
  264. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native/codec.hpp +0 -0
  265. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native/scalars.cpp +0 -0
  266. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/_native/scalars.hpp +0 -0
  267. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/benchmarks/__main__.py +0 -0
  268. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/benchmarks/cli.py +0 -0
  269. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/benchmarks/size.py +0 -0
  270. {sharedbox-0.4.1 → sharedbox-0.6.0}/src/sharedbox/benchmarks/size_diff.py +0 -0
  271. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/consumer/CMakeLists.txt +0 -0
  272. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/consumer/consumer.c +0 -0
  273. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/table_builder.hpp +0 -0
  274. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_atomics.cpp +0 -0
  275. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_c_smoke.c +0 -0
  276. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_c_smoke_box.cpp +0 -0
  277. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_fork.cpp +0 -0
  278. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/test_windows_h.cpp +0 -0
  279. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/cpp/unique.hpp +0 -0
  280. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/refs_future.py +0 -0
  281. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/stress/test_stress_contention.py +0 -0
  282. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/stress/test_stress_crashes.py +0 -0
  283. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/stress/test_stress_follow.py +0 -0
  284. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/stress/test_stress_lock_timeout.py +0 -0
  285. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/stress/test_stress_memory.py +0 -0
  286. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/stress/test_stress_waiters.py +0 -0
  287. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/stress/test_stress_watchers.py +0 -0
  288. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_doc_examples.py +0 -0
  289. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_events_async.py +0 -0
  290. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_events_bytes.py +0 -0
  291. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_events_signals.py +0 -0
  292. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_events_sync.py +0 -0
  293. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_exit.py +0 -0
  294. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_follow.py +0 -0
  295. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_native_codec.py +0 -0
  296. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_native_liveness.py +0 -0
  297. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_native_wait.py +0 -0
  298. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_properties_codec.py +0 -0
  299. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_properties_forged.py +0 -0
  300. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_properties_layout.py +0 -0
  301. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_refs_lazy.py +0 -0
  302. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_types_arrays_torch.py +0 -0
  303. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_types_choices.py +0 -0
  304. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_types_collections.py +0 -0
  305. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_types_records.py +0 -0
  306. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_types_scalars.py +0 -0
  307. {sharedbox-0.4.1 → sharedbox-0.6.0}/tests/test_types_unions.py +0 -0
  308. {sharedbox-0.4.1 → 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,45 @@
1
+ name: Contention
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [ main ]
6
+ paths:
7
+ - include/sharedbox/**
8
+ - src/sharedbox/_native/**
9
+ - src/sharedbox/benchmarks/contention.py
10
+ - .github/workflows/contention.yaml
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ jobs:
17
+ contention:
18
+ name: Contention on ${{ matrix.os }}
19
+ runs-on: ${{ matrix.os }}
20
+ timeout-minutes: 30
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ os: [ ubuntu-latest, windows-latest ]
25
+ steps:
26
+ - uses: actions/checkout@v7
27
+ with:
28
+ fetch-depth: 0
29
+
30
+ - uses: astral-sh/setup-uv@v7
31
+
32
+ - name: Install the project
33
+ run: uv sync --frozen --python 3.12
34
+
35
+ - name: Run benchbox contention
36
+ shell: bash
37
+ run: |
38
+ cores=$(uv run --no-sync python -c "import os; print(os.cpu_count())")
39
+ echo "### Contention on ${{ matrix.os }}, $cores logical cores" >> "$GITHUB_STEP_SUMMARY"
40
+ uv run --no-sync benchbox contention --json contention.json --markdown >> "$GITHUB_STEP_SUMMARY"
41
+
42
+ - uses: actions/upload-artifact@v7
43
+ with:
44
+ name: contention-${{ matrix.os }}
45
+ path: contention.json
@@ -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,177 @@ 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
+
143
+
144
+ ## [0.5.0] - 09-10-2026
145
+
146
+ ### Added
147
+
148
+ - `SharedBox.read_into`: copies an array field into an array the caller
149
+ passes and returns it, without allocating a new array.
150
+ - `SharedBox.writing`: a context manager that holds the box's write lock
151
+ and yields an array field as an array to fill in place.
152
+ - `benchbox contention`: times writes and reads of an `int` while several
153
+ writer and reader processes share it, for a box, `mp.Value` and
154
+ `SharedMemory` with a `Lock`.
155
+
156
+ ### Changed
157
+
158
+ - `SharedBox`: a field named `read_into` raises `TypeError`.
159
+ - `SharedBox`: a field named `writing` raises `TypeError`.
160
+ - `SharedBox`: reading a collection, tuple or record field whose members
161
+ are `bool`, `int`, `float` or `str` takes less time: about 90 ns less
162
+ for a list of 16 `float` on Windows.
163
+ - `SharedBox`: reading a field whose value cannot be changed (a frozen
164
+ dataclass, attrs class or msgspec Struct, a NamedTuple, a tuple, a
165
+ frozenset, an enum, flag or literal, `complex`, `date`, `time`,
166
+ `datetime`, `timedelta`, `UUID` or `Decimal`) returns the value the
167
+ previous read built until the field is written: 40 ns instead of 540 ns
168
+ for a frozen dataclass of four fields on Windows. A tuple, frozenset or
169
+ record qualifies only when its members are of these kinds or `bool`,
170
+ `int`, `float`, `str` or `bytes`.
171
+ - `SharedBox`: a frozen record's `__post_init__`, attrs converters and
172
+ validators run on the first read after each write instead of on every
173
+ read.
174
+
175
+ ### Fixed
176
+
177
+ - `SharedBox.attach`: a box whose header gives a field count other than the
178
+ class's raises `SchemaMismatchError` instead of `ValueError`.
179
+
180
+ ## [0.4.1] - 07-10-2026
11
181
 
12
182
  ### Changed
13
183
 
@@ -292,7 +462,8 @@ stage.events.nested.connect(lambda path, new, old: print(path, new))
292
462
 
293
463
  - Initial release
294
464
 
295
- [Unreleased]: https://github.com/jacopoabramo/sharedbox/compare/v0.4.0...HEAD
465
+ [0.5.0]: https://github.com/jacopoabramo/sharedbox/compare/v0.4.1...v0.5.0
466
+ [0.4.1]: https://github.com/jacopoabramo/sharedbox/compare/v0.4.0...v0.4.1
296
467
  [0.4.0]: https://github.com/jacopoabramo/sharedbox/compare/v0.3.1...v0.4.0
297
468
  [0.3.1]: https://github.com/jacopoabramo/sharedbox/compare/v0.3.0...v0.3.1
298
469
  [0.3.0]: https://github.com/jacopoabramo/sharedbox/compare/0.2.4...v0.3.0