tigerbeetle 0.0.36 → 0.0.38

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 (248) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/ext/tb_client/extconf.rb +13 -13
  4. data/ext/tb_client/tigerbeetle/LICENSE +177 -0
  5. data/ext/tb_client/tigerbeetle/build.zig +2327 -0
  6. data/ext/tb_client/tigerbeetle/src/aof.zig +1000 -0
  7. data/ext/tb_client/tigerbeetle/src/build_multiversion.zig +808 -0
  8. data/ext/tb_client/tigerbeetle/src/cdc/amqp/protocol.zig +1283 -0
  9. data/ext/tb_client/tigerbeetle/src/cdc/amqp/spec.zig +1704 -0
  10. data/ext/tb_client/tigerbeetle/src/cdc/amqp/types.zig +341 -0
  11. data/ext/tb_client/tigerbeetle/src/cdc/amqp.zig +1450 -0
  12. data/ext/tb_client/tigerbeetle/src/cdc/runner.zig +1659 -0
  13. data/ext/tb_client/tigerbeetle/src/clients/c/samples/main.c +406 -0
  14. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/context.zig +1092 -0
  15. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/echo_client.zig +286 -0
  16. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/packet.zig +158 -0
  17. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal.zig +229 -0
  18. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client/signal_fuzz.zig +110 -0
  19. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.h +386 -0
  20. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client.zig +34 -0
  21. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_exports.zig +281 -0
  22. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header.zig +312 -0
  23. data/ext/tb_client/tigerbeetle/src/clients/c/tb_client_header_test.zig +138 -0
  24. data/ext/tb_client/tigerbeetle/src/clients/c/test.zig +466 -0
  25. data/ext/tb_client/tigerbeetle/src/clients/docs_samples.zig +157 -0
  26. data/ext/tb_client/tigerbeetle/src/clients/docs_types.zig +90 -0
  27. data/ext/tb_client/tigerbeetle/src/clients/dotnet/ci.zig +203 -0
  28. data/ext/tb_client/tigerbeetle/src/clients/dotnet/docs.zig +79 -0
  29. data/ext/tb_client/tigerbeetle/src/clients/dotnet/dotnet_bindings.zig +542 -0
  30. data/ext/tb_client/tigerbeetle/src/clients/go/ci.zig +109 -0
  31. data/ext/tb_client/tigerbeetle/src/clients/go/docs.zig +86 -0
  32. data/ext/tb_client/tigerbeetle/src/clients/go/go_bindings.zig +370 -0
  33. data/ext/tb_client/tigerbeetle/src/clients/go/pkg/native/tb_client.h +386 -0
  34. data/ext/tb_client/tigerbeetle/src/clients/java/ci.zig +167 -0
  35. data/ext/tb_client/tigerbeetle/src/clients/java/docs.zig +126 -0
  36. data/ext/tb_client/tigerbeetle/src/clients/java/java_bindings.zig +996 -0
  37. data/ext/tb_client/tigerbeetle/src/clients/java/src/client.zig +748 -0
  38. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni.zig +3238 -0
  39. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_tests.zig +1718 -0
  40. data/ext/tb_client/tigerbeetle/src/clients/java/src/jni_thread_cleaner.zig +190 -0
  41. data/ext/tb_client/tigerbeetle/src/clients/node/ci.zig +104 -0
  42. data/ext/tb_client/tigerbeetle/src/clients/node/docs.zig +75 -0
  43. data/ext/tb_client/tigerbeetle/src/clients/node/node.zig +522 -0
  44. data/ext/tb_client/tigerbeetle/src/clients/node/node_bindings.zig +267 -0
  45. data/ext/tb_client/tigerbeetle/src/clients/node/src/c.zig +3 -0
  46. data/ext/tb_client/tigerbeetle/src/clients/node/src/translate.zig +379 -0
  47. data/ext/tb_client/tigerbeetle/src/clients/python/ci.zig +131 -0
  48. data/ext/tb_client/tigerbeetle/src/clients/python/docs.zig +63 -0
  49. data/ext/tb_client/tigerbeetle/src/clients/python/python_bindings.zig +588 -0
  50. data/ext/tb_client/tigerbeetle/src/clients/rust/assets/tb_client.h +386 -0
  51. data/ext/tb_client/tigerbeetle/src/clients/rust/ci.zig +73 -0
  52. data/ext/tb_client/tigerbeetle/src/clients/rust/docs.zig +106 -0
  53. data/ext/tb_client/tigerbeetle/src/clients/rust/rust_bindings.zig +305 -0
  54. data/ext/tb_client/tigerbeetle/src/config.zig +296 -0
  55. data/ext/tb_client/tigerbeetle/src/constants.zig +790 -0
  56. data/ext/tb_client/tigerbeetle/src/copyhound.zig +202 -0
  57. data/ext/tb_client/tigerbeetle/src/counting_allocator.zig +72 -0
  58. data/ext/tb_client/tigerbeetle/src/direction.zig +120 -0
  59. data/ext/tb_client/tigerbeetle/src/docs_website/build.zig +158 -0
  60. data/ext/tb_client/tigerbeetle/src/docs_website/src/content.zig +156 -0
  61. data/ext/tb_client/tigerbeetle/src/docs_website/src/docs.zig +252 -0
  62. data/ext/tb_client/tigerbeetle/src/docs_website/src/file_checker.zig +313 -0
  63. data/ext/tb_client/tigerbeetle/src/docs_website/src/html.zig +87 -0
  64. data/ext/tb_client/tigerbeetle/src/docs_website/src/page_writer.zig +63 -0
  65. data/ext/tb_client/tigerbeetle/src/docs_website/src/redirects.zig +47 -0
  66. data/ext/tb_client/tigerbeetle/src/docs_website/src/search_index_writer.zig +28 -0
  67. data/ext/tb_client/tigerbeetle/src/docs_website/src/service_worker_writer.zig +61 -0
  68. data/ext/tb_client/tigerbeetle/src/docs_website/src/single_page_writer.zig +169 -0
  69. data/ext/tb_client/tigerbeetle/src/docs_website/src/website.zig +46 -0
  70. data/ext/tb_client/tigerbeetle/src/ewah.zig +445 -0
  71. data/ext/tb_client/tigerbeetle/src/ewah_benchmark.zig +128 -0
  72. data/ext/tb_client/tigerbeetle/src/ewah_fuzz.zig +171 -0
  73. data/ext/tb_client/tigerbeetle/src/fuzz_tests.zig +179 -0
  74. data/ext/tb_client/tigerbeetle/src/integration_tests.zig +662 -0
  75. data/ext/tb_client/tigerbeetle/src/io/common.zig +155 -0
  76. data/ext/tb_client/tigerbeetle/src/io/darwin.zig +1093 -0
  77. data/ext/tb_client/tigerbeetle/src/io/linux.zig +1880 -0
  78. data/ext/tb_client/tigerbeetle/src/io/test.zig +1005 -0
  79. data/ext/tb_client/tigerbeetle/src/io/windows.zig +1598 -0
  80. data/ext/tb_client/tigerbeetle/src/io.zig +34 -0
  81. data/ext/tb_client/tigerbeetle/src/iops.zig +134 -0
  82. data/ext/tb_client/tigerbeetle/src/list.zig +236 -0
  83. data/ext/tb_client/tigerbeetle/src/lsm/binary_search.zig +848 -0
  84. data/ext/tb_client/tigerbeetle/src/lsm/binary_search_benchmark.zig +179 -0
  85. data/ext/tb_client/tigerbeetle/src/lsm/cache_map.zig +424 -0
  86. data/ext/tb_client/tigerbeetle/src/lsm/cache_map_fuzz.zig +420 -0
  87. data/ext/tb_client/tigerbeetle/src/lsm/compaction.zig +2117 -0
  88. data/ext/tb_client/tigerbeetle/src/lsm/composite_key.zig +182 -0
  89. data/ext/tb_client/tigerbeetle/src/lsm/forest.zig +1119 -0
  90. data/ext/tb_client/tigerbeetle/src/lsm/forest_fuzz.zig +1102 -0
  91. data/ext/tb_client/tigerbeetle/src/lsm/forest_table_iterator.zig +200 -0
  92. data/ext/tb_client/tigerbeetle/src/lsm/groove.zig +1495 -0
  93. data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge.zig +739 -0
  94. data/ext/tb_client/tigerbeetle/src/lsm/k_way_merge_benchmark.zig +166 -0
  95. data/ext/tb_client/tigerbeetle/src/lsm/manifest.zig +754 -0
  96. data/ext/tb_client/tigerbeetle/src/lsm/manifest_level.zig +1294 -0
  97. data/ext/tb_client/tigerbeetle/src/lsm/manifest_level_fuzz.zig +510 -0
  98. data/ext/tb_client/tigerbeetle/src/lsm/manifest_log.zig +1263 -0
  99. data/ext/tb_client/tigerbeetle/src/lsm/manifest_log_fuzz.zig +628 -0
  100. data/ext/tb_client/tigerbeetle/src/lsm/node_pool.zig +247 -0
  101. data/ext/tb_client/tigerbeetle/src/lsm/scan_buffer.zig +116 -0
  102. data/ext/tb_client/tigerbeetle/src/lsm/scan_builder.zig +543 -0
  103. data/ext/tb_client/tigerbeetle/src/lsm/scan_fuzz.zig +938 -0
  104. data/ext/tb_client/tigerbeetle/src/lsm/scan_lookup.zig +293 -0
  105. data/ext/tb_client/tigerbeetle/src/lsm/scan_merge.zig +359 -0
  106. data/ext/tb_client/tigerbeetle/src/lsm/scan_range.zig +99 -0
  107. data/ext/tb_client/tigerbeetle/src/lsm/scan_state.zig +17 -0
  108. data/ext/tb_client/tigerbeetle/src/lsm/scan_tree.zig +962 -0
  109. data/ext/tb_client/tigerbeetle/src/lsm/schema.zig +617 -0
  110. data/ext/tb_client/tigerbeetle/src/lsm/scratch_memory.zig +84 -0
  111. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array.zig +1500 -0
  112. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_benchmark.zig +149 -0
  113. data/ext/tb_client/tigerbeetle/src/lsm/segmented_array_fuzz.zig +7 -0
  114. data/ext/tb_client/tigerbeetle/src/lsm/set_associative_cache.zig +865 -0
  115. data/ext/tb_client/tigerbeetle/src/lsm/table.zig +607 -0
  116. data/ext/tb_client/tigerbeetle/src/lsm/table_memory.zig +843 -0
  117. data/ext/tb_client/tigerbeetle/src/lsm/table_value_iterator.zig +90 -0
  118. data/ext/tb_client/tigerbeetle/src/lsm/timestamp_range.zig +40 -0
  119. data/ext/tb_client/tigerbeetle/src/lsm/tree.zig +630 -0
  120. data/ext/tb_client/tigerbeetle/src/lsm/tree_fuzz.zig +933 -0
  121. data/ext/tb_client/tigerbeetle/src/lsm/zig_zag_merge.zig +534 -0
  122. data/ext/tb_client/tigerbeetle/src/message_buffer.zig +469 -0
  123. data/ext/tb_client/tigerbeetle/src/message_bus.zig +1214 -0
  124. data/ext/tb_client/tigerbeetle/src/message_bus_fuzz.zig +936 -0
  125. data/ext/tb_client/tigerbeetle/src/message_pool.zig +343 -0
  126. data/ext/tb_client/tigerbeetle/src/multiversion.zig +2195 -0
  127. data/ext/tb_client/tigerbeetle/src/queue.zig +390 -0
  128. data/ext/tb_client/tigerbeetle/src/repl/completion.zig +201 -0
  129. data/ext/tb_client/tigerbeetle/src/repl/parser.zig +1356 -0
  130. data/ext/tb_client/tigerbeetle/src/repl/terminal.zig +496 -0
  131. data/ext/tb_client/tigerbeetle/src/repl.zig +1034 -0
  132. data/ext/tb_client/tigerbeetle/src/scripts/amqp.zig +973 -0
  133. data/ext/tb_client/tigerbeetle/src/scripts/cfo.zig +1866 -0
  134. data/ext/tb_client/tigerbeetle/src/scripts/changelog.zig +304 -0
  135. data/ext/tb_client/tigerbeetle/src/scripts/ci.zig +227 -0
  136. data/ext/tb_client/tigerbeetle/src/scripts/client_readmes.zig +658 -0
  137. data/ext/tb_client/tigerbeetle/src/scripts/devhub.zig +466 -0
  138. data/ext/tb_client/tigerbeetle/src/scripts/release.zig +1058 -0
  139. data/ext/tb_client/tigerbeetle/src/scripts.zig +105 -0
  140. data/ext/tb_client/tigerbeetle/src/shell.zig +1195 -0
  141. data/ext/tb_client/tigerbeetle/src/stack.zig +260 -0
  142. data/ext/tb_client/tigerbeetle/src/state_machine/auditor.zig +911 -0
  143. data/ext/tb_client/tigerbeetle/src/state_machine/workload.zig +2079 -0
  144. data/ext/tb_client/tigerbeetle/src/state_machine.zig +4872 -0
  145. data/ext/tb_client/tigerbeetle/src/state_machine_fuzz.zig +288 -0
  146. data/ext/tb_client/tigerbeetle/src/state_machine_tests.zig +3128 -0
  147. data/ext/tb_client/tigerbeetle/src/static_allocator.zig +82 -0
  148. data/ext/tb_client/tigerbeetle/src/stdx/bit_set.zig +157 -0
  149. data/ext/tb_client/tigerbeetle/src/stdx/bounded_array.zig +292 -0
  150. data/ext/tb_client/tigerbeetle/src/stdx/debug.zig +65 -0
  151. data/ext/tb_client/tigerbeetle/src/stdx/flags.zig +1414 -0
  152. data/ext/tb_client/tigerbeetle/src/stdx/mlock.zig +92 -0
  153. data/ext/tb_client/tigerbeetle/src/stdx/prng.zig +677 -0
  154. data/ext/tb_client/tigerbeetle/src/stdx/radix.zig +336 -0
  155. data/ext/tb_client/tigerbeetle/src/stdx/ring_buffer.zig +511 -0
  156. data/ext/tb_client/tigerbeetle/src/stdx/sort_test.zig +112 -0
  157. data/ext/tb_client/tigerbeetle/src/stdx/stdx.zig +1160 -0
  158. data/ext/tb_client/tigerbeetle/src/stdx/testing/low_level_hash_vectors.zig +142 -0
  159. data/ext/tb_client/tigerbeetle/src/stdx/testing/snaptest.zig +361 -0
  160. data/ext/tb_client/tigerbeetle/src/stdx/time_units.zig +275 -0
  161. data/ext/tb_client/tigerbeetle/src/stdx/unshare.zig +295 -0
  162. data/ext/tb_client/tigerbeetle/src/stdx/vendored/aegis.zig +436 -0
  163. data/ext/tb_client/tigerbeetle/src/stdx/windows.zig +48 -0
  164. data/ext/tb_client/tigerbeetle/src/stdx/zipfian.zig +402 -0
  165. data/ext/tb_client/tigerbeetle/src/storage.zig +489 -0
  166. data/ext/tb_client/tigerbeetle/src/storage_fuzz.zig +180 -0
  167. data/ext/tb_client/tigerbeetle/src/testing/bench.zig +146 -0
  168. data/ext/tb_client/tigerbeetle/src/testing/cluster/grid_checker.zig +53 -0
  169. data/ext/tb_client/tigerbeetle/src/testing/cluster/journal_checker.zig +61 -0
  170. data/ext/tb_client/tigerbeetle/src/testing/cluster/manifest_checker.zig +76 -0
  171. data/ext/tb_client/tigerbeetle/src/testing/cluster/message_bus.zig +110 -0
  172. data/ext/tb_client/tigerbeetle/src/testing/cluster/network.zig +412 -0
  173. data/ext/tb_client/tigerbeetle/src/testing/cluster/state_checker.zig +331 -0
  174. data/ext/tb_client/tigerbeetle/src/testing/cluster/storage_checker.zig +458 -0
  175. data/ext/tb_client/tigerbeetle/src/testing/cluster.zig +1198 -0
  176. data/ext/tb_client/tigerbeetle/src/testing/exhaustigen.zig +128 -0
  177. data/ext/tb_client/tigerbeetle/src/testing/fixtures.zig +181 -0
  178. data/ext/tb_client/tigerbeetle/src/testing/fuzz.zig +144 -0
  179. data/ext/tb_client/tigerbeetle/src/testing/id.zig +97 -0
  180. data/ext/tb_client/tigerbeetle/src/testing/io.zig +317 -0
  181. data/ext/tb_client/tigerbeetle/src/testing/marks.zig +126 -0
  182. data/ext/tb_client/tigerbeetle/src/testing/packet_simulator.zig +533 -0
  183. data/ext/tb_client/tigerbeetle/src/testing/reply_sequence.zig +154 -0
  184. data/ext/tb_client/tigerbeetle/src/testing/state_machine.zig +389 -0
  185. data/ext/tb_client/tigerbeetle/src/testing/storage.zig +1247 -0
  186. data/ext/tb_client/tigerbeetle/src/testing/table.zig +249 -0
  187. data/ext/tb_client/tigerbeetle/src/testing/time.zig +98 -0
  188. data/ext/tb_client/tigerbeetle/src/testing/tmp_tigerbeetle.zig +212 -0
  189. data/ext/tb_client/tigerbeetle/src/testing/vortex/constants.zig +26 -0
  190. data/ext/tb_client/tigerbeetle/src/testing/vortex/faulty_network.zig +580 -0
  191. data/ext/tb_client/tigerbeetle/src/testing/vortex/java_driver/ci.zig +39 -0
  192. data/ext/tb_client/tigerbeetle/src/testing/vortex/logged_process.zig +214 -0
  193. data/ext/tb_client/tigerbeetle/src/testing/vortex/rust_driver/ci.zig +34 -0
  194. data/ext/tb_client/tigerbeetle/src/testing/vortex/supervisor.zig +766 -0
  195. data/ext/tb_client/tigerbeetle/src/testing/vortex/workload.zig +543 -0
  196. data/ext/tb_client/tigerbeetle/src/testing/vortex/zig_driver.zig +181 -0
  197. data/ext/tb_client/tigerbeetle/src/tidy.zig +1448 -0
  198. data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_driver.zig +227 -0
  199. data/ext/tb_client/tigerbeetle/src/tigerbeetle/benchmark_load.zig +1069 -0
  200. data/ext/tb_client/tigerbeetle/src/tigerbeetle/cli.zig +1422 -0
  201. data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect.zig +1658 -0
  202. data/ext/tb_client/tigerbeetle/src/tigerbeetle/inspect_integrity.zig +518 -0
  203. data/ext/tb_client/tigerbeetle/src/tigerbeetle/libtb_client.zig +36 -0
  204. data/ext/tb_client/tigerbeetle/src/tigerbeetle/main.zig +646 -0
  205. data/ext/tb_client/tigerbeetle/src/tigerbeetle.zig +958 -0
  206. data/ext/tb_client/tigerbeetle/src/time.zig +236 -0
  207. data/ext/tb_client/tigerbeetle/src/trace/event.zig +745 -0
  208. data/ext/tb_client/tigerbeetle/src/trace/statsd.zig +462 -0
  209. data/ext/tb_client/tigerbeetle/src/trace.zig +556 -0
  210. data/ext/tb_client/tigerbeetle/src/unit_tests.zig +321 -0
  211. data/ext/tb_client/tigerbeetle/src/vopr.zig +1785 -0
  212. data/ext/tb_client/tigerbeetle/src/vortex.zig +101 -0
  213. data/ext/tb_client/tigerbeetle/src/vsr/checkpoint_trailer.zig +473 -0
  214. data/ext/tb_client/tigerbeetle/src/vsr/checksum.zig +208 -0
  215. data/ext/tb_client/tigerbeetle/src/vsr/checksum_benchmark.zig +43 -0
  216. data/ext/tb_client/tigerbeetle/src/vsr/client.zig +768 -0
  217. data/ext/tb_client/tigerbeetle/src/vsr/client_replies.zig +532 -0
  218. data/ext/tb_client/tigerbeetle/src/vsr/client_sessions.zig +338 -0
  219. data/ext/tb_client/tigerbeetle/src/vsr/clock.zig +1019 -0
  220. data/ext/tb_client/tigerbeetle/src/vsr/fault_detector.zig +279 -0
  221. data/ext/tb_client/tigerbeetle/src/vsr/free_set.zig +1381 -0
  222. data/ext/tb_client/tigerbeetle/src/vsr/free_set_fuzz.zig +315 -0
  223. data/ext/tb_client/tigerbeetle/src/vsr/grid.zig +1460 -0
  224. data/ext/tb_client/tigerbeetle/src/vsr/grid_blocks_missing.zig +757 -0
  225. data/ext/tb_client/tigerbeetle/src/vsr/grid_scrubber.zig +797 -0
  226. data/ext/tb_client/tigerbeetle/src/vsr/journal.zig +2586 -0
  227. data/ext/tb_client/tigerbeetle/src/vsr/marzullo.zig +308 -0
  228. data/ext/tb_client/tigerbeetle/src/vsr/message_header.zig +1777 -0
  229. data/ext/tb_client/tigerbeetle/src/vsr/multi_batch.zig +715 -0
  230. data/ext/tb_client/tigerbeetle/src/vsr/multi_batch_fuzz.zig +185 -0
  231. data/ext/tb_client/tigerbeetle/src/vsr/repair_budget.zig +333 -0
  232. data/ext/tb_client/tigerbeetle/src/vsr/replica.zig +12355 -0
  233. data/ext/tb_client/tigerbeetle/src/vsr/replica_format.zig +416 -0
  234. data/ext/tb_client/tigerbeetle/src/vsr/replica_reformat.zig +165 -0
  235. data/ext/tb_client/tigerbeetle/src/vsr/replica_test.zig +2928 -0
  236. data/ext/tb_client/tigerbeetle/src/vsr/routing.zig +1075 -0
  237. data/ext/tb_client/tigerbeetle/src/vsr/superblock.zig +1603 -0
  238. data/ext/tb_client/tigerbeetle/src/vsr/superblock_fuzz.zig +484 -0
  239. data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums.zig +405 -0
  240. data/ext/tb_client/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +355 -0
  241. data/ext/tb_client/tigerbeetle/src/vsr/sync.zig +29 -0
  242. data/ext/tb_client/tigerbeetle/src/vsr.zig +1727 -0
  243. data/lib/tb_client/shared_lib.rb +12 -5
  244. data/lib/tigerbeetle/platforms.rb +9 -0
  245. data/lib/tigerbeetle/version.rb +2 -2
  246. data/tigerbeetle.gemspec +22 -5
  247. metadata +242 -3
  248. data/ext/tb_client/pkg.tar.gz +0 -0
