farce 0.0.1.alpha2-java

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 (376) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +26 -0
  3. data/CONTRIBUTING.md +71 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +1524 -0
  6. data/SECURITY.md +10 -0
  7. data/docs/benchmarks.md +185 -0
  8. data/docs/gems/dry-types.md +290 -0
  9. data/docs/gems/msgpack.md +70 -0
  10. data/docs/gems/ractor-shim.md +63 -0
  11. data/docs/modes.md +628 -0
  12. data/docs/scopes.md +649 -0
  13. data/docs/variants.md +346 -0
  14. data/lib/farce/_yard/internal.rb +13 -0
  15. data/lib/farce/_yard/macros.rb +61 -0
  16. data/lib/farce/_yard/ractor.rb +46 -0
  17. data/lib/farce/abstract/atom.rb +186 -0
  18. data/lib/farce/abstract/bounded_map.rb +232 -0
  19. data/lib/farce/abstract/collection.rb +151 -0
  20. data/lib/farce/abstract/concurrent_map.rb +381 -0
  21. data/lib/farce/abstract/counter.rb +193 -0
  22. data/lib/farce/abstract/duplicable_map.rb +229 -0
  23. data/lib/farce/abstract/exchanger.rb +26 -0
  24. data/lib/farce/abstract/flag.rb +71 -0
  25. data/lib/farce/abstract/lazy.rb +115 -0
  26. data/lib/farce/abstract/lease.rb +104 -0
  27. data/lib/farce/abstract/lease_map.rb +261 -0
  28. data/lib/farce/abstract/lease_pool.rb +91 -0
  29. data/lib/farce/abstract/lfu_map.rb +20 -0
  30. data/lib/farce/abstract/lru_map.rb +25 -0
  31. data/lib/farce/abstract/map.rb +345 -0
  32. data/lib/farce/abstract/molecule.rb +245 -0
  33. data/lib/farce/abstract/port.rb +74 -0
  34. data/lib/farce/abstract/priority_queue.rb +117 -0
  35. data/lib/farce/abstract/queue.rb +269 -0
  36. data/lib/farce/abstract/scheduler.rb +111 -0
  37. data/lib/farce/abstract/set.rb +910 -0
  38. data/lib/farce/abstract/sorted_set.rb +172 -0
  39. data/lib/farce/abstract/timer_queue.rb +136 -0
  40. data/lib/farce/abstract/tree_map.rb +269 -0
  41. data/lib/farce/abstract/value.rb +68 -0
  42. data/lib/farce/abstract/vector.rb +1126 -0
  43. data/lib/farce/abstract/weak_atom.rb +32 -0
  44. data/lib/farce/abstract/weak_key_map.rb +12 -0
  45. data/lib/farce/abstract/weak_map.rb +13 -0
  46. data/lib/farce/abstract/weak_set.rb +12 -0
  47. data/lib/farce/abstract/weak_value_map.rb +12 -0
  48. data/lib/farce/abstract.rb +17 -0
  49. data/lib/farce/atom.rb +293 -0
  50. data/lib/farce/class_mirror.rb +87 -0
  51. data/lib/farce/clock.rb +121 -0
  52. data/lib/farce/config.rb +229 -0
  53. data/lib/farce/counter.rb +71 -0
  54. data/lib/farce/deduper.rb +122 -0
  55. data/lib/farce/engine/jruby/bounded_map.rb +314 -0
  56. data/lib/farce/engine/jruby/fiber_scheduler.jar +0 -0
  57. data/lib/farce/engine/jruby/fiber_scheduler.rb +119 -0
  58. data/lib/farce/engine/jruby/lease_waiting.rb +19 -0
  59. data/lib/farce/engine/jruby/map.rb +505 -0
  60. data/lib/farce/engine/jruby/mutable_numeric_copy.rb +42 -0
  61. data/lib/farce/engine/jruby/signal.rb +147 -0
  62. data/lib/farce/engine/jruby.rb +63 -0
  63. data/lib/farce/engine/jvm/concurrent_weak_registry.rb +55 -0
  64. data/lib/farce/engine/jvm/counter.rb +102 -0
  65. data/lib/farce/engine/jvm/extension.rb +32 -0
  66. data/lib/farce/engine/jvm/farce.jar +0 -0
  67. data/lib/farce/engine/jvm/flag.rb +79 -0
  68. data/lib/farce/engine/jvm/priority_queue.rb +217 -0
  69. data/lib/farce/engine/jvm/tree_map.rb +350 -0
  70. data/lib/farce/engine/jvm/types.rb +180 -0
  71. data/lib/farce/engine/jvm.rb +19 -0
  72. data/lib/farce/engine/ruby/3.4/fiber_scheduler.rb +20 -0
  73. data/lib/farce/engine/ruby/3.4/port.rb +186 -0
  74. data/lib/farce/engine/ruby/3.4/ractor_methods.rb +26 -0
  75. data/lib/farce/engine/ruby/3.4/ractor_selector.rb +92 -0
  76. data/lib/farce/engine/ruby/3.4/vault.rb +56 -0
  77. data/lib/farce/engine/ruby/4.0/port.rb +19 -0
  78. data/lib/farce/engine/ruby/4.0/ractor_methods.rb +20 -0
  79. data/lib/farce/engine/ruby/4.0/ractor_selector.rb +108 -0
  80. data/lib/farce/engine/ruby/4.0/vault.rb +74 -0
  81. data/lib/farce/engine/ruby/4.1/port.rb +21 -0
  82. data/lib/farce/engine/ruby/4.1/ractor_methods.rb +22 -0
  83. data/lib/farce/engine/ruby/4.1/ractor_selector.rb +25 -0
  84. data/lib/farce/engine/ruby/4.1/vault.rb +5 -0
  85. data/lib/farce/engine/ruby/fiber_scheduler.rb +32 -0
  86. data/lib/farce/engine/ruby/key_lock_map.rb +28 -0
  87. data/lib/farce/engine/ruby/shared/lease.rb +26 -0
  88. data/lib/farce/engine/ruby/shared/lease_pool.rb +24 -0
  89. data/lib/farce/engine/ruby/shared/main_scheduler.rb +9 -0
  90. data/lib/farce/engine/ruby/shared/parallel_scheduler.rb +9 -0
  91. data/lib/farce/engine/ruby/shared/proxy_owner.rb +31 -0
  92. data/lib/farce/engine/ruby/shared/ractor_methods.rb +34 -0
  93. data/lib/farce/engine/ruby/shared/ractor_selector.rb +328 -0
  94. data/lib/farce/engine/ruby/shared/strict_map.rb +13 -0
  95. data/lib/farce/engine/ruby/shared/unshared_vector.rb +14 -0
  96. data/lib/farce/engine/ruby/shared/vault.rb +144 -0
  97. data/lib/farce/engine/ruby/shared/vault_weak_map.rb +336 -0
  98. data/lib/farce/engine/ruby/shared/weak_atom.rb +54 -0
  99. data/lib/farce/engine/ruby/shared/weak_map.rb +413 -0
  100. data/lib/farce/engine/ruby.rb +130 -0
  101. data/lib/farce/engine/shared/atom.rb +10 -0
  102. data/lib/farce/engine/shared/exchanger.rb +130 -0
  103. data/lib/farce/engine/shared/identity_key.rb +22 -0
  104. data/lib/farce/engine/shared/lease.rb +10 -0
  105. data/lib/farce/engine/shared/lease_pool.rb +10 -0
  106. data/lib/farce/engine/shared/main_scheduler.rb +20 -0
  107. data/lib/farce/engine/shared/map_key_coordination.rb +226 -0
  108. data/lib/farce/engine/shared/parallel_scheduler.rb +9 -0
  109. data/lib/farce/engine/shared/port.rb +44 -0
  110. data/lib/farce/engine/shared/portable_bounded_map.rb +619 -0
  111. data/lib/farce/engine/shared/proxy_owner.rb +43 -0
  112. data/lib/farce/engine/shared/queue.rb +233 -0
  113. data/lib/farce/engine/shared/ractor_methods.rb +73 -0
  114. data/lib/farce/engine/shared/rebindable.rb +15 -0
  115. data/lib/farce/engine/shared/strict_atom.rb +73 -0
  116. data/lib/farce/engine/shared/strict_map.rb +117 -0
  117. data/lib/farce/engine/shared/strict_queue_values.rb +27 -0
  118. data/lib/farce/engine/shared/strict_tree_map.rb +56 -0
  119. data/lib/farce/engine/shared/transaction_map_backend.rb +20 -0
  120. data/lib/farce/engine/shared/trie.rb +317 -0
  121. data/lib/farce/engine/shared/trie_builder.rb +199 -0
  122. data/lib/farce/engine/shared/unshareable.rb +14 -0
  123. data/lib/farce/engine/shared/unshared_atom.rb +256 -0
  124. data/lib/farce/engine/shared/unshared_priority_queue.rb +9 -0
  125. data/lib/farce/engine/shared/unshared_queue.rb +18 -0
  126. data/lib/farce/engine/shared/unshared_signal.rb +21 -0
  127. data/lib/farce/engine/shared/unshared_vector.rb +377 -0
  128. data/lib/farce/engine/shared/unshared_weak_atom.rb +30 -0
  129. data/lib/farce/engine/shared/unshared_weak_map.rb +445 -0
  130. data/lib/farce/engine/shared/vault.rb +31 -0
  131. data/lib/farce/engine/shared/vector.rb +83 -0
  132. data/lib/farce/engine/shared/weak_atom/base.rb +189 -0
  133. data/lib/farce/engine/shared/weak_atom.rb +20 -0
  134. data/lib/farce/engine/shared/weak_map/cell.rb +99 -0
  135. data/lib/farce/engine/shared/weak_map/index.rb +249 -0
  136. data/lib/farce/engine/shared/weak_map/lock.rb +80 -0
  137. data/lib/farce/engine/shared/weak_map/reference.rb +33 -0
  138. data/lib/farce/engine/shared.rb +63 -0
  139. data/lib/farce/engine/truffleruby/fiber_scheduler.rb +13 -0
  140. data/lib/farce/engine/truffleruby/lock.rb +121 -0
  141. data/lib/farce/engine/truffleruby/map.rb +656 -0
  142. data/lib/farce/engine/truffleruby/native/counter.rb +105 -0
  143. data/lib/farce/engine/truffleruby/native/flag.rb +77 -0
  144. data/lib/farce/engine/truffleruby/native/ordered_array_support.rb +67 -0
  145. data/lib/farce/engine/truffleruby/native/priority_queue.rb +388 -0
  146. data/lib/farce/engine/truffleruby/native/tree_map.rb +51 -0
  147. data/lib/farce/engine/truffleruby/native/unsafe_tree_map.rb +350 -0
  148. data/lib/farce/engine/truffleruby/signal.rb +77 -0
  149. data/lib/farce/engine/truffleruby.rb +148 -0
  150. data/lib/farce/envelope.rb +335 -0
  151. data/lib/farce/error.rb +35 -0
  152. data/lib/farce/exchanger.rb +41 -0
  153. data/lib/farce/flag.rb +27 -0
  154. data/lib/farce/integrations/active_support/blank.rb +68 -0
  155. data/lib/farce/integrations/active_support/clock.rb +17 -0
  156. data/lib/farce/integrations/active_support/duplicable.rb +78 -0
  157. data/lib/farce/integrations/active_support/map.rb +175 -0
  158. data/lib/farce/integrations/active_support/set.rb +60 -0
  159. data/lib/farce/integrations/active_support/value_serialization.rb +17 -0
  160. data/lib/farce/integrations/active_support/vector.rb +231 -0
  161. data/lib/farce/integrations/active_support.rb +9 -0
  162. data/lib/farce/integrations/activesupport.rb +5 -0
  163. data/lib/farce/integrations/bson.rb +108 -0
  164. data/lib/farce/integrations/cbor.rb +51 -0
  165. data/lib/farce/integrations/concurrent.rb +112 -0
  166. data/lib/farce/integrations/dry-types.rb +5 -0
  167. data/lib/farce/integrations/dry_types.rb +694 -0
  168. data/lib/farce/integrations/json.rb +7 -0
  169. data/lib/farce/integrations/msgpack.rb +112 -0
  170. data/lib/farce/integrations/oj.rb +69 -0
  171. data/lib/farce/integrations/psych.rb +191 -0
  172. data/lib/farce/integrations/ractor-sharing.rb +5 -0
  173. data/lib/farce/integrations/ractor-tmvar.rb +5 -0
  174. data/lib/farce/integrations/ractor_sharing.rb +172 -0
  175. data/lib/farce/integrations/ractor_tmvar.rb +64 -0
  176. data/lib/farce/integrations/shared/to_json.rb +42 -0
  177. data/lib/farce/integrations/sorted_set.rb +11 -0
  178. data/lib/farce/integrations/weakref.rb +38 -0
  179. data/lib/farce/integrations/yajl.rb +10 -0
  180. data/lib/farce/integrations.rb +156 -0
  181. data/lib/farce/internal/_frozen_config.rb +11 -0
  182. data/lib/farce/internal/autoloads.rb +47 -0
  183. data/lib/farce/internal/blocking_priority_queue.rb +122 -0
  184. data/lib/farce/internal/converter.rb +106 -0
  185. data/lib/farce/internal/copyable.rb +31 -0
  186. data/lib/farce/internal/delegation.rb +20 -0
  187. data/lib/farce/internal/external_transaction.rb +59 -0
  188. data/lib/farce/internal/fake_ractor.rb +179 -0
  189. data/lib/farce/internal/freeze.rb +118 -0
  190. data/lib/farce/internal/inspect.rb +157 -0
  191. data/lib/farce/internal/key_lock_map.rb +29 -0
  192. data/lib/farce/internal/key_normalizer.rb +289 -0
  193. data/lib/farce/internal/lease_initialization.rb +115 -0
  194. data/lib/farce/internal/lease_map.rb +441 -0
  195. data/lib/farce/internal/lease_pool_state.rb +228 -0
  196. data/lib/farce/internal/lease_state.rb +342 -0
  197. data/lib/farce/internal/lease_waiting.rb +13 -0
  198. data/lib/farce/internal/managed_queue.rb +26 -0
  199. data/lib/farce/internal/map_value_modes.rb +227 -0
  200. data/lib/farce/internal/marshal_support.rb +227 -0
  201. data/lib/farce/internal/mixin.rb +20 -0
  202. data/lib/farce/internal/mutable_ordered_key_lock_map.rb +63 -0
  203. data/lib/farce/internal/noncopyable.rb +17 -0
  204. data/lib/farce/internal/ordered_key_lock_map.rb +69 -0
  205. data/lib/farce/internal/pool_supervisor.rb +41 -0
  206. data/lib/farce/internal/pool_worker.rb +61 -0
  207. data/lib/farce/internal/portable_transaction/reservation_entry.rb +29 -0
  208. data/lib/farce/internal/portable_transaction/strong_map_entry.rb +137 -0
  209. data/lib/farce/internal/portable_transaction/strong_map_size_entry.rb +44 -0
  210. data/lib/farce/internal/portable_transaction/tree_entry.rb +64 -0
  211. data/lib/farce/internal/portable_transaction.rb +164 -0
  212. data/lib/farce/internal/proxy_owner_notifications.rb +29 -0
  213. data/lib/farce/internal/reservation_waiting.rb +24 -0
  214. data/lib/farce/internal/scheduled_task.rb +48 -0
  215. data/lib/farce/internal/scheduler_io.rb +171 -0
  216. data/lib/farce/internal/scheduler_lifecycle.rb +314 -0
  217. data/lib/farce/internal/select_scheduler.rb +235 -0
  218. data/lib/farce/internal/storage.rb +162 -0
  219. data/lib/farce/internal/strict_lease.rb +30 -0
  220. data/lib/farce/internal/strict_lease_map.rb +20 -0
  221. data/lib/farce/internal/strict_lease_pool.rb +29 -0
  222. data/lib/farce/internal/thread_pool.rb +166 -0
  223. data/lib/farce/internal/transaction_conflict.rb +9 -0
  224. data/lib/farce/internal/transaction_freeze_guard.rb +30 -0
  225. data/lib/farce/internal/transaction_map_snapshot.rb +123 -0
  226. data/lib/farce/internal/undefined.rb +22 -0
  227. data/lib/farce/internal/unshared_lease.rb +29 -0
  228. data/lib/farce/internal/unshared_lease_pool.rb +34 -0
  229. data/lib/farce/internal/unshared_queue_waiting.rb +28 -0
  230. data/lib/farce/internal/value_serialization.rb +13 -0
  231. data/lib/farce/internal/weak_map_value_modes.rb +58 -0
  232. data/lib/farce/internal/weak_mode_manager.rb +26 -0
  233. data/lib/farce/internal.rb +129 -0
  234. data/lib/farce/lazy.rb +100 -0
  235. data/lib/farce/lazy_ref.rb +40 -0
  236. data/lib/farce/lease.rb +28 -0
  237. data/lib/farce/lease_map.rb +34 -0
  238. data/lib/farce/lease_pool.rb +29 -0
  239. data/lib/farce/lfu_map.rb +53 -0
  240. data/lib/farce/local/atom.rb +23 -0
  241. data/lib/farce/local/counter.rb +88 -0
  242. data/lib/farce/local/flag.rb +65 -0
  243. data/lib/farce/local/lazy.rb +38 -0
  244. data/lib/farce/local/lazy_ref.rb +36 -0
  245. data/lib/farce/local/lease.rb +77 -0
  246. data/lib/farce/local/lease_map.rb +80 -0
  247. data/lib/farce/local/lease_pool.rb +38 -0
  248. data/lib/farce/local/lfu_map.rb +55 -0
  249. data/lib/farce/local/lru_map.rb +62 -0
  250. data/lib/farce/local/map.rb +47 -0
  251. data/lib/farce/local/molecule.rb +45 -0
  252. data/lib/farce/local/priority_queue.rb +53 -0
  253. data/lib/farce/local/queue.rb +32 -0
  254. data/lib/farce/local/scoped.rb +166 -0
  255. data/lib/farce/local/set.rb +18 -0
  256. data/lib/farce/local/sorted_set.rb +50 -0
  257. data/lib/farce/local/timer_queue.rb +41 -0
  258. data/lib/farce/local/tree_map.rb +47 -0
  259. data/lib/farce/local/vector.rb +30 -0
  260. data/lib/farce/local/weak_atom.rb +23 -0
  261. data/lib/farce/local/weak_key_map.rb +39 -0
  262. data/lib/farce/local/weak_map.rb +39 -0
  263. data/lib/farce/local/weak_set.rb +18 -0
  264. data/lib/farce/local/weak_value_map.rb +39 -0
  265. data/lib/farce/local.rb +35 -0
  266. data/lib/farce/lock.rb +54 -0
  267. data/lib/farce/lru_map.rb +63 -0
  268. data/lib/farce/map.rb +58 -0
  269. data/lib/farce/mode_manager.rb +142 -0
  270. data/lib/farce/molecule.rb +60 -0
  271. data/lib/farce/mutable.rb +171 -0
  272. data/lib/farce/pool.rb +332 -0
  273. data/lib/farce/port.rb +134 -0
  274. data/lib/farce/priority_queue.rb +70 -0
  275. data/lib/farce/proxy/register.rb +101 -0
  276. data/lib/farce/proxy/supervisor.rb +137 -0
  277. data/lib/farce/proxy/wrapper.rb +49 -0
  278. data/lib/farce/proxy.rb +291 -0
  279. data/lib/farce/queue.rb +60 -0
  280. data/lib/farce/ractor.rb +269 -0
  281. data/lib/farce/read_write_lock.rb +256 -0
  282. data/lib/farce/reference.rb +158 -0
  283. data/lib/farce/resolv/dns.rb +42 -0
  284. data/lib/farce/resolv.rb +85 -0
  285. data/lib/farce/scheduler.rb +536 -0
  286. data/lib/farce/set.rb +39 -0
  287. data/lib/farce/shareable.rb +150 -0
  288. data/lib/farce/signal.rb +97 -0
  289. data/lib/farce/sorted_set.rb +36 -0
  290. data/lib/farce/strict/atom.rb +34 -0
  291. data/lib/farce/strict/counter.rb +10 -0
  292. data/lib/farce/strict/exchanger.rb +25 -0
  293. data/lib/farce/strict/flag.rb +10 -0
  294. data/lib/farce/strict/lazy.rb +26 -0
  295. data/lib/farce/strict/lazy_ref.rb +26 -0
  296. data/lib/farce/strict/lease.rb +27 -0
  297. data/lib/farce/strict/lease_map.rb +33 -0
  298. data/lib/farce/strict/lease_pool.rb +28 -0
  299. data/lib/farce/strict/lfu_map.rb +27 -0
  300. data/lib/farce/strict/lru_map.rb +28 -0
  301. data/lib/farce/strict/map.rb +54 -0
  302. data/lib/farce/strict/molecule.rb +16 -0
  303. data/lib/farce/strict/port.rb +40 -0
  304. data/lib/farce/strict/priority_queue.rb +20 -0
  305. data/lib/farce/strict/queue.rb +17 -0
  306. data/lib/farce/strict/set.rb +14 -0
  307. data/lib/farce/strict/sorted_set.rb +19 -0
  308. data/lib/farce/strict/timer_queue.rb +13 -0
  309. data/lib/farce/strict/tree_map.rb +27 -0
  310. data/lib/farce/strict/vector.rb +24 -0
  311. data/lib/farce/strict/weak_atom.rb +31 -0
  312. data/lib/farce/strict/weak_key_map.rb +49 -0
  313. data/lib/farce/strict/weak_map.rb +49 -0
  314. data/lib/farce/strict/weak_set.rb +14 -0
  315. data/lib/farce/strict/weak_value_map.rb +48 -0
  316. data/lib/farce/strict.rb +28 -0
  317. data/lib/farce/system.rb +40 -0
  318. data/lib/farce/thread_scheduler.rb +70 -0
  319. data/lib/farce/timer_queue.rb +66 -0
  320. data/lib/farce/transaction/atom.rb +73 -0
  321. data/lib/farce/transaction/map.rb +25 -0
  322. data/lib/farce/transaction/map_operations.rb +143 -0
  323. data/lib/farce/transaction/molecule.rb +90 -0
  324. data/lib/farce/transaction/mutable.rb +61 -0
  325. data/lib/farce/transaction/set.rb +17 -0
  326. data/lib/farce/transaction/set_operations.rb +48 -0
  327. data/lib/farce/transaction/sorted_set.rb +18 -0
  328. data/lib/farce/transaction/tree_map.rb +78 -0
  329. data/lib/farce/transaction/vector.rb +139 -0
  330. data/lib/farce/transaction/wrapper.rb +202 -0
  331. data/lib/farce/transaction.rb +343 -0
  332. data/lib/farce/tree_map.rb +56 -0
  333. data/lib/farce/unsafe/lfu_map.rb +36 -0
  334. data/lib/farce/unsafe/lru_map.rb +36 -0
  335. data/lib/farce/unsafe/tree_map.rb +21 -0
  336. data/lib/farce/unsafe.rb +29 -0
  337. data/lib/farce/unshareable.rb +67 -0
  338. data/lib/farce/unshared/atom.rb +24 -0
  339. data/lib/farce/unshared/counter.rb +10 -0
  340. data/lib/farce/unshared/flag.rb +10 -0
  341. data/lib/farce/unshared/lazy.rb +38 -0
  342. data/lib/farce/unshared/lazy_ref.rb +26 -0
  343. data/lib/farce/unshared/lease.rb +27 -0
  344. data/lib/farce/unshared/lease_map.rb +26 -0
  345. data/lib/farce/unshared/lease_pool.rb +25 -0
  346. data/lib/farce/unshared/lfu_map.rb +20 -0
  347. data/lib/farce/unshared/lru_map.rb +20 -0
  348. data/lib/farce/unshared/map.rb +49 -0
  349. data/lib/farce/unshared/molecule.rb +16 -0
  350. data/lib/farce/unshared/priority_queue.rb +16 -0
  351. data/lib/farce/unshared/queue.rb +27 -0
  352. data/lib/farce/unshared/set.rb +14 -0
  353. data/lib/farce/unshared/sorted_set.rb +28 -0
  354. data/lib/farce/unshared/timer_queue.rb +16 -0
  355. data/lib/farce/unshared/tree_map.rb +21 -0
  356. data/lib/farce/unshared/vector.rb +19 -0
  357. data/lib/farce/unshared/weak_atom.rb +31 -0
  358. data/lib/farce/unshared/weak_key_map.rb +44 -0
  359. data/lib/farce/unshared/weak_map.rb +44 -0
  360. data/lib/farce/unshared/weak_set.rb +14 -0
  361. data/lib/farce/unshared/weak_value_map.rb +43 -0
  362. data/lib/farce/unshared.rb +28 -0
  363. data/lib/farce/vector.rb +228 -0
  364. data/lib/farce/version.rb +8 -0
  365. data/lib/farce/walker/definitions.rb +186 -0
  366. data/lib/farce/walker/modification.rb +355 -0
  367. data/lib/farce/walker.rb +319 -0
  368. data/lib/farce/weak_atom.rb +121 -0
  369. data/lib/farce/weak_key_map.rb +31 -0
  370. data/lib/farce/weak_map.rb +33 -0
  371. data/lib/farce/weak_ref.rb +67 -0
  372. data/lib/farce/weak_set.rb +82 -0
  373. data/lib/farce/weak_value.rb +195 -0
  374. data/lib/farce/weak_value_map.rb +32 -0
  375. data/lib/farce.rb +519 -0
  376. metadata +420 -0
@@ -0,0 +1,1126 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # @abstract Superclass for concurrent indexed collections.
8
+ # Negative indexes count from the end. Assignments beyond the end fill gaps with nil.
9
+ # Atomic updates reserve the entire vector. Reads through {#[]} do not wait for updates.
10
+ # Timeouts are finite, non-negative seconds. Nil waits indefinitely for access.
11
+ class Vector < Collection
12
+ include Internal::MarshalSupport::Vector
13
+
14
+ # @api private
15
+ def transaction_wrapper(transaction) = Transaction::Vector.new(transaction, self, internal_vector)
16
+
17
+ # Iterate over live entries, up to the length when enumeration starts.
18
+ # Changes can affect entries not yet visited. Indexes beyond the starting length are not visited.
19
+ # Each entry is read separately. The block runs without holding a collection lock.
20
+ # @yield [value] Called for each entry. Returns an Enumerator without a block.
21
+ # @yieldparam value [BasicObject] The current value.
22
+ # @yieldreturn [void] The result is ignored.
23
+ # @return [self, Enumerator]
24
+ def each
25
+ return enum_for(__method__) { size } unless block_given?
26
+
27
+ internal_vector.each { yield logical_value(it) }
28
+ self
29
+ end
30
+
31
+ # Iterate over indexes up to the length when enumeration starts.
32
+ # @yield [index] Called for each index. Returns an Enumerator without a block.
33
+ # @yieldparam index [Integer] The current index.
34
+ # @yieldreturn [void] The result is ignored.
35
+ # @return [self, Enumerator]
36
+ def each_index(&)
37
+ return enum_for(__method__) { size } unless block_given?
38
+
39
+ size.times(&)
40
+ self
41
+ end
42
+
43
+ # Iterate over live entries from the last index when enumeration starts.
44
+ # Replacements and removals can affect entries not yet visited. The block runs without a collection lock.
45
+ # @yield [value] Called for each entry. Returns an Enumerator without a block.
46
+ # @yieldparam value [BasicObject] The current value.
47
+ # @yieldreturn [void] The result is ignored.
48
+ # @return [self, Enumerator]
49
+ def reverse_each
50
+ return enum_for(__method__) { size } unless block_given?
51
+
52
+ internal_vector.reverse_each { yield logical_value(it) }
53
+ self
54
+ end
55
+
56
+ # Return a new Array containing a logical snapshot of the values.
57
+ # @return [Array<BasicObject>] A new Array of logical values.
58
+ def to_a = internal_vector.snapshot.map! { logical_value(it) }
59
+
60
+ # (see #to_a)
61
+ def deconstruct = to_a
62
+
63
+ # Convert pair-like entries to a Hash. Vector entries are accepted as pairs.
64
+ # @yield [value] Optionally transform each entry into a key-value pair.
65
+ # @yieldparam value [BasicObject] The current entry.
66
+ # @yieldreturn [Array, Vector] A two-element key-value pair.
67
+ # @return [Hash] The converted pairs. Without a block, entries must be pair-like.
68
+ def to_h = to_a.to_h { normalize_hash_pair(block_given? ? yield(it) : it) }
69
+
70
+ # Recursively retrieve a nested value.
71
+ # @param index [Integer] The initial index. Negative indexes count from the end.
72
+ # @param identifiers [Array<BasicObject>] Indexes or keys passed to the nested value's `dig` method.
73
+ # @return [BasicObject, nil] The nested value, or nil if an intermediate value is nil.
74
+ def dig(index, *identifiers)
75
+ value = at(index)
76
+ return value if identifiers.empty?
77
+ return if value.nil?
78
+ raise TypeError, "#{value.class} does not have #dig method" unless value.respond_to?(:dig)
79
+ value.dig(*identifiers)
80
+ end
81
+
82
+ # Find the first pair whose first value equals key.
83
+ # @param key [BasicObject] The value to compare with each pair's first entry.
84
+ # @return [Array, Vector, nil] The first matching pair, or nil if none matches.
85
+ def assoc(key) = find_pair(key, 0)
86
+
87
+ # Find the first pair whose second value equals value.
88
+ # @param value [BasicObject] The value to compare with each pair's second entry.
89
+ # @return [Array, Vector, nil] The first matching pair, or nil if none matches.
90
+ def rassoc(value) = find_pair(value, 1)
91
+
92
+ # (see #[])
93
+ def at(index) = self[index]
94
+
95
+ # Fetch a value by index, with Array-compatible fallback behavior.
96
+ # @param index [Integer] The index. Negative indexes count from the end.
97
+ # @param fallback [Array<BasicObject>] At most one default value for a missing index.
98
+ # @yield [index] Called for a missing index. Takes precedence over the default value.
99
+ # @yieldparam index [BasicObject] The original index argument, before integer conversion.
100
+ # @yieldreturn [BasicObject] The fallback value.
101
+ # @return [BasicObject] The entry, default value, or block result.
102
+ # @raise [IndexError] If the index is absent and neither a default nor a block is supplied.
103
+ def fetch(index, *fallback)
104
+ original_index = index
105
+ index = convert_vector_index(index)
106
+
107
+ if fallback.length > 1
108
+ raise ArgumentError, "wrong number of arguments (given #{fallback.length + 1}, expected 1..2)"
109
+ end
110
+
111
+ warn("block supersedes default value argument") if !fallback.empty? && block_given?
112
+
113
+ return logical_value(internal_vector.fetch(index)) if fallback.empty? && !block_given?
114
+
115
+ stored = internal_vector.fetch(index) do
116
+ return yield(original_index) if block_given?
117
+ return fallback.first
118
+ end
119
+
120
+ logical_value(stored)
121
+ end
122
+
123
+ # Fetch several values. Missing indexes are passed to the block.
124
+ # @param indexes [Array<Integer>] The indexes to fetch.
125
+ # @yield [index] Called for each missing index when a block is supplied.
126
+ # @yieldparam index [BasicObject] The original missing index argument.
127
+ # @yieldreturn [BasicObject] The fallback value.
128
+ # @return [Vector] The requested entries and fallback values.
129
+ # @raise [IndexError] If an index is absent and no block is supplied.
130
+ def fetch_values(*indexes)
131
+ values = if block_given?
132
+ indexes.map { |index| internal_vector.fetch(index) { derived_storage(yield(index)) } }
133
+ else
134
+ indexes.map { internal_vector.fetch(it) }
135
+ end
136
+ build_derived_vector(values)
137
+ end
138
+
139
+ # Select values at indexes and ranges.
140
+ # @overload values_at(*indexes)
141
+ # @param indexes [Array<Integer, Range>] The indexes and ranges to select.
142
+ # @return [Vector] The selected entries, with nil for missing positions.
143
+ def values_at(...) = build_derived_vector(internal_vector.snapshot.values_at(...))
144
+
145
+ # Return one value, or a Vector when a count is supplied.
146
+ # @param count [Integer] The maximum number of entries. Omit to return one entry.
147
+ # @return [BasicObject, Vector, nil] The first entry, nil if empty, or a Vector when count is supplied.
148
+ def first(count = UNDEFINED)
149
+ return self[0] if count.equal?(UNDEFINED)
150
+
151
+ snapshot = internal_vector.snapshot
152
+ build_derived_vector(snapshot.first(count))
153
+ end
154
+
155
+ # Return one value, or a Vector when a count is supplied.
156
+ # @param count [Integer] The maximum number of entries. Omit to return one entry.
157
+ # @return [BasicObject, Vector, nil] The last entry, nil if empty, or a Vector when count is supplied.
158
+ def last(count = UNDEFINED)
159
+ return self[-1] if count.equal?(UNDEFINED)
160
+
161
+ snapshot = internal_vector.snapshot
162
+ build_derived_vector(snapshot.last(count))
163
+ end
164
+
165
+ # Return an element or subsequence without changing the hot path for {#[]}.
166
+ # Range and start-length results are Vectors.
167
+ # @param index [Integer, Range] An index, range, or start index when length is supplied.
168
+ # @param length [Integer] The maximum length of a subsequence. Omit for a single index or range.
169
+ # @return [BasicObject, Vector, nil] A single entry, a Vector subsequence, or nil for an invalid slice.
170
+ def slice(index, length = UNDEFINED)
171
+ snapshot = internal_vector.snapshot
172
+
173
+ if length.equal?(UNDEFINED)
174
+ result = snapshot.slice(index)
175
+ return logical_value(result) unless index.is_a?(Range)
176
+ else
177
+ result = snapshot.slice(index, length)
178
+ end
179
+
180
+ result && build_derived_vector(result)
181
+ end
182
+
183
+ # Return whether a live entry equals value.
184
+ # @param value [BasicObject] The value to find using `==`.
185
+ # @return [Boolean] Whether a matching entry exists.
186
+ def include?(value)
187
+ each { return true if array_value_equal?(it, value) }
188
+ false
189
+ end
190
+ alias member? include?
191
+
192
+ # Return the first matching index.
193
+ # @param value [BasicObject] The value to find. Omit to use the block.
194
+ # @yield [entry] Test each entry when value is omitted.
195
+ # @yieldparam entry [BasicObject] The current entry.
196
+ # @yieldreturn [BasicObject] A truthy value for a match.
197
+ # @return [Integer, nil, Enumerator] The matching index, nil if absent, or an Enumerator without a value or block.
198
+ def index(value = UNDEFINED)
199
+ return enum_for(__method__) { size } if value.equal?(UNDEFINED) && !block_given? # rubocop:disable Lint/ToEnumArguments
200
+
201
+ warn("given block not used") if !value.equal?(UNDEFINED) && block_given?
202
+ each_with_index do |entry, index|
203
+ return index if value.equal?(UNDEFINED) ? yield(entry) : array_value_equal?(entry, value)
204
+ end
205
+ nil
206
+ end
207
+ alias find_index index
208
+
209
+ # Return the last matching index.
210
+ # @param value [BasicObject] The value to find. Omit to use the block.
211
+ # @yield [entry] Test each entry when value is omitted.
212
+ # @yieldparam entry [BasicObject] The current entry.
213
+ # @yieldreturn [BasicObject] A truthy value for a match.
214
+ # @return [Integer, nil, Enumerator] The matching index, nil if absent, or an Enumerator without a value or block.
215
+ def rindex(value = UNDEFINED)
216
+ return enum_for(__method__) { size } if value.equal?(UNDEFINED) && !block_given? # rubocop:disable Lint/ToEnumArguments
217
+
218
+ warn("given block not used") if !value.equal?(UNDEFINED) && block_given?
219
+ backend = internal_vector
220
+ index = backend.size
221
+ while index.positive?
222
+ index -= 1
223
+ found = true
224
+ stored = backend.fetch(index) { found = false }
225
+ next unless found
226
+ entry = logical_value(stored)
227
+ return index if value.equal?(UNDEFINED) ? yield(entry) : array_value_equal?(entry, value)
228
+ end
229
+ nil
230
+ end
231
+
232
+ # Find a value by searching from the end.
233
+ # @param if_none [#call, nil] Called without arguments if no entry matches.
234
+ # @yield [value] Test entries from last to first.
235
+ # @yieldparam value [BasicObject] The current entry.
236
+ # @yieldreturn [BasicObject] A truthy value for a match.
237
+ # @return [BasicObject, nil, Enumerator] The matching entry, the fallback result, or an Enumerator without a
238
+ # block.
239
+ def rfind(if_none = nil)
240
+ return enum_for(__method__, if_none) { size } unless block_given?
241
+
242
+ reverse_each { return it if yield(it) }
243
+ if_none&.call
244
+ end
245
+
246
+ # Transform a snapshot into a Vector.
247
+ # @yield [value] Transform each entry. Returns an Enumerator without a block.
248
+ # @yieldparam value [BasicObject] The current value.
249
+ # @yieldreturn [BasicObject] The replacement value.
250
+ # @return [Vector, Enumerator]
251
+ def map
252
+ return enum_for(__method__) { size } unless block_given?
253
+
254
+ snapshot = internal_vector.snapshot
255
+ logical = []
256
+ mapped = snapshot.map do |stored|
257
+ value = logical_value(stored)
258
+ logical << value
259
+ yield value
260
+ end
261
+ build_derived_from_logical(mapped, snapshot, logical)
262
+ end
263
+ alias collect map
264
+
265
+ # Keep values accepted by a block.
266
+ # @yield [value] Test each entry. Returns an Enumerator without a block.
267
+ # @yieldparam value [BasicObject] The current value.
268
+ # @yieldreturn [BasicObject] A truthy value to retain the entry.
269
+ # @return [Vector, Enumerator]
270
+ def select
271
+ return enum_for(__method__) { size } unless block_given?
272
+
273
+ build_derived_vector(internal_vector.each.select { yield logical_value(it) })
274
+ end
275
+ alias filter select
276
+ alias find_all select
277
+
278
+ # Remove values accepted by a block.
279
+ # @yield [value] Test each entry. Returns an Enumerator without a block.
280
+ # @yieldparam value [BasicObject] The current value.
281
+ # @yieldreturn [BasicObject] A truthy value to exclude the entry.
282
+ # @return [Vector, Enumerator]
283
+ def reject
284
+ return enum_for(__method__) { size } unless block_given?
285
+
286
+ build_derived_vector(internal_vector.each.reject { yield logical_value(it) })
287
+ end
288
+
289
+ # Transform accepted values into a Vector.
290
+ # @yield [value] Transform each entry. Returns an Enumerator without a block.
291
+ # @yieldparam value [BasicObject] The current value.
292
+ # @yieldreturn [BasicObject] The replacement value. Nil and false results are omitted.
293
+ # @return [Vector, Enumerator]
294
+ def filter_map
295
+ return enum_for(__method__) { size } unless block_given?
296
+
297
+ snapshot = internal_vector.snapshot
298
+ logical = []
299
+ values = []
300
+
301
+ snapshot.each do |stored|
302
+ value = logical_value(stored)
303
+ logical << value
304
+ mapped = yield(value)
305
+ values << mapped if mapped
306
+ end
307
+
308
+ build_derived_from_logical(values, snapshot, logical)
309
+ end
310
+
311
+ # Transform and flatten one Array or Vector level.
312
+ # @yield [value] Transform each entry. Returns an Enumerator without a block.
313
+ # @yieldparam value [BasicObject] The current value.
314
+ # @yieldreturn [BasicObject] An Array or Vector to expand by one level, or a single value to retain.
315
+ # @return [Vector, Enumerator]
316
+ def flat_map
317
+ return enum_for(__method__) { size } unless block_given?
318
+
319
+ snapshot = internal_vector.snapshot
320
+ logical = []
321
+ values = []
322
+ snapshot.each do |stored|
323
+ value = logical_value(stored)
324
+ logical << value
325
+ mapped = yield(value)
326
+ converted = mapped.is_a?(Vector) ? mapped.to_a : Array.try_convert(mapped)
327
+ values.concat(converted || [mapped])
328
+ end
329
+ build_derived_from_logical(values, snapshot, logical)
330
+ end
331
+ alias collect_concat flat_map
332
+
333
+ # Remove nil values.
334
+ # @return [Vector] A new same-kind Vector containing the result.
335
+ def compact = build_derived_vector(internal_vector.each.compact)
336
+
337
+ # Remove duplicate values, retaining the first stored entry.
338
+ # @yield [value] Optionally compute a comparison key for each entry.
339
+ # @yieldparam value [BasicObject] The current value.
340
+ # @yieldreturn [BasicObject] The key compared using `hash` and `eql?`. Without a block, entries are compared
341
+ # directly.
342
+ # @return [Vector]
343
+ def uniq
344
+ snapshot = internal_vector.snapshot
345
+ selected = if block_given?
346
+ snapshot.uniq { yield logical_value(it) }
347
+ else
348
+ snapshot.uniq { logical_value(it) }
349
+ end
350
+ build_derived_vector(selected)
351
+ end
352
+
353
+ # Return a reversed snapshot.
354
+ # @return [Vector] A new same-kind Vector containing the result.
355
+ def reverse = build_derived_vector(internal_vector.snapshot.reverse)
356
+
357
+ # Return a rotated snapshot.
358
+ # @param count [Integer] The rotation distance. Negative values rotate right.
359
+ # @return [Vector] The rotated entries.
360
+ def rotate(count = 1) = build_derived_vector(internal_vector.snapshot.rotate(count))
361
+
362
+ # Return a sorted snapshot.
363
+ # @yield [left, right] Optionally compare two entries. Without a block, uses `<=>`.
364
+ # @yieldparam left [BasicObject] The left entry.
365
+ # @yieldparam right [BasicObject] The right entry.
366
+ # @yieldreturn [Numeric] A negative number, zero, or a positive number for less than, equal to, or greater than.
367
+ # @return [Vector] The sorted entries.
368
+ def sort(&block)
369
+ snapshot = internal_vector.snapshot
370
+ logical = snapshot.map { logical_value(it) }
371
+ sorted = block ? logical.sort(&block) : logical.sort
372
+ build_derived_from_logical(sorted, snapshot, logical)
373
+ end
374
+
375
+ # Sort a snapshot by block results.
376
+ # @yield [value] Compute a sort key. Returns an Enumerator without a block.
377
+ # @yieldparam value [BasicObject] The current value.
378
+ # @yieldreturn [BasicObject] The key used to order the entry.
379
+ # @return [Vector, Enumerator]
380
+ def sort_by
381
+ return enum_for(__method__) { size } unless block_given?
382
+
383
+ snapshot = internal_vector.snapshot
384
+ logical = snapshot.map { logical_value(it) }
385
+ build_derived_from_logical(logical.sort_by { yield it }, snapshot, logical)
386
+ end
387
+
388
+ # Return the first count entries.
389
+ # @param count [Integer] The non-negative number of entries to take.
390
+ # @return [Vector] The resulting entries.
391
+ def take(count) = build_derived_vector(internal_vector.each.take(count))
392
+
393
+ # Return all entries after count entries.
394
+ # @param count [Integer] The non-negative number of entries to drop.
395
+ # @return [Vector] The resulting entries.
396
+ def drop(count) = build_derived_vector(internal_vector.each.drop(count))
397
+
398
+ # Return entries before the first rejected value.
399
+ # @yield [value] Test each entry. Returns an Enumerator without a block.
400
+ # @yieldparam value [BasicObject] The current value.
401
+ # @yieldreturn [BasicObject] A truthy value to continue retaining entries.
402
+ # @return [Vector, Enumerator]
403
+ def take_while
404
+ return enum_for(__method__) { size } unless block_given?
405
+ build_derived_vector(internal_vector.each.take_while { yield logical_value(it) })
406
+ end
407
+
408
+ # Drop entries before the first rejected value.
409
+ # @yield [value] Test each entry. Returns an Enumerator without a block.
410
+ # @yieldparam value [BasicObject] The current value.
411
+ # @yieldreturn [BasicObject] A truthy value to continue dropping entries.
412
+ # @return [Vector, Enumerator]
413
+ def drop_while
414
+ return enum_for(__method__) { size } unless block_given?
415
+ build_derived_vector(internal_vector.each.drop_while { yield logical_value(it) })
416
+ end
417
+
418
+ # Return a shuffled snapshot.
419
+ # @param random [#rand] The random number generator.
420
+ # @return [Vector] The shuffled entries.
421
+ def shuffle(random: Random) = build_derived_vector(internal_vector.snapshot.shuffle(random:))
422
+
423
+ # Return one sample, or a Vector when count is supplied.
424
+ # @param count [Integer] The maximum sample size. Omit to return one entry.
425
+ # @param random [#rand] The random number generator.
426
+ # @return [BasicObject, Vector, nil] One entry, nil if empty, or a Vector when count is supplied.
427
+ def sample(count = UNDEFINED, random: Random)
428
+ snapshot = internal_vector.snapshot
429
+ return logical_value(snapshot.sample(random:)) if count.equal?(UNDEFINED)
430
+ build_derived_vector(snapshot.sample(count, random:))
431
+ end
432
+
433
+ # Concatenate a snapshot with another sequence.
434
+ # @param other [Vector, #to_ary] The other sequence.
435
+ # @return [Vector] The resulting entries.
436
+ def +(other)
437
+ snapshot = internal_vector.snapshot
438
+ appended = if other.equal?(self)
439
+ snapshot
440
+ else
441
+ reusable_operand_snapshot(other) || vector_operand(other).map { derived_storage(it) }
442
+ end
443
+ build_derived_vector(snapshot + appended)
444
+ end
445
+
446
+ # Repeat a snapshot, or join it when a String separator is supplied.
447
+ # @param other [Integer, #to_str] The non-negative repetition count or String separator.
448
+ # @return [Vector, String] The repeated entries, or the joined String for a separator.
449
+ def *(other)
450
+ separator = String.try_convert(other)
451
+ return join(separator) if separator
452
+ build_derived_vector(internal_vector.snapshot * other)
453
+ end
454
+
455
+ # Remove values present in another sequence.
456
+ # @param other [Vector, #to_ary] The other sequence.
457
+ # @return [Vector] The resulting entries.
458
+ def -(other) = derive_array_operation(:-, other)
459
+
460
+ # Intersect with another sequence.
461
+ # @param other [Vector, #to_ary] The other sequence.
462
+ # @return [Vector] The resulting entries.
463
+ def &(other) = derive_array_operation(:&, other)
464
+
465
+ # Union with another sequence.
466
+ # @param other [Vector, #to_ary] The other sequence.
467
+ # @return [Vector] The resulting entries.
468
+ def |(other) = derive_array_operation(:|, other)
469
+
470
+ # Remove values present in any supplied sequence.
471
+ # @param others [Array<Vector, #to_ary>] The other sequences.
472
+ # @return [Vector] The resulting entries.
473
+ def difference(*others) = derive_array_operation(:difference, *others)
474
+
475
+ # Intersect with every supplied sequence.
476
+ # @param others [Array<Vector, #to_ary>] The other sequences.
477
+ # @return [Vector] The resulting entries.
478
+ def intersection(*others) = derive_array_operation(:intersection, *others)
479
+
480
+ # Union with every supplied sequence.
481
+ # @param others [Array<Vector, #to_ary>] The other sequences.
482
+ # @return [Vector] The resulting entries.
483
+ def union(*others) = derive_array_operation(:union, *others)
484
+
485
+ # Return whether another sequence shares any value.
486
+ # @param other [Vector, #to_ary] The other sequence.
487
+ # @return [Boolean] Whether the sequences have an entry in common.
488
+ def intersect?(other) = to_a.intersect?(vector_operand(other))
489
+
490
+ # Binary-search the live entries and return the matching value.
491
+ # The entries must remain sorted. Concurrent writes can change the result.
492
+ # @yield [value] Test an entry in an already sorted vector. Returns an Enumerator without a block.
493
+ # @yieldparam value [BasicObject] The entry being tested.
494
+ # @yieldreturn [Boolean, Numeric, nil] A monotonic predicate or comparison result, following Array's binary-search
495
+ # contract.
496
+ # @return [BasicObject, nil, Enumerator] The matching entry, nil if absent, or an Enumerator.
497
+ def bsearch
498
+ return enum_for(__method__) { size } unless block_given?
499
+
500
+ candidate = nil
501
+ index = (0...size).bsearch do |position|
502
+ value = self[position]
503
+ result = yield(value)
504
+ candidate = value if result.equal?(true) || (result.is_a?(Numeric) && result.zero?)
505
+ result
506
+ end
507
+ candidate if index
508
+ end
509
+
510
+ # Binary-search the live entries and return the matching index.
511
+ # The entries must remain sorted. Concurrent writes can change the result.
512
+ # @yield [value] Test an entry in an already sorted vector. Returns an Enumerator without a block.
513
+ # @yieldparam value [BasicObject] The entry being tested.
514
+ # @yieldreturn [Boolean, Numeric, nil] A monotonic predicate or comparison result, following Array's binary-search
515
+ # contract.
516
+ # @return [Integer, nil, Enumerator] The matching index, nil if absent, or an Enumerator.
517
+ def bsearch_index
518
+ return enum_for(__method__) { size } unless block_given?
519
+
520
+ (0...size).bsearch { yield self[it] }
521
+ end
522
+
523
+ # Pack a logical snapshot according to format.
524
+ # @overload pack(format, buffer: nil)
525
+ # @param format [String] The Array packing directives.
526
+ # @param buffer [String, nil] An optional String to append the packed bytes to.
527
+ # @return [String] The packed bytes, using buffer when supplied.
528
+ def pack(format, **) = to_a.pack(format, **)
529
+
530
+ # Select values matched by pattern, optionally transforming them.
531
+ # @param pattern [#===] The pattern used to test each entry.
532
+ # @yield [value] Optionally transform each selected entry.
533
+ # @yieldparam value [BasicObject] The selected entry.
534
+ # @yieldreturn [BasicObject] The replacement value.
535
+ # @return [Vector] The selected entries or their block results.
536
+ def grep(pattern, &)
537
+ snapshot = internal_vector.snapshot
538
+ logical = snapshot.map { logical_value(it) }
539
+ result = block_given? ? logical.grep(pattern, &) : logical.grep(pattern)
540
+ build_derived_from_logical(result, snapshot, logical)
541
+ end
542
+
543
+ # Select values not matched by pattern, optionally transforming them.
544
+ # @param pattern [#===] The pattern used to test each entry.
545
+ # @yield [value] Optionally transform each selected entry.
546
+ # @yieldparam value [BasicObject] The selected entry.
547
+ # @yieldreturn [BasicObject] The replacement value.
548
+ # @return [Vector] The selected entries or their block results.
549
+ def grep_v(pattern, &)
550
+ snapshot = internal_vector.snapshot
551
+ logical = snapshot.map { logical_value(it) }
552
+ result = block_given? ? logical.grep_v(pattern, &) : logical.grep_v(pattern)
553
+ build_derived_from_logical(result, snapshot, logical)
554
+ end
555
+
556
+ # Split live entries into accepted and rejected Vectors, wrapped in a Vector.
557
+ # @yield [value] Classify each entry. Returns an Enumerator without a block.
558
+ # @yieldparam value [BasicObject] The current value.
559
+ # @yieldreturn [BasicObject] A truthy value for the accepted group, or a falsy value for the rejected group.
560
+ # @return [Vector, Enumerator] A Vector containing the accepted and rejected Vectors, or an Enumerator.
561
+ def partition
562
+ return enum_for(__method__) { size } unless block_given?
563
+
564
+ accepted, rejected = internal_vector.each.partition { yield logical_value(it) }
565
+ build_derived_values([build_derived_vector(accepted), build_derived_vector(rejected)])
566
+ end
567
+
568
+ # Group live entries into same-kind Vectors.
569
+ # @yield [value] Compute a grouping key. Returns an Enumerator without a block.
570
+ # @yieldparam value [BasicObject] The current value.
571
+ # @yieldreturn [BasicObject] The key for the entry's group.
572
+ # @return [Hash{BasicObject => Vector}, Enumerator] Keys mapped to same-kind Vector groups, or an Enumerator.
573
+ def group_by
574
+ return enum_for(__method__) { size } unless block_given?
575
+
576
+ internal_vector.each.group_by { yield logical_value(it) }
577
+ .transform_values { build_derived_vector(it) }
578
+ end
579
+
580
+ # Return minimum and maximum in a Vector.
581
+ # @yield [left, right] Optionally compare two entries. Without a block, uses `<=>`.
582
+ # @yieldparam left [BasicObject] The left entry.
583
+ # @yieldparam right [BasicObject] The right entry.
584
+ # @yieldreturn [Numeric] A negative number, zero, or a positive number for less than, equal to, or greater than.
585
+ # @return [Vector] The minimum and maximum, with two nil entries for an empty vector.
586
+ def minmax(&)
587
+ snapshot = internal_vector.snapshot
588
+ logical = snapshot.map { logical_value(it) }
589
+ build_derived_from_logical(logical.minmax(&), snapshot, logical)
590
+ end
591
+
592
+ # Return one minimum, or a Vector when count is supplied.
593
+ # @param count [Integer, nil] The maximum result size. Omit or pass nil to return one entry.
594
+ # @yield [left, right] Optionally compare two entries. Without a block, uses `<=>`.
595
+ # @yieldparam left [BasicObject] The left entry.
596
+ # @yieldparam right [BasicObject] The right entry.
597
+ # @yieldreturn [Numeric] A negative number, zero, or a positive number for less than, equal to, or greater than.
598
+ # @return [BasicObject, Vector, nil] One extreme entry, nil if empty, or a Vector when count is supplied.
599
+ def min(count = UNDEFINED, &)
600
+ count = normalized_extreme_count(count)
601
+ return super(&) if count.nil?
602
+ return build_derived_vector([]) if count.zero?
603
+
604
+ snapshot = internal_vector.snapshot
605
+ logical = snapshot.map { logical_value(it) }
606
+ build_derived_from_logical(logical.min(count, &), snapshot, logical)
607
+ end
608
+
609
+ # Return one maximum, or a Vector when count is supplied.
610
+ # @param count [Integer, nil] The maximum result size. Omit or pass nil to return one entry.
611
+ # @yield [left, right] Optionally compare two entries. Without a block, uses `<=>`.
612
+ # @yieldparam left [BasicObject] The left entry.
613
+ # @yieldparam right [BasicObject] The right entry.
614
+ # @yieldreturn [Numeric] A negative number, zero, or a positive number for less than, equal to, or greater than.
615
+ # @return [BasicObject, Vector, nil] One extreme entry, nil if empty, or a Vector when count is supplied.
616
+ def max(count = UNDEFINED, &)
617
+ count = normalized_extreme_count(count)
618
+ return super(&) if count.nil?
619
+ return build_derived_vector([]) if count.zero?
620
+
621
+ snapshot = internal_vector.snapshot
622
+ logical = snapshot.map { logical_value(it) }
623
+ build_derived_from_logical(logical.max(count, &), snapshot, logical)
624
+ end
625
+
626
+ # Return one block minimum, or a Vector when count is supplied.
627
+ # @param count [Integer, nil] The maximum result size. Omit or pass nil to return one entry.
628
+ # @yield [value] Compute a comparison key. Returns an Enumerator without a block.
629
+ # @yieldparam value [BasicObject] The current value.
630
+ # @yieldreturn [BasicObject] The key used to order the entry.
631
+ # @return [BasicObject, Vector, nil, Enumerator] One extreme entry, nil if empty, a Vector for count, or an
632
+ # Enumerator.
633
+ def min_by(count = UNDEFINED)
634
+ count = normalized_extreme_count(count)
635
+ unless block_given?
636
+ return enum_for(__method__) { size } if count.nil? # rubocop:disable Lint/ToEnumArguments
637
+ return enum_for(__method__, count) { size }
638
+ end
639
+ return super() { yield it } if count.nil?
640
+ return build_derived_vector([]) if count.zero?
641
+
642
+ snapshot = internal_vector.snapshot
643
+ logical = snapshot.map { logical_value(it) }
644
+ build_derived_from_logical(logical.min_by(count) { yield it }, snapshot, logical)
645
+ end
646
+
647
+ # Return one block maximum, or a Vector when count is supplied.
648
+ # @param count [Integer, nil] The maximum result size. Omit or pass nil to return one entry.
649
+ # @yield [value] Compute a comparison key. Returns an Enumerator without a block.
650
+ # @yieldparam value [BasicObject] The current value.
651
+ # @yieldreturn [BasicObject] The key used to order the entry.
652
+ # @return [BasicObject, Vector, nil, Enumerator] One extreme entry, nil if empty, a Vector for count, or an
653
+ # Enumerator.
654
+ def max_by(count = UNDEFINED)
655
+ count = normalized_extreme_count(count)
656
+ unless block_given?
657
+ return enum_for(__method__) { size } if count.nil? # rubocop:disable Lint/ToEnumArguments
658
+ return enum_for(__method__, count) { size }
659
+ end
660
+ return super() { yield it } if count.nil?
661
+ return build_derived_vector([]) if count.zero?
662
+
663
+ snapshot = internal_vector.snapshot
664
+ logical = snapshot.map { logical_value(it) }
665
+ build_derived_from_logical(logical.max_by(count) { yield it }, snapshot, logical)
666
+ end
667
+
668
+ # Return the block minimum and maximum in a Vector.
669
+ # @yield [value] Compute a comparison key. Returns an Enumerator without a block.
670
+ # @yieldparam value [BasicObject] The current value.
671
+ # @yieldreturn [BasicObject] The key used to order the entry.
672
+ # @return [Vector, Enumerator] The minimum and maximum entries, two nil entries if empty, or an Enumerator.
673
+ def minmax_by
674
+ return enum_for(__method__) { size } unless block_given?
675
+
676
+ snapshot = internal_vector.snapshot
677
+ logical = snapshot.map { logical_value(it) }
678
+ build_derived_from_logical(logical.minmax_by { yield it }, snapshot, logical)
679
+ end
680
+
681
+ # Yield same-kind windows from live iteration.
682
+ # @param count [Integer] The positive window size.
683
+ # @yield [window] Visit each window. Returns an Enumerator without a block.
684
+ # @yieldparam window [Vector] The current window.
685
+ # @yieldreturn [void] The result is ignored.
686
+ # @return [self, Enumerator]
687
+ def each_slice(count)
688
+ count = convert_vector_count(count)
689
+ raise ArgumentError, "invalid slice size" unless count.positive?
690
+ return enum_for(__method__, count) { (size + count - 1) / count } unless block_given?
691
+
692
+ internal_vector.each.each_slice(count) { yield build_derived_vector(it) }
693
+ self
694
+ end
695
+
696
+ # Yield same-kind overlapping windows from live iteration.
697
+ # @param count [Integer] The positive window size.
698
+ # @yield [window] Visit each window. Returns an Enumerator without a block.
699
+ # @yieldparam window [Vector] The current window.
700
+ # @yieldreturn [void] The result is ignored.
701
+ # @return [self, Enumerator]
702
+ def each_cons(count)
703
+ count = convert_vector_count(count)
704
+ raise ArgumentError, "invalid size" unless count.positive?
705
+ return enum_for(__method__, count) { [size - count + 1, 0].max } unless block_given?
706
+
707
+ internal_vector.each.each_cons(count) { yield build_derived_vector(it) }
708
+ self
709
+ end
710
+
711
+ # Group adjacent entries by a block-generated key. Group contents are Vectors.
712
+ # @yield [value] Compute a grouping key for each entry.
713
+ # @yieldparam value [BasicObject] The current value.
714
+ # @yieldreturn [BasicObject] The grouping key. Nil and `:_separator` omit the entry. `:_alone` isolates it.
715
+ # @return [Enumerator] Yields keys and Vector groups. Without a block, enumerates the grouping operation.
716
+ def chunk(&block)
717
+ return enum_for(__method__) { size } unless block
718
+
719
+ Enumerator.new do |yielder|
720
+ snapshot = internal_vector.snapshot
721
+ snapshot.chunk { block.call(logical_value(it)) }.each do |key, group|
722
+ yielder.yield(key, build_derived_vector(group))
723
+ end
724
+ end
725
+ end
726
+
727
+ # Group adjacent entries while the block accepts each pair.
728
+ # @yield [left, right] Test consecutive entries. A block is required.
729
+ # @yieldparam left [BasicObject] The preceding entry.
730
+ # @yieldparam right [BasicObject] The current entry.
731
+ # @yieldreturn [BasicObject] A truthy value to keep the entries in one group.
732
+ # @return [Enumerator] Yields same-kind Vector groups.
733
+ def chunk_while(&block)
734
+ raise ArgumentError, "no block given" unless block
735
+
736
+ Enumerator.new do |yielder|
737
+ snapshot = internal_vector.snapshot
738
+ snapshot.chunk_while { |left, right| block.call(logical_value(left), logical_value(right)) }
739
+ .each { yielder << build_derived_vector(it) }
740
+ end
741
+ end
742
+
743
+ # Group a snapshot before matching entries.
744
+ # @param arguments [Array<BasicObject>] One pattern for `===` matching, or no arguments when using a block.
745
+ # @yield [value] Test each entry when no pattern is supplied.
746
+ # @yieldparam value [BasicObject] The current entry.
747
+ # @yieldreturn [BasicObject] A truthy value to split at this entry.
748
+ # @return [Enumerator] Yields same-kind Vector groups.
749
+ def slice_before(*arguments, &block)
750
+ logical_grouping_enumerator(:slice_before, arguments, block)
751
+ end
752
+
753
+ # Group a snapshot after matching entries.
754
+ # @param arguments [Array<BasicObject>] One pattern for `===` matching, or no arguments when using a block.
755
+ # @yield [value] Test each entry when no pattern is supplied.
756
+ # @yieldparam value [BasicObject] The current entry.
757
+ # @yieldreturn [BasicObject] A truthy value to split at this entry.
758
+ # @return [Enumerator] Yields same-kind Vector groups.
759
+ def slice_after(*arguments, &block)
760
+ logical_grouping_enumerator(:slice_after, arguments, block)
761
+ end
762
+
763
+ # Group a snapshot between pairs accepted by the block.
764
+ # @yield [left, right] Test consecutive entries. A block is required.
765
+ # @yieldparam left [BasicObject] The preceding entry.
766
+ # @yieldparam right [BasicObject] The current entry.
767
+ # @yieldreturn [BasicObject] A truthy value to start a new group.
768
+ # @return [Enumerator] Yields same-kind Vector groups.
769
+ def slice_when(&block)
770
+ raise ArgumentError, "no block given" unless block
771
+ logical_grouping_enumerator(:slice_when, [], block)
772
+ end
773
+
774
+ # Zip values into Vector rows. With a block, yield rows and return nil.
775
+ # @param others [Array<Enumerable, #to_ary>] The sequences to combine with this vector.
776
+ # @yield [row] Optionally visit each combined row.
777
+ # @yieldparam row [Vector] One entry from each sequence, padded with nil for shorter sequences.
778
+ # @yieldreturn [void] The result is ignored.
779
+ # @return [Vector, nil] A Vector of Vector rows, or nil when a block is supplied.
780
+ def zip(*others)
781
+ snapshot = internal_vector.snapshot
782
+ operands = others.map do |other|
783
+ stored = other.equal?(self) ? snapshot : reusable_operand_snapshot(other)
784
+ stored ? [stored, true] : [zip_operand(other, snapshot.length), false]
785
+ end
786
+ build_row = lambda do |stored, index|
787
+ row = [stored]
788
+ operands.each do |values, prepared|
789
+ row << (prepared ? values[index] : derived_storage(values[index]))
790
+ end
791
+ build_derived_vector(row)
792
+ end
793
+ if block_given?
794
+ snapshot.each_with_index { |stored, index| yield build_row.call(stored, index) }
795
+ nil
796
+ else
797
+ rows = snapshot.each_with_index.map { |stored, index| build_row.call(stored, index) }
798
+ build_derived_values(rows)
799
+ end
800
+ end
801
+
802
+ # Materialize enumeration as a Vector rather than an Array.
803
+ # @return [Vector] A new same-kind Vector containing the result.
804
+ def entries = build_derived_vector(internal_vector.snapshot)
805
+
806
+ # Read an index without waiting for atomic-update access.
807
+ # @param index [Integer] The index. Negative indexes count from the end.
808
+ # @return [BasicObject, nil] The value, or nil for an index outside the vector.
809
+ def [](index) = internal_vector[index]
810
+
811
+ # Store a value, growing the vector if necessary.
812
+ # @param index [Integer] The index. Negative indexes count from the end.
813
+ # @param value [BasicObject] The value to store.
814
+ # @return [BasicObject] The assigned value.
815
+ def []=(index, value)
816
+ internal_vector[index] = value
817
+ end
818
+
819
+ # Read an index after acquiring atomic-update access.
820
+ # @param index [Integer] The index. Negative indexes count from the end.
821
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
822
+ # @return [BasicObject, nil] The value, or nil if absent or timed out.
823
+ def get(index, timeout: nil) = internal_vector.get(index, timeout:)
824
+
825
+ # Store a value after acquiring atomic-update access.
826
+ # @param index [Integer] The index. Negative indexes count from the end.
827
+ # @param value [BasicObject] The value to store.
828
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
829
+ # @return [BasicObject, false] The value, or false on timeout.
830
+ def store(index, value, timeout: nil) = internal_vector.store(index, value, timeout:)
831
+
832
+ # Append a single value.
833
+ # @param value [BasicObject] The value to append.
834
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
835
+ # @return [self, false] Self on success, or false on timeout.
836
+ def push(value, timeout: nil)
837
+ internal_vector.push(value, timeout:) ? self : false
838
+ end
839
+
840
+ # Append snapshots of one or more sequences and return this vector.
841
+ # Each append is synchronized separately. Other writers may interleave.
842
+ # Values use the vector's default transfer mode. Self-concatenation reuses
843
+ # existing storage and captures the original contents only once.
844
+ # @param sources [Array<Vector, #to_ary>] sequences to append
845
+ # @return [self]
846
+ def concat(*sources)
847
+ Internal::Freeze.check(self)
848
+ own_snapshot = internal_vector.snapshot if sources.any? { it.equal?(self) }
849
+ snapshots = sources.map do |source|
850
+ if source.equal?(self)
851
+ own_snapshot
852
+ else
853
+ reusable_operand_snapshot(source) || vector_operand(source).map { derived_storage(it) }
854
+ end
855
+ end
856
+ snapshots.each { |values| values.each { internal_vector.push(it) } }
857
+ self
858
+ end
859
+
860
+ # Append a single value without a timeout.
861
+ # @param value [BasicObject] The value to append.
862
+ # @return [self]
863
+ def <<(value) = push(value)
864
+
865
+ # Append one value using the same options as {#push}.
866
+ # @overload append(value, timeout: nil)
867
+ # @param value [BasicObject] The value to append.
868
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
869
+ # @return [self, false] Self on success, or false on timeout.
870
+ def append(...) = push(...)
871
+
872
+ # Remove and return the last value.
873
+ # This does not wait for an empty vector to become nonempty.
874
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
875
+ # @return [BasicObject, nil] The last value, or nil if empty or timed out.
876
+ def pop(timeout: nil) = internal_vector.pop(timeout:)
877
+
878
+ # Replace an index and return its previous value, growing the vector if necessary.
879
+ # @param index [Integer] The index. Negative indexes count from the end.
880
+ # @param replacement [BasicObject] The new value.
881
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
882
+ # @return [BasicObject, nil] The previous value, or nil if absent or timed out.
883
+ def swap(index, replacement, timeout: nil) = internal_vector.swap(index, replacement, timeout:)
884
+
885
+ # Compute and store a value only when the index is absent or contains nil.
886
+ # @param index [Integer] The index. Negative indexes count from the end.
887
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
888
+ # @yield Called without arguments to compute a value when the slot is absent or nil.
889
+ # @yieldreturn [BasicObject] The value to store.
890
+ # @return [BasicObject, nil] The existing or computed value, or nil on timeout.
891
+ def store_if_absent(index, timeout: nil, &) = internal_vector.store_if_absent(index, timeout:, &)
892
+
893
+ # Replace an existing index only if its value matches the expected value.
894
+ # This never grows the vector. Matching uses the configured comparison mode.
895
+ # @param index [Integer] The index. Negative indexes count from the end.
896
+ # @param expected [BasicObject] The value that must match the current entry.
897
+ # @param replacement [BasicObject] The value to store on a match.
898
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
899
+ # @return [Boolean] Whether the replacement succeeded. False on timeout.
900
+ def compare_and_set(index, expected, replacement, timeout: nil)
901
+ internal_vector.compare_and_set(index, expected, replacement, timeout:)
902
+ end
903
+
904
+ # Atomically replace an index with the block result, growing the vector if necessary.
905
+ # @param index [Integer] The index. Negative indexes count from the end.
906
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
907
+ # @yield [value] Compute the replacement while holding atomic-update access.
908
+ # @yieldparam value [BasicObject, nil] The current value, or nil if absent.
909
+ # @yieldreturn [BasicObject] The replacement value.
910
+ # @return [BasicObject, nil] The replacement value, or nil on timeout.
911
+ def update(index, timeout: nil, &) = internal_vector.update(index, timeout:, &)
912
+
913
+ # Store initial for an absent or nil index, otherwise replace it with the block result.
914
+ # @param index [Integer] The index. Negative indexes count from the end.
915
+ # @param initial [BasicObject] The value to store when the slot is absent or nil.
916
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
917
+ # @yield [value] Compute a replacement for an existing non-nil entry.
918
+ # @yieldparam value [BasicObject] The current non-nil value.
919
+ # @yieldreturn [BasicObject] The replacement value.
920
+ # @return [BasicObject, nil] The stored value, or nil on timeout.
921
+ def upsert(index, initial, timeout: nil, &) = internal_vector.upsert(index, initial, timeout:, &)
922
+
923
+ # Wait until a block condition matches the value at an index.
924
+ # Absent indexes are observed as nil.
925
+ # One timeout budget covers all checks and waits. The block is not interrupted.
926
+ # @yieldparam value [BasicObject, nil] the current value
927
+ # @yieldreturn [Boolean] whether the value matches
928
+ # @param index [Integer] the index to observe. Negative indexes count from the end.
929
+ # @param timeout [Numeric, nil] the total seconds available
930
+ # @return [BasicObject, nil] the matching value, or nil on timeout
931
+ # @raise [LocalJumpError] if no block is given
932
+ def wait_until(index, timeout: nil, &) = Internal.wait_until(self, index, timeout:, &)
933
+
934
+ # Wait while the block returns a truthy value.
935
+ # @yieldparam value [BasicObject, nil] the current value
936
+ # @yieldreturn [BasicObject] a truthy value to keep waiting, or nil or false to stop
937
+ # @param index [Integer] the index to observe. Negative indexes count from the end.
938
+ # @param timeout [Numeric, nil] the total seconds available
939
+ # @return [BasicObject, nil] the value when the condition becomes false, or nil on timeout
940
+ # @raise [LocalJumpError] if no block is given
941
+ def wait_while(index, timeout: nil)
942
+ raise LocalJumpError, "no block given" unless block_given?
943
+ wait_until(index, timeout:) { |value| !yield(value) }
944
+ end
945
+
946
+ # Wait while `object === value` is true.
947
+ # @param object [#===] the pattern to stop matching
948
+ # @param index [Integer] the index to observe. Negative indexes count from the end.
949
+ # @param timeout [Numeric, nil] the total seconds available
950
+ # @return [BasicObject, nil] the first nonmatching value, or nil on timeout
951
+ def wait_while_match(index, object, timeout: nil)
952
+ wait_while(index, timeout:) { |value| object === value } # rubocop:disable Style/CaseEquality
953
+ end
954
+
955
+ # Wait until the current value equals an object using the configured comparison mode.
956
+ # @param object [BasicObject, nil] the value to compare with the current value
957
+ # @param index [Integer] the index to observe. Negative indexes count from the end.
958
+ # @param timeout [Numeric, nil] the total seconds available
959
+ # @return [BasicObject, nil] the matching value, or nil on timeout
960
+ def wait_until_value(index, object, timeout: nil)
961
+ wait_until(index, timeout:) { |value| compare_by_identity? ? object.equal?(value) : object == value }
962
+ end
963
+
964
+ # Wait until `object === value` is true.
965
+ # @param object [#===] the pattern to match
966
+ # @param index [Integer] the index to observe. Negative indexes count from the end.
967
+ # @param timeout [Numeric, nil] the total seconds available
968
+ # @return [BasicObject, nil] the matching value, or nil on timeout
969
+ def wait_until_match(index, object, timeout: nil)
970
+ wait_until(index, timeout:) { |value| object === value } # rubocop:disable Style/CaseEquality
971
+ end
972
+
973
+ # Wait until an index no longer matches expected. Absent indexes are observed as nil.
974
+ # @param index [Integer] The index. Negative indexes count from the end.
975
+ # @param expected [BasicObject] The value to wait for the entry to stop matching.
976
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
977
+ # @return [BasicObject, nil] The changed value, or nil on timeout.
978
+ def wait_until_changed(index, expected, timeout: nil)
979
+ internal_vector.wait_until_changed(index, expected, timeout:)
980
+ end
981
+
982
+ # (see #wait_until_changed)
983
+ def wait_while_value(...) = wait_until_changed(...)
984
+
985
+ # Wait until an index contains a non-nil value.
986
+ # @param index [Integer] The index. Negative indexes count from the end.
987
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
988
+ # @return [BasicObject, nil] The non-nil value, or nil on timeout.
989
+ def wait_until_non_nil(index, timeout: nil) = internal_vector.wait_until_non_nil(index, timeout:)
990
+
991
+ # @return [Integer] The number of slots, including nil slots.
992
+ def size = internal_vector.size
993
+
994
+ # @return [Boolean] Whether values are compared by identity.
995
+ def compare_by_identity? = internal_vector.compare_by_identity?
996
+
997
+ # @return [Boolean] Whether stored values must be Ractor-shareable.
998
+ def shareable_values? = false
999
+
1000
+ # Remove all slots.
1001
+ # @return [self]
1002
+ def clear
1003
+ internal_vector.clear
1004
+ self
1005
+ end
1006
+
1007
+ protected
1008
+
1009
+ def internal_vector = @vector
1010
+
1011
+ # Convert a stored value into the value visible through the public API.
1012
+ def logical_value(value) = value
1013
+
1014
+ # Build a new same-kind Vector from already prepared stored values.
1015
+ def build_derived_vector(values)
1016
+ self.class.new(values, compare_by_identity: compare_by_identity?)
1017
+ end
1018
+
1019
+ def reusable_operand_snapshot(other)
1020
+ return unless other.instance_of?(self.class)
1021
+ other.internal_vector.snapshot
1022
+ end
1023
+
1024
+ private
1025
+
1026
+ def each_for_inspect(&) = internal_vector.each(&)
1027
+
1028
+ def build_derived_values(values) = build_derived_vector(values.map { derived_storage(it) })
1029
+
1030
+ def build_derived_from_logical(values, source_storage, source_values)
1031
+ retained = {}.compare_by_identity
1032
+ source_values.each_with_index { |value, index| retained[value] ||= source_storage[index] }
1033
+ storage = values.map do |value|
1034
+ retained.fetch(value) { derived_storage(value) }
1035
+ end
1036
+ build_derived_vector(storage)
1037
+ end
1038
+
1039
+ def derived_storage(value) = value
1040
+
1041
+ def derive_array_operation(operation, *others)
1042
+ snapshot = internal_vector.snapshot
1043
+ logical = snapshot.map { logical_value(it) }
1044
+ result = logical.public_send(operation, *others.map { vector_operand(it) })
1045
+ build_derived_from_logical(result, snapshot, logical)
1046
+ end
1047
+
1048
+ def vector_operand(value)
1049
+ return value.to_a if value.is_a?(Vector)
1050
+ converted = Array.try_convert(value)
1051
+ return converted if converted
1052
+ raise TypeError, "no implicit conversion of #{value.class} into Array"
1053
+ end
1054
+
1055
+ def zip_operand(value, length)
1056
+ converted = Array.try_convert(value)
1057
+ return converted if converted
1058
+ raise TypeError, "wrong argument type #{value.class} (must respond to :each)" unless value.respond_to?(:each)
1059
+
1060
+ enumerator = value.to_enum
1061
+ Array.new(length) do
1062
+ enumerator.next
1063
+ rescue StopIteration
1064
+ nil
1065
+ end
1066
+ end
1067
+
1068
+ def normalize_hash_pair(value) = value.is_a?(Vector) ? value.to_a : value
1069
+
1070
+ def find_pair(expected, index)
1071
+ each do |value|
1072
+ pair = if value.is_a?(Vector)
1073
+ value
1074
+ else
1075
+ Array.try_convert(value)
1076
+ end
1077
+ return pair if pair && pair.length > index && array_value_equal?(pair[index], expected)
1078
+ end
1079
+ nil
1080
+ end
1081
+
1082
+ def normalized_extreme_count(count)
1083
+ return if count.equal?(UNDEFINED) || count.nil?
1084
+
1085
+ count = convert_vector_count(count)
1086
+ raise ArgumentError, "negative size (#{count})" if count.negative?
1087
+ count
1088
+ end
1089
+
1090
+ def array_value_equal?(left, right) = left.equal?(right) || left == right
1091
+
1092
+ def logical_grouping_enumerator(method, arguments, block)
1093
+ # Ask an empty Array to validate argument and block combinations now.
1094
+ [].public_send(method, *arguments, &block)
1095
+ Enumerator.new do |yielder|
1096
+ snapshot = internal_vector.snapshot
1097
+ logical = snapshot.map { logical_value(it) }
1098
+ logical.public_send(method, *arguments, &block).each do |group|
1099
+ yielder << build_derived_from_logical(group, snapshot, logical)
1100
+ end
1101
+ end
1102
+ end
1103
+
1104
+ def convert_vector_count(value)
1105
+ return value if value.is_a?(Integer)
1106
+ raise TypeError, "no implicit conversion of #{value.class} into Integer" unless value.respond_to?(:to_int)
1107
+ converted = value.to_int
1108
+ return converted if converted.is_a?(Integer)
1109
+ raise TypeError, "can't convert #{value.class} to Integer"
1110
+ end
1111
+
1112
+ alias convert_vector_index convert_vector_count
1113
+
1114
+ def initialize_copy(other)
1115
+ super
1116
+ source = other.internal_vector
1117
+ copy = source.class.new(source.snapshot, compare_by_identity: source.compare_by_identity?)
1118
+ if is_a?(Local::Scoped)
1119
+ Internal::Storage.scope(scope)[self] = copy
1120
+ else
1121
+ @vector = copy
1122
+ end
1123
+ end
1124
+ end
1125
+ end
1126
+ end