@@ -0,0 +1,82 @@
1
+ //! An allocator wrapper which can be disabled at runtime.
2
+ //! We use this for allocating at startup and then
3
+ //! disable it to prevent accidental dynamic allocation at runtime.
4
+
5
+ const std = @import("std");
6
+ const assert = std.debug.assert;
7
+ const mem = std.mem;
8
+ const Alignment = mem.Alignment;
9
+
10
+ const StaticAllocator = @This();
11
+ parent_allocator: mem.Allocator,
12
+ state: State,
13
+
14
+ const State = enum {
15
+ /// Allow `alloc` and `resize`.
16
+ /// (To make errdefer cleanup easier to write we also allow calling `free`,
17
+ /// in which case we switch state to `.deinit` and no longer allow `alloc` or `resize`.)
18
+ init,
19
+ /// Don't allow any calls.
20
+ static,
21
+ /// Allow `free` but not `alloc` and `resize`.
22
+ deinit,
23
+ };
24
+
25
+ pub fn init(parent_allocator: mem.Allocator) StaticAllocator {
26
+ return .{
27
+ .parent_allocator = parent_allocator,
28
+ .state = .init,
29
+ };
30
+ }
31
+
32
+ pub fn deinit(self: *StaticAllocator) void {
33
+ self.* = undefined;
34
+ }
35
+
36
+ pub fn transition_from_init_to_static(self: *StaticAllocator) void {
37
+ assert(self.state == .init);
38
+ self.state = .static;
39
+ }
40
+
41
+ pub fn transition_from_static_to_deinit(self: *StaticAllocator) void {
42
+ assert(self.state == .static);
43
+ self.state = .deinit;
44
+ }
45
+
46
+ pub fn allocator(self: *StaticAllocator) mem.Allocator {
47
+ return .{
48
+ .ptr = self,
49
+ .vtable = &.{
50
+ .alloc = alloc,
51
+ .resize = resize,
52
+ .remap = remap,
53
+ .free = free,
54
+ },
55
+ };
56
+ }
57
+
58
+ fn alloc(ctx: *anyopaque, len: usize, ptr_align: Alignment, ret_addr: usize) ?[*]u8 {
59
+ const self: *StaticAllocator = @ptrCast(@alignCast(ctx));
60
+ assert(self.state == .init);
61
+ return self.parent_allocator.rawAlloc(len, ptr_align, ret_addr);
62
+ }
63
+
64
+ fn resize(ctx: *anyopaque, buf: []u8, buf_align: Alignment, new_len: usize, ret_addr: usize) bool {
65
+ const self: *StaticAllocator = @ptrCast(@alignCast(ctx));
66
+ assert(self.state == .init);
67
+ return self.parent_allocator.rawResize(buf, buf_align, new_len, ret_addr);
68
+ }
69
+
70
+ fn remap(ctx: *anyopaque, buf: []u8, buf_align: Alignment, new_len: usize, ret_addr: usize) ?[*]u8 {
71
+ const self: *StaticAllocator = @ptrCast(@alignCast(ctx));
72
+ assert(self.state == .init);
73
+ return self.parent_allocator.rawRemap(buf, buf_align, new_len, ret_addr);
74
+ }
75
+
76
+ fn free(ctx: *anyopaque, buf: []u8, buf_align: Alignment, ret_addr: usize) void {
77
+ const self: *StaticAllocator = @ptrCast(@alignCast(ctx));
78
+ assert(self.state == .init or self.state == .deinit);
79
+ // Once you start freeing, you don't stop.
80
+ self.state = .deinit;
81
+ return self.parent_allocator.rawFree(buf, buf_align, ret_addr);
82
+ }
@@ -0,0 +1,157 @@
1
+ const stdx = @import("stdx.zig");
2
+ const std = @import("std");
3
+ const assert = std.debug.assert;
4
+
5
+ /// Use a dynamic bitset for larger sizes.
6
+ pub fn BitSetType(comptime with_capacity: u9) type {
7
+ assert(with_capacity <= 256);
8
+
9
+ return struct {
10
+ // While mathematically 0 and 1 are symmetric, we intentionally bias the API to use zeros
11
+ // default, as zero-initialization reduces binary size.
12
+ bits: Word = 0,
13
+
14
+ pub const Word = for (.{ u8, u16, u32, u64, u128, u256 }) |w| {
15
+ if (@bitSizeOf(w) >= with_capacity) break w;
16
+ } else unreachable;
17
+
18
+ const BitSet = @This();
19
+
20
+ pub fn is_set(bit_set: BitSet, index: usize) bool {
21
+ assert(index < bit_set.capacity());
22
+ return bit_set.bits & bit(index) != 0;
23
+ }
24
+
25
+ pub fn count(bit_set: BitSet) usize {
26
+ return @popCount(bit_set.bits);
27
+ }
28
+
29
+ pub inline fn capacity(_: BitSet) usize {
30
+ return with_capacity;
31
+ }
32
+
33
+ pub fn full(bit_set: BitSet) bool {
34
+ return bit_set.count() == bit_set.capacity();
35
+ }
36
+
37
+ pub fn empty(bit_set: BitSet) bool {
38
+ return bit_set.bits == 0;
39
+ }
40
+
41
+ pub fn first_set(bit_set: BitSet) ?usize {
42
+ if (bit_set.bits == 0) return null;
43
+ return @ctz(bit_set.bits);
44
+ }
45
+
46
+ pub fn first_unset(bit_set: BitSet) ?usize {
47
+ const result = @ctz(~bit_set.bits);
48
+ return if (result < bit_set.capacity()) result else null;
49
+ }
50
+
51
+ pub fn set(bit_set: *BitSet, index: usize) void {
52
+ assert(index < bit_set.capacity());
53
+ bit_set.bits |= bit(index);
54
+ }
55
+
56
+ pub fn unset(bit_set: *BitSet, index: usize) void {
57
+ assert(index < bit_set.capacity());
58
+ bit_set.bits &= ~bit(index);
59
+ }
60
+
61
+ pub fn set_value(bit_set: *BitSet, index: usize, value: bool) void {
62
+ if (value) {
63
+ bit_set.set(index);
64
+ } else {
65
+ bit_set.unset(index);
66
+ }
67
+ }
68
+
69
+ fn bit(index: usize) Word {
70
+ assert(index < with_capacity);
71
+ return @as(Word, 1) << @intCast(index);
72
+ }
73
+
74
+ pub fn iterate(bit_set: BitSet) Iterator {
75
+ return .{ .bits_remain = bit_set.bits };
76
+ }
77
+
78
+ pub const Iterator = struct {
79
+ bits_remain: Word,
80
+
81
+ pub fn next(it: *@This()) ?usize {
82
+ const result = @ctz(it.bits_remain);
83
+ if (result >= with_capacity) return null;
84
+ it.bits_remain &= it.bits_remain - 1;
85
+ return result;
86
+ }
87
+ };
88
+ };
89
+ }
90
+
91
+ test BitSetType {
92
+ var prng = stdx.PRNG.from_seed_testing();
93
+ inline for (.{ 0, 1, 8, 32, 65, 255, 256 }) |N| {
94
+ const BitSet = BitSetType(N);
95
+
96
+ var set: BitSet = .{};
97
+ var model = try std.DynamicBitSetUnmanaged.initEmpty(std.testing.allocator, N);
98
+ defer model.deinit(std.testing.allocator);
99
+
100
+ for (0..1000) |_| {
101
+ switch (prng.enum_uniform(std.meta.DeclEnum(BitSet))) {
102
+ .Word => {
103
+ const bit_size =
104
+ comptime if (N == 0) 8 else @max(8, try std.math.ceilPowerOfTwo(u16, N));
105
+ assert(BitSet.Word == std.meta.Int(.unsigned, bit_size));
106
+ },
107
+ .Iterator => {},
108
+ .is_set => {
109
+ if (N > 0) {
110
+ const bit = prng.int_inclusive(usize, N - 1);
111
+ assert(set.is_set(bit) == model.isSet(bit));
112
+ }
113
+ },
114
+ .count => assert(set.count() == model.count()),
115
+ .capacity => assert(set.capacity() == N),
116
+ .full => assert(set.full() == (model.count() == N)),
117
+ .empty => assert(set.empty() == (model.count() == 0)),
118
+ .first_set => assert(set.first_set() == model.findFirstSet()),
119
+ .first_unset => {
120
+ var it = model.iterator(.{ .kind = .unset });
121
+ assert(set.first_unset() == it.next());
122
+ },
123
+ .set => {
124
+ if (N > 0) {
125
+ const bit = prng.int_inclusive(usize, N - 1);
126
+ set.set(bit);
127
+ model.set(bit);
128
+ }
129
+ },
130
+ .unset => {
131
+ if (N > 0) {
132
+ const bit = prng.int_inclusive(usize, N - 1);
133
+ set.unset(bit);
134
+ model.unset(bit);
135
+ }
136
+ },
137
+ .set_value => {
138
+ if (N > 0) {
139
+ const bit = prng.int_inclusive(usize, N - 1);
140
+ const value = prng.boolean();
141
+ set.set_value(bit, value);
142
+ model.setValue(bit, value);
143
+ }
144
+ },
145
+ .iterate => {
146
+ var it_set = set.iterate();
147
+ var it_model = model.iterator(.{});
148
+ while (it_model.next()) |next| {
149
+ assert(next == it_set.next());
150
+ }
151
+ assert(it_set.next() == null);
152
+ assert(it_set.next() == null);
153
+ },
154
+ }
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,292 @@
1
+ const std = @import("std");
2
+ const stdx = @import("stdx.zig");
3
+ const assert = std.debug.assert;
4
+
5
+ /// A version of standard `BoundedArray` with TigerBeetle-idiomatic APIs.
6
+ pub fn BoundedArrayType(comptime T: type, comptime buffer_capacity: usize) type {
7
+ return struct {
8
+ buffer: [buffer_capacity]T = undefined,
9
+ // Its not clear whether the best type of count is u32, usize, or u`log(buffer_capacity)`.
10
+ // Use an ugly internal name here and expose `pub fn count` as an API.
11
+ count_u32: u32 = 0,
12
+
13
+ const BoundedArray = @This();
14
+
15
+ pub inline fn from_slice(items: []const T) error{Overflow}!BoundedArray {
16
+ if (items.len <= buffer_capacity) {
17
+ var result: BoundedArray = .{};
18
+ result.push_slice(items);
19
+ return result;
20
+ } else {
21
+ return error.Overflow;
22
+ }
23
+ }
24
+
25
+ pub inline fn count(array: *const BoundedArray) usize {
26
+ return array.count_u32;
27
+ }
28
+
29
+ /// Returns count of elements in this BoundedArray in the specified integer types,
30
+ /// checking at compile time that it indeed can represent the length.
31
+ pub inline fn count_as(array: *const BoundedArray, comptime Int: type) Int {
32
+ comptime assert(buffer_capacity <= std.math.maxInt(Int));
33
+ return @intCast(array.count_u32);
34
+ }
35
+
36
+ pub inline fn full(array: BoundedArray) bool {
37
+ return array.count_u32 == buffer_capacity;
38
+ }
39
+
40
+ pub inline fn empty(array: BoundedArray) bool {
41
+ return array.count_u32 == 0;
42
+ }
43
+
44
+ pub inline fn get(array: *const BoundedArray, index: usize) T {
45
+ assert(index < array.count_u32);
46
+ return array.buffer[index];
47
+ }
48
+
49
+ pub inline fn slice(array: *BoundedArray) []T {
50
+ return array.buffer[0..array.count_u32];
51
+ }
52
+
53
+ pub inline fn const_slice(array: *const BoundedArray) []const T {
54
+ return array.buffer[0..array.count_u32];
55
+ }
56
+
57
+ pub inline fn unused_capacity_slice(array: *BoundedArray) []T {
58
+ return array.buffer[array.count_u32..];
59
+ }
60
+
61
+ pub fn insert_at(array: *BoundedArray, index: usize, item: T) void {
62
+ assert(!array.full());
63
+ assert(index <= array.count_u32);
64
+ stdx.copy_right(
65
+ .exact,
66
+ T,
67
+ array.buffer[index + 1 .. array.count_u32 + 1],
68
+ array.buffer[index..array.count_u32],
69
+ );
70
+ array.buffer[index] = item;
71
+ array.count_u32 += 1;
72
+ }
73
+
74
+ pub fn push(array: *BoundedArray, item: T) void {
75
+ assert(!array.full());
76
+ array.buffer[array.count_u32] = item;
77
+ array.count_u32 += 1;
78
+ }
79
+
80
+ pub fn push_slice(array: *BoundedArray, items: []const T) void {
81
+ assert(array.count_u32 + items.len <= array.capacity());
82
+ stdx.copy_disjoint(.inexact, T, array.buffer[array.count_u32..], items);
83
+ array.count_u32 += @intCast(items.len);
84
+ }
85
+
86
+ pub inline fn swap_remove(array: *BoundedArray, index: usize) T {
87
+ assert(array.count_u32 > 0);
88
+ assert(index < array.count_u32);
89
+ const result = array.buffer[index];
90
+ array.count_u32 -= 1;
91
+ array.buffer[index] = array.buffer[array.count_u32];
92
+ return result;
93
+ }
94
+
95
+ pub inline fn ordered_remove(array: *BoundedArray, index: usize) T {
96
+ assert(array.count_u32 > 0);
97
+ assert(index < array.count_u32);
98
+ const result = array.buffer[index];
99
+ stdx.copy_left(
100
+ .exact,
101
+ T,
102
+ array.buffer[index .. array.count_u32 - 1],
103
+ array.buffer[index + 1 .. array.count_u32],
104
+ );
105
+ array.count_u32 -= 1;
106
+ return result;
107
+ }
108
+
109
+ pub fn resize(array: *BoundedArray, count_new: usize) error{Overflow}!void {
110
+ if (count_new <= buffer_capacity) {
111
+ array.count_u32 = @intCast(count_new);
112
+ } else {
113
+ return error.Overflow;
114
+ }
115
+ }
116
+
117
+ pub inline fn truncate(array: *BoundedArray, count_new: usize) void {
118
+ assert(count_new <= array.count_u32);
119
+ array.count_u32 = @intCast(count_new); // can't overflow due to check above.
120
+ }
121
+
122
+ pub inline fn clear(array: *BoundedArray) void {
123
+ array.count_u32 = 0;
124
+ }
125
+
126
+ pub inline fn pop(array: *BoundedArray) ?T {
127
+ if (array.count_u32 == 0) return null;
128
+ array.count_u32 -= 1;
129
+ return array.buffer[array.count_u32];
130
+ }
131
+
132
+ pub inline fn capacity(_: *BoundedArray) usize {
133
+ return buffer_capacity;
134
+ }
135
+ };
136
+ }
137
+
138
+ test BoundedArrayType {
139
+ const capacity = 8;
140
+ const Array = BoundedArrayType(u8, capacity);
141
+ const Model = std.ArrayListUnmanaged(u8);
142
+ const swarm_count = 10;
143
+ const action_count = 1_000;
144
+
145
+ const gpa = std.testing.allocator;
146
+
147
+ var array: Array = .{};
148
+ var model: Model = try .initCapacity(gpa, capacity);
149
+ defer model.deinit(gpa);
150
+
151
+ var prng = stdx.PRNG.from_seed_testing();
152
+
153
+ for (0..swarm_count) |_| {
154
+ const swarm_weights = prng.enum_weights(std.meta.DeclEnum(Array));
155
+ for (0..action_count) |_| {
156
+ const action = prng.enum_weighted(std.meta.DeclEnum(Array), swarm_weights);
157
+ switch (action) {
158
+ .count => assert(array.count() == model.items.len),
159
+ .count_as => assert(array.count_as(u8) == model.items.len),
160
+ .full => assert(array.full() == (model.unusedCapacitySlice().len == 0)),
161
+ .empty => assert(array.empty() == (model.items.len == 0)),
162
+ .get => {
163
+ if (model.items.len > 0) {
164
+ const index = prng.index(model.items);
165
+ assert(array.get(index) == model.items[index]);
166
+ }
167
+ },
168
+ .slice => assert(std.mem.eql(u8, array.slice(), model.items)),
169
+ .const_slice => assert(std.mem.eql(u8, array.const_slice(), model.items)),
170
+ .unused_capacity_slice => {
171
+ assert(array.unused_capacity_slice().len == model.unusedCapacitySlice().len);
172
+ },
173
+ .insert_at => {
174
+ if (model.items.len < model.capacity) {
175
+ const index = prng.int_inclusive(usize, model.items.len);
176
+ const value = prng.int(u8);
177
+
178
+ array.insert_at(index, value);
179
+ model.insertAssumeCapacity(index, value);
180
+ }
181
+ },
182
+ .push => {
183
+ if (model.items.len < model.capacity) {
184
+ const value = prng.int(u8);
185
+
186
+ array.push(value);
187
+ model.appendAssumeCapacity(value);
188
+ }
189
+ },
190
+ .push_slice => {
191
+ var buffer: [capacity]u8 = undefined;
192
+ const count = prng.int_inclusive(usize, model.capacity - model.items.len);
193
+ for (0..count) |index| buffer[index] = prng.int(u8);
194
+ const slice = buffer[0..count];
195
+
196
+ array.push_slice(slice);
197
+ model.appendSliceAssumeCapacity(slice);
198
+ },
199
+ .swap_remove => {
200
+ if (model.items.len > 0) {
201
+ const index = prng.index(model.items);
202
+
203
+ const a = array.swap_remove(index);
204
+ const b = model.swapRemove(index);
205
+ assert(a == b);
206
+ }
207
+ },
208
+ .ordered_remove => {
209
+ if (model.items.len > 0) {
210
+ const index = prng.index(model.items);
211
+
212
+ const a = array.ordered_remove(index);
213
+ const b = model.orderedRemove(index);
214
+ assert(a == b);
215
+ }
216
+ },
217
+ .resize => {
218
+ const count_old = model.items.len;
219
+ const count_new = prng.int_inclusive(usize, capacity);
220
+
221
+ model.resize(gpa, count_new) catch unreachable;
222
+ array.resize(count_new) catch unreachable;
223
+ if (count_old <= count_new) {
224
+ for (count_old..count_new) |index| {
225
+ const value = prng.int(u8);
226
+ model.items[index] = value;
227
+ array.buffer[index] = value;
228
+ }
229
+ }
230
+ },
231
+ .truncate => {
232
+ const count_new = prng.int_inclusive(usize, model.items.len);
233
+ array.truncate(count_new);
234
+ model.resize(gpa, count_new) catch unreachable;
235
+ },
236
+ .clear => {
237
+ array.clear();
238
+ model.clearRetainingCapacity();
239
+ },
240
+ .pop => {
241
+ const b = model.pop();
242
+ const a = array.pop();
243
+ assert((a == null and b == null) or (a.? == b.?));
244
+ },
245
+ .capacity => assert(array.capacity() == model.capacity),
246
+ .from_slice => {
247
+ var buffer: [capacity]u8 = undefined;
248
+ const count = prng.int_inclusive(usize, model.capacity - model.items.len);
249
+ for (0..count) |index| buffer[index] = prng.int(u8);
250
+ const slice = buffer[0..count];
251
+
252
+ array = Array.from_slice(slice) catch unreachable;
253
+ model.clearRetainingCapacity();
254
+ model.appendSliceAssumeCapacity(slice);
255
+ },
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ test "BoundedArray.insert_at" {
262
+ const items_max = 32;
263
+ const BoundedArrayU64 = BoundedArrayType(u64, items_max);
264
+
265
+ // Test lists of every size (less than the capacity).
266
+ for (0..items_max) |len| {
267
+ var list_base = BoundedArrayU64{};
268
+ for (0..len) |i| {
269
+ list_base.push(i);
270
+ }
271
+
272
+ // Test an insert at every possible position (including an append).
273
+ for (0..list_base.count() + 1) |i| {
274
+ var list = list_base;
275
+
276
+ list.insert_at(i, 12345);
277
+
278
+ // Verify the result:
279
+
280
+ try std.testing.expectEqual(list.count(), list_base.count() + 1);
281
+ try std.testing.expectEqual(list.get(i), 12345);
282
+
283
+ for (0..i) |j| {
284
+ try std.testing.expectEqual(list.get(j), j);
285
+ }
286
+
287
+ for (i + 1..list.count()) |j| {
288
+ try std.testing.expectEqual(list.get(j), j - 1);
289
+ }
290
+ }
291
+ }
292
+ }
@@ -0,0 +1,65 @@
1
+ const std = @import("std");
2
+
3
+ /// Utility function for ad-hoc profiling.
4
+ ///
5
+ /// A thin wrapper around `std.time.Timer` which handles the boilerplate of
6
+ /// printing to stderr and formatting times in some (unspecified) readable way.
7
+ pub fn timeit() TimeIt {
8
+ return TimeIt{ .inner = std.time.Timer.start() catch unreachable };
9
+ }
10
+
11
+ const TimeIt = struct {
12
+ inner: std.time.Timer,
13
+
14
+ /// Prints elapsed time to stderr and resets the internal timer.
15
+ pub fn print(self: *TimeIt, comptime label: []const u8) void {
16
+ const label_alignment = comptime " " ** (1 + (12 -| label.len));
17
+
18
+ const elapsed_ns = self.inner.lap();
19
+ std.debug.print(
20
+ label ++ ":" ++ label_alignment ++ "{}\n",
21
+ .{std.fmt.fmtDuration(elapsed_ns)},
22
+ );
23
+ }
24
+
25
+ pub fn print_if_longer_than_ms(
26
+ self: *TimeIt,
27
+ threshold_ms: u64,
28
+ comptime label: []const u8,
29
+ ) void {
30
+ self.if_longer_than(label, threshold_ms, false);
31
+ }
32
+
33
+ pub fn backtrace_if_longer_than_ms(
34
+ self: *TimeIt,
35
+ threshold_ms: u64,
36
+ comptime label: []const u8,
37
+ ) void {
38
+ self.if_longer_than(label, threshold_ms, true);
39
+ }
40
+
41
+ fn if_longer_than(
42
+ self: *TimeIt,
43
+ comptime label: []const u8,
44
+ threshold_ms: u64,
45
+ backtrace: bool,
46
+ ) void {
47
+ const elapsed_ns = self.inner.lap();
48
+ if (elapsed_ns > threshold_ms * std.time.ns_per_ms) {
49
+ std.debug.print(label ++ ": {}\n", .{std.fmt.fmtDuration(elapsed_ns)});
50
+ if (backtrace) std.debug.dumpCurrentStackTrace(null);
51
+ }
52
+ }
53
+ };
54
+
55
+ /// Utility for print-if debugging, a-la Rust's dbg! macro.
56
+ ///
57
+ /// dbg prints the value with the prefix, while also returning the value, which makes it convenient
58
+ /// to drop it in the middle of a complex expression.
59
+ pub fn dbg(prefix: []const u8, value: anytype) @TypeOf(value) {
60
+ std.debug.print("{s} = {any}\n", .{
61
+ prefix,
62
+ std.json.fmt(value, .{ .whitespace = .indent_2 }),
63
+ });
64
+ return value;
65
+ }