farce 0.0.1.alpha2-x86_64-linux-gnu

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 (423) 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/ext/ext_helper.rb +20 -0
  15. data/ext/farce/README.md +21 -0
  16. data/ext/farce/atom.c +1023 -0
  17. data/ext/farce/bounded_map.c +1683 -0
  18. data/ext/farce/containers.h +77 -0
  19. data/ext/farce/counter.c +399 -0
  20. data/ext/farce/darwin.c +100 -0
  21. data/ext/farce/depend +12 -0
  22. data/ext/farce/dict.c +1523 -0
  23. data/ext/farce/dict.h +152 -0
  24. data/ext/farce/drivers.c +237 -0
  25. data/ext/farce/exchanger.c +299 -0
  26. data/ext/farce/extconf.rb +99 -0
  27. data/ext/farce/farce.c +359 -0
  28. data/ext/farce/flag.c +288 -0
  29. data/ext/farce/io.c +338 -0
  30. data/ext/farce/lock.c +510 -0
  31. data/ext/farce/map.c +2240 -0
  32. data/ext/farce/priority_queue.c +2056 -0
  33. data/ext/farce/queue.c +1059 -0
  34. data/ext/farce/reactor.c +820 -0
  35. data/ext/farce/reactor.h +103 -0
  36. data/ext/farce/shareable.h +31 -0
  37. data/ext/farce/signal.c +350 -0
  38. data/ext/farce/transaction.c +354 -0
  39. data/ext/farce/transaction.h +40 -0
  40. data/ext/farce/tree_map.c +1953 -0
  41. data/ext/farce/trie.c +2020 -0
  42. data/ext/farce/unshareable.c +155 -0
  43. data/ext/farce/unshared_io_pool.h +234 -0
  44. data/ext/farce/unshared_signal.c +263 -0
  45. data/ext/farce/unshared_wait.h +193 -0
  46. data/ext/farce/unsupported.c +6 -0
  47. data/ext/farce/vector.c +1195 -0
  48. data/ext/farce/weak_map.c +1714 -0
  49. data/ext/java/org/farce/BoundedMap.java +394 -0
  50. data/ext/java/org/farce/FiberScheduler.java +141 -0
  51. data/ext/java/org/farce/PriorityKey.java +45 -0
  52. data/ext/java/org/farce/PriorityQueue.java +373 -0
  53. data/ext/java/org/farce/QueueSignal.java +28 -0
  54. data/ext/rebind/README.md +14 -0
  55. data/ext/rebind/extconf.rb +10 -0
  56. data/ext/rebind/rebind.c +186 -0
  57. data/lib/farce/_yard/internal.rb +13 -0
  58. data/lib/farce/_yard/macros.rb +61 -0
  59. data/lib/farce/_yard/ractor.rb +46 -0
  60. data/lib/farce/abstract/atom.rb +186 -0
  61. data/lib/farce/abstract/bounded_map.rb +232 -0
  62. data/lib/farce/abstract/collection.rb +151 -0
  63. data/lib/farce/abstract/concurrent_map.rb +381 -0
  64. data/lib/farce/abstract/counter.rb +193 -0
  65. data/lib/farce/abstract/duplicable_map.rb +229 -0
  66. data/lib/farce/abstract/exchanger.rb +26 -0
  67. data/lib/farce/abstract/flag.rb +71 -0
  68. data/lib/farce/abstract/lazy.rb +115 -0
  69. data/lib/farce/abstract/lease.rb +104 -0
  70. data/lib/farce/abstract/lease_map.rb +261 -0
  71. data/lib/farce/abstract/lease_pool.rb +91 -0
  72. data/lib/farce/abstract/lfu_map.rb +20 -0
  73. data/lib/farce/abstract/lru_map.rb +25 -0
  74. data/lib/farce/abstract/map.rb +345 -0
  75. data/lib/farce/abstract/molecule.rb +245 -0
  76. data/lib/farce/abstract/port.rb +74 -0
  77. data/lib/farce/abstract/priority_queue.rb +117 -0
  78. data/lib/farce/abstract/queue.rb +269 -0
  79. data/lib/farce/abstract/scheduler.rb +111 -0
  80. data/lib/farce/abstract/set.rb +910 -0
  81. data/lib/farce/abstract/sorted_set.rb +172 -0
  82. data/lib/farce/abstract/timer_queue.rb +136 -0
  83. data/lib/farce/abstract/tree_map.rb +269 -0
  84. data/lib/farce/abstract/value.rb +68 -0
  85. data/lib/farce/abstract/vector.rb +1126 -0
  86. data/lib/farce/abstract/weak_atom.rb +32 -0
  87. data/lib/farce/abstract/weak_key_map.rb +12 -0
  88. data/lib/farce/abstract/weak_map.rb +13 -0
  89. data/lib/farce/abstract/weak_set.rb +12 -0
  90. data/lib/farce/abstract/weak_value_map.rb +12 -0
  91. data/lib/farce/abstract.rb +17 -0
  92. data/lib/farce/atom.rb +293 -0
  93. data/lib/farce/class_mirror.rb +87 -0
  94. data/lib/farce/clock.rb +121 -0
  95. data/lib/farce/config.rb +229 -0
  96. data/lib/farce/counter.rb +71 -0
  97. data/lib/farce/deduper.rb +122 -0
  98. data/lib/farce/engine/jruby/bounded_map.rb +314 -0
  99. data/lib/farce/engine/jruby/fiber_scheduler.jar +0 -0
  100. data/lib/farce/engine/jruby/fiber_scheduler.rb +119 -0
  101. data/lib/farce/engine/jruby/lease_waiting.rb +19 -0
  102. data/lib/farce/engine/jruby/map.rb +505 -0
  103. data/lib/farce/engine/jruby/mutable_numeric_copy.rb +42 -0
  104. data/lib/farce/engine/jruby/signal.rb +147 -0
  105. data/lib/farce/engine/jruby.rb +63 -0
  106. data/lib/farce/engine/jvm/concurrent_weak_registry.rb +55 -0
  107. data/lib/farce/engine/jvm/counter.rb +102 -0
  108. data/lib/farce/engine/jvm/extension.rb +32 -0
  109. data/lib/farce/engine/jvm/farce.jar +0 -0
  110. data/lib/farce/engine/jvm/flag.rb +79 -0
  111. data/lib/farce/engine/jvm/priority_queue.rb +217 -0
  112. data/lib/farce/engine/jvm/tree_map.rb +350 -0
  113. data/lib/farce/engine/jvm/types.rb +180 -0
  114. data/lib/farce/engine/jvm.rb +19 -0
  115. data/lib/farce/engine/ruby/3.4/farce.so +0 -0
  116. data/lib/farce/engine/ruby/3.4/fiber_scheduler.rb +20 -0
  117. data/lib/farce/engine/ruby/3.4/port.rb +186 -0
  118. data/lib/farce/engine/ruby/3.4/ractor_methods.rb +26 -0
  119. data/lib/farce/engine/ruby/3.4/ractor_selector.rb +92 -0
  120. data/lib/farce/engine/ruby/3.4/rebind.so +0 -0
  121. data/lib/farce/engine/ruby/3.4/vault.rb +56 -0
  122. data/lib/farce/engine/ruby/4.0/farce.so +0 -0
  123. data/lib/farce/engine/ruby/4.0/port.rb +19 -0
  124. data/lib/farce/engine/ruby/4.0/ractor_methods.rb +20 -0
  125. data/lib/farce/engine/ruby/4.0/ractor_selector.rb +108 -0
  126. data/lib/farce/engine/ruby/4.0/rebind.so +0 -0
  127. data/lib/farce/engine/ruby/4.0/vault.rb +74 -0
  128. data/lib/farce/engine/ruby/4.1/port.rb +21 -0
  129. data/lib/farce/engine/ruby/4.1/ractor_methods.rb +22 -0
  130. data/lib/farce/engine/ruby/4.1/ractor_selector.rb +25 -0
  131. data/lib/farce/engine/ruby/4.1/vault.rb +5 -0
  132. data/lib/farce/engine/ruby/fiber_scheduler.rb +32 -0
  133. data/lib/farce/engine/ruby/key_lock_map.rb +28 -0
  134. data/lib/farce/engine/ruby/shared/lease.rb +26 -0
  135. data/lib/farce/engine/ruby/shared/lease_pool.rb +24 -0
  136. data/lib/farce/engine/ruby/shared/main_scheduler.rb +9 -0
  137. data/lib/farce/engine/ruby/shared/parallel_scheduler.rb +9 -0
  138. data/lib/farce/engine/ruby/shared/proxy_owner.rb +31 -0
  139. data/lib/farce/engine/ruby/shared/ractor_methods.rb +34 -0
  140. data/lib/farce/engine/ruby/shared/ractor_selector.rb +328 -0
  141. data/lib/farce/engine/ruby/shared/strict_map.rb +13 -0
  142. data/lib/farce/engine/ruby/shared/unshared_vector.rb +14 -0
  143. data/lib/farce/engine/ruby/shared/vault.rb +144 -0
  144. data/lib/farce/engine/ruby/shared/vault_weak_map.rb +336 -0
  145. data/lib/farce/engine/ruby/shared/weak_atom.rb +54 -0
  146. data/lib/farce/engine/ruby/shared/weak_map.rb +413 -0
  147. data/lib/farce/engine/ruby.rb +130 -0
  148. data/lib/farce/engine/shared/atom.rb +10 -0
  149. data/lib/farce/engine/shared/exchanger.rb +130 -0
  150. data/lib/farce/engine/shared/identity_key.rb +22 -0
  151. data/lib/farce/engine/shared/lease.rb +10 -0
  152. data/lib/farce/engine/shared/lease_pool.rb +10 -0
  153. data/lib/farce/engine/shared/main_scheduler.rb +20 -0
  154. data/lib/farce/engine/shared/map_key_coordination.rb +226 -0
  155. data/lib/farce/engine/shared/parallel_scheduler.rb +9 -0
  156. data/lib/farce/engine/shared/port.rb +44 -0
  157. data/lib/farce/engine/shared/portable_bounded_map.rb +619 -0
  158. data/lib/farce/engine/shared/proxy_owner.rb +43 -0
  159. data/lib/farce/engine/shared/queue.rb +233 -0
  160. data/lib/farce/engine/shared/ractor_methods.rb +73 -0
  161. data/lib/farce/engine/shared/rebindable.rb +15 -0
  162. data/lib/farce/engine/shared/strict_atom.rb +73 -0
  163. data/lib/farce/engine/shared/strict_map.rb +117 -0
  164. data/lib/farce/engine/shared/strict_queue_values.rb +27 -0
  165. data/lib/farce/engine/shared/strict_tree_map.rb +56 -0
  166. data/lib/farce/engine/shared/transaction_map_backend.rb +20 -0
  167. data/lib/farce/engine/shared/trie.rb +317 -0
  168. data/lib/farce/engine/shared/trie_builder.rb +199 -0
  169. data/lib/farce/engine/shared/unshareable.rb +14 -0
  170. data/lib/farce/engine/shared/unshared_atom.rb +256 -0
  171. data/lib/farce/engine/shared/unshared_priority_queue.rb +9 -0
  172. data/lib/farce/engine/shared/unshared_queue.rb +18 -0
  173. data/lib/farce/engine/shared/unshared_signal.rb +21 -0
  174. data/lib/farce/engine/shared/unshared_vector.rb +377 -0
  175. data/lib/farce/engine/shared/unshared_weak_atom.rb +30 -0
  176. data/lib/farce/engine/shared/unshared_weak_map.rb +445 -0
  177. data/lib/farce/engine/shared/vault.rb +31 -0
  178. data/lib/farce/engine/shared/vector.rb +83 -0
  179. data/lib/farce/engine/shared/weak_atom/base.rb +189 -0
  180. data/lib/farce/engine/shared/weak_atom.rb +20 -0
  181. data/lib/farce/engine/shared/weak_map/cell.rb +99 -0
  182. data/lib/farce/engine/shared/weak_map/index.rb +249 -0
  183. data/lib/farce/engine/shared/weak_map/lock.rb +80 -0
  184. data/lib/farce/engine/shared/weak_map/reference.rb +33 -0
  185. data/lib/farce/engine/shared.rb +63 -0
  186. data/lib/farce/engine/truffleruby/fiber_scheduler.rb +13 -0
  187. data/lib/farce/engine/truffleruby/lock.rb +121 -0
  188. data/lib/farce/engine/truffleruby/map.rb +656 -0
  189. data/lib/farce/engine/truffleruby/native/counter.rb +105 -0
  190. data/lib/farce/engine/truffleruby/native/flag.rb +77 -0
  191. data/lib/farce/engine/truffleruby/native/ordered_array_support.rb +67 -0
  192. data/lib/farce/engine/truffleruby/native/priority_queue.rb +388 -0
  193. data/lib/farce/engine/truffleruby/native/tree_map.rb +51 -0
  194. data/lib/farce/engine/truffleruby/native/unsafe_tree_map.rb +350 -0
  195. data/lib/farce/engine/truffleruby/signal.rb +77 -0
  196. data/lib/farce/engine/truffleruby.rb +148 -0
  197. data/lib/farce/envelope.rb +335 -0
  198. data/lib/farce/error.rb +35 -0
  199. data/lib/farce/exchanger.rb +41 -0
  200. data/lib/farce/flag.rb +27 -0
  201. data/lib/farce/integrations/active_support/blank.rb +68 -0
  202. data/lib/farce/integrations/active_support/clock.rb +17 -0
  203. data/lib/farce/integrations/active_support/duplicable.rb +78 -0
  204. data/lib/farce/integrations/active_support/map.rb +175 -0
  205. data/lib/farce/integrations/active_support/set.rb +60 -0
  206. data/lib/farce/integrations/active_support/value_serialization.rb +17 -0
  207. data/lib/farce/integrations/active_support/vector.rb +231 -0
  208. data/lib/farce/integrations/active_support.rb +9 -0
  209. data/lib/farce/integrations/activesupport.rb +5 -0
  210. data/lib/farce/integrations/bson.rb +108 -0
  211. data/lib/farce/integrations/cbor.rb +51 -0
  212. data/lib/farce/integrations/concurrent.rb +112 -0
  213. data/lib/farce/integrations/dry-types.rb +5 -0
  214. data/lib/farce/integrations/dry_types.rb +694 -0
  215. data/lib/farce/integrations/json.rb +7 -0
  216. data/lib/farce/integrations/msgpack.rb +112 -0
  217. data/lib/farce/integrations/oj.rb +69 -0
  218. data/lib/farce/integrations/psych.rb +191 -0
  219. data/lib/farce/integrations/ractor-sharing.rb +5 -0
  220. data/lib/farce/integrations/ractor-tmvar.rb +5 -0
  221. data/lib/farce/integrations/ractor_sharing.rb +172 -0
  222. data/lib/farce/integrations/ractor_tmvar.rb +64 -0
  223. data/lib/farce/integrations/shared/to_json.rb +42 -0
  224. data/lib/farce/integrations/sorted_set.rb +11 -0
  225. data/lib/farce/integrations/weakref.rb +38 -0
  226. data/lib/farce/integrations/yajl.rb +10 -0
  227. data/lib/farce/integrations.rb +156 -0
  228. data/lib/farce/internal/_frozen_config.rb +11 -0
  229. data/lib/farce/internal/autoloads.rb +47 -0
  230. data/lib/farce/internal/blocking_priority_queue.rb +122 -0
  231. data/lib/farce/internal/converter.rb +106 -0
  232. data/lib/farce/internal/copyable.rb +31 -0
  233. data/lib/farce/internal/delegation.rb +20 -0
  234. data/lib/farce/internal/external_transaction.rb +59 -0
  235. data/lib/farce/internal/fake_ractor.rb +179 -0
  236. data/lib/farce/internal/freeze.rb +118 -0
  237. data/lib/farce/internal/inspect.rb +157 -0
  238. data/lib/farce/internal/key_lock_map.rb +29 -0
  239. data/lib/farce/internal/key_normalizer.rb +289 -0
  240. data/lib/farce/internal/lease_initialization.rb +115 -0
  241. data/lib/farce/internal/lease_map.rb +441 -0
  242. data/lib/farce/internal/lease_pool_state.rb +228 -0
  243. data/lib/farce/internal/lease_state.rb +342 -0
  244. data/lib/farce/internal/lease_waiting.rb +13 -0
  245. data/lib/farce/internal/managed_queue.rb +26 -0
  246. data/lib/farce/internal/map_value_modes.rb +227 -0
  247. data/lib/farce/internal/marshal_support.rb +227 -0
  248. data/lib/farce/internal/mixin.rb +20 -0
  249. data/lib/farce/internal/mutable_ordered_key_lock_map.rb +63 -0
  250. data/lib/farce/internal/noncopyable.rb +17 -0
  251. data/lib/farce/internal/ordered_key_lock_map.rb +69 -0
  252. data/lib/farce/internal/pool_supervisor.rb +41 -0
  253. data/lib/farce/internal/pool_worker.rb +61 -0
  254. data/lib/farce/internal/portable_transaction/reservation_entry.rb +29 -0
  255. data/lib/farce/internal/portable_transaction/strong_map_entry.rb +137 -0
  256. data/lib/farce/internal/portable_transaction/strong_map_size_entry.rb +44 -0
  257. data/lib/farce/internal/portable_transaction/tree_entry.rb +64 -0
  258. data/lib/farce/internal/portable_transaction.rb +164 -0
  259. data/lib/farce/internal/proxy_owner_notifications.rb +29 -0
  260. data/lib/farce/internal/reservation_waiting.rb +24 -0
  261. data/lib/farce/internal/scheduled_task.rb +48 -0
  262. data/lib/farce/internal/scheduler_io.rb +171 -0
  263. data/lib/farce/internal/scheduler_lifecycle.rb +314 -0
  264. data/lib/farce/internal/select_scheduler.rb +235 -0
  265. data/lib/farce/internal/storage.rb +162 -0
  266. data/lib/farce/internal/strict_lease.rb +30 -0
  267. data/lib/farce/internal/strict_lease_map.rb +20 -0
  268. data/lib/farce/internal/strict_lease_pool.rb +29 -0
  269. data/lib/farce/internal/thread_pool.rb +166 -0
  270. data/lib/farce/internal/transaction_conflict.rb +9 -0
  271. data/lib/farce/internal/transaction_freeze_guard.rb +30 -0
  272. data/lib/farce/internal/transaction_map_snapshot.rb +123 -0
  273. data/lib/farce/internal/undefined.rb +22 -0
  274. data/lib/farce/internal/unshared_lease.rb +29 -0
  275. data/lib/farce/internal/unshared_lease_pool.rb +34 -0
  276. data/lib/farce/internal/unshared_queue_waiting.rb +28 -0
  277. data/lib/farce/internal/value_serialization.rb +13 -0
  278. data/lib/farce/internal/weak_map_value_modes.rb +58 -0
  279. data/lib/farce/internal/weak_mode_manager.rb +26 -0
  280. data/lib/farce/internal.rb +129 -0
  281. data/lib/farce/lazy.rb +100 -0
  282. data/lib/farce/lazy_ref.rb +40 -0
  283. data/lib/farce/lease.rb +28 -0
  284. data/lib/farce/lease_map.rb +34 -0
  285. data/lib/farce/lease_pool.rb +29 -0
  286. data/lib/farce/lfu_map.rb +53 -0
  287. data/lib/farce/local/atom.rb +23 -0
  288. data/lib/farce/local/counter.rb +88 -0
  289. data/lib/farce/local/flag.rb +65 -0
  290. data/lib/farce/local/lazy.rb +38 -0
  291. data/lib/farce/local/lazy_ref.rb +36 -0
  292. data/lib/farce/local/lease.rb +77 -0
  293. data/lib/farce/local/lease_map.rb +80 -0
  294. data/lib/farce/local/lease_pool.rb +38 -0
  295. data/lib/farce/local/lfu_map.rb +55 -0
  296. data/lib/farce/local/lru_map.rb +62 -0
  297. data/lib/farce/local/map.rb +47 -0
  298. data/lib/farce/local/molecule.rb +45 -0
  299. data/lib/farce/local/priority_queue.rb +53 -0
  300. data/lib/farce/local/queue.rb +32 -0
  301. data/lib/farce/local/scoped.rb +166 -0
  302. data/lib/farce/local/set.rb +18 -0
  303. data/lib/farce/local/sorted_set.rb +50 -0
  304. data/lib/farce/local/timer_queue.rb +41 -0
  305. data/lib/farce/local/tree_map.rb +47 -0
  306. data/lib/farce/local/vector.rb +30 -0
  307. data/lib/farce/local/weak_atom.rb +23 -0
  308. data/lib/farce/local/weak_key_map.rb +39 -0
  309. data/lib/farce/local/weak_map.rb +39 -0
  310. data/lib/farce/local/weak_set.rb +18 -0
  311. data/lib/farce/local/weak_value_map.rb +39 -0
  312. data/lib/farce/local.rb +35 -0
  313. data/lib/farce/lock.rb +54 -0
  314. data/lib/farce/lru_map.rb +63 -0
  315. data/lib/farce/map.rb +58 -0
  316. data/lib/farce/mode_manager.rb +142 -0
  317. data/lib/farce/molecule.rb +60 -0
  318. data/lib/farce/mutable.rb +171 -0
  319. data/lib/farce/pool.rb +332 -0
  320. data/lib/farce/port.rb +134 -0
  321. data/lib/farce/priority_queue.rb +70 -0
  322. data/lib/farce/proxy/register.rb +101 -0
  323. data/lib/farce/proxy/supervisor.rb +137 -0
  324. data/lib/farce/proxy/wrapper.rb +49 -0
  325. data/lib/farce/proxy.rb +291 -0
  326. data/lib/farce/queue.rb +60 -0
  327. data/lib/farce/ractor.rb +269 -0
  328. data/lib/farce/read_write_lock.rb +256 -0
  329. data/lib/farce/reference.rb +158 -0
  330. data/lib/farce/resolv/dns.rb +42 -0
  331. data/lib/farce/resolv.rb +85 -0
  332. data/lib/farce/scheduler.rb +536 -0
  333. data/lib/farce/set.rb +39 -0
  334. data/lib/farce/shareable.rb +150 -0
  335. data/lib/farce/signal.rb +97 -0
  336. data/lib/farce/sorted_set.rb +36 -0
  337. data/lib/farce/strict/atom.rb +34 -0
  338. data/lib/farce/strict/counter.rb +10 -0
  339. data/lib/farce/strict/exchanger.rb +25 -0
  340. data/lib/farce/strict/flag.rb +10 -0
  341. data/lib/farce/strict/lazy.rb +26 -0
  342. data/lib/farce/strict/lazy_ref.rb +26 -0
  343. data/lib/farce/strict/lease.rb +27 -0
  344. data/lib/farce/strict/lease_map.rb +33 -0
  345. data/lib/farce/strict/lease_pool.rb +28 -0
  346. data/lib/farce/strict/lfu_map.rb +27 -0
  347. data/lib/farce/strict/lru_map.rb +28 -0
  348. data/lib/farce/strict/map.rb +54 -0
  349. data/lib/farce/strict/molecule.rb +16 -0
  350. data/lib/farce/strict/port.rb +40 -0
  351. data/lib/farce/strict/priority_queue.rb +20 -0
  352. data/lib/farce/strict/queue.rb +17 -0
  353. data/lib/farce/strict/set.rb +14 -0
  354. data/lib/farce/strict/sorted_set.rb +19 -0
  355. data/lib/farce/strict/timer_queue.rb +13 -0
  356. data/lib/farce/strict/tree_map.rb +27 -0
  357. data/lib/farce/strict/vector.rb +24 -0
  358. data/lib/farce/strict/weak_atom.rb +31 -0
  359. data/lib/farce/strict/weak_key_map.rb +49 -0
  360. data/lib/farce/strict/weak_map.rb +49 -0
  361. data/lib/farce/strict/weak_set.rb +14 -0
  362. data/lib/farce/strict/weak_value_map.rb +48 -0
  363. data/lib/farce/strict.rb +28 -0
  364. data/lib/farce/system.rb +40 -0
  365. data/lib/farce/thread_scheduler.rb +70 -0
  366. data/lib/farce/timer_queue.rb +66 -0
  367. data/lib/farce/transaction/atom.rb +73 -0
  368. data/lib/farce/transaction/map.rb +25 -0
  369. data/lib/farce/transaction/map_operations.rb +143 -0
  370. data/lib/farce/transaction/molecule.rb +90 -0
  371. data/lib/farce/transaction/mutable.rb +61 -0
  372. data/lib/farce/transaction/set.rb +17 -0
  373. data/lib/farce/transaction/set_operations.rb +48 -0
  374. data/lib/farce/transaction/sorted_set.rb +18 -0
  375. data/lib/farce/transaction/tree_map.rb +78 -0
  376. data/lib/farce/transaction/vector.rb +139 -0
  377. data/lib/farce/transaction/wrapper.rb +202 -0
  378. data/lib/farce/transaction.rb +343 -0
  379. data/lib/farce/tree_map.rb +56 -0
  380. data/lib/farce/unsafe/lfu_map.rb +36 -0
  381. data/lib/farce/unsafe/lru_map.rb +36 -0
  382. data/lib/farce/unsafe/tree_map.rb +21 -0
  383. data/lib/farce/unsafe.rb +29 -0
  384. data/lib/farce/unshareable.rb +67 -0
  385. data/lib/farce/unshared/atom.rb +24 -0
  386. data/lib/farce/unshared/counter.rb +10 -0
  387. data/lib/farce/unshared/flag.rb +10 -0
  388. data/lib/farce/unshared/lazy.rb +38 -0
  389. data/lib/farce/unshared/lazy_ref.rb +26 -0
  390. data/lib/farce/unshared/lease.rb +27 -0
  391. data/lib/farce/unshared/lease_map.rb +26 -0
  392. data/lib/farce/unshared/lease_pool.rb +25 -0
  393. data/lib/farce/unshared/lfu_map.rb +20 -0
  394. data/lib/farce/unshared/lru_map.rb +20 -0
  395. data/lib/farce/unshared/map.rb +49 -0
  396. data/lib/farce/unshared/molecule.rb +16 -0
  397. data/lib/farce/unshared/priority_queue.rb +16 -0
  398. data/lib/farce/unshared/queue.rb +27 -0
  399. data/lib/farce/unshared/set.rb +14 -0
  400. data/lib/farce/unshared/sorted_set.rb +28 -0
  401. data/lib/farce/unshared/timer_queue.rb +16 -0
  402. data/lib/farce/unshared/tree_map.rb +21 -0
  403. data/lib/farce/unshared/vector.rb +19 -0
  404. data/lib/farce/unshared/weak_atom.rb +31 -0
  405. data/lib/farce/unshared/weak_key_map.rb +44 -0
  406. data/lib/farce/unshared/weak_map.rb +44 -0
  407. data/lib/farce/unshared/weak_set.rb +14 -0
  408. data/lib/farce/unshared/weak_value_map.rb +43 -0
  409. data/lib/farce/unshared.rb +28 -0
  410. data/lib/farce/vector.rb +228 -0
  411. data/lib/farce/version.rb +8 -0
  412. data/lib/farce/walker/definitions.rb +186 -0
  413. data/lib/farce/walker/modification.rb +355 -0
  414. data/lib/farce/walker.rb +319 -0
  415. data/lib/farce/weak_atom.rb +121 -0
  416. data/lib/farce/weak_key_map.rb +31 -0
  417. data/lib/farce/weak_map.rb +33 -0
  418. data/lib/farce/weak_ref.rb +67 -0
  419. data/lib/farce/weak_set.rb +82 -0
  420. data/lib/farce/weak_value.rb +195 -0
  421. data/lib/farce/weak_value_map.rb +32 -0
  422. data/lib/farce.rb +519 -0
  423. metadata +468 -0
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ # @!visibility private
7
+ module Internal # :nodoc: all
8
+ class Vault
9
+ class Manager
10
+ def initialize
11
+ @data = ObjectSpace::WeakKeyMap.new
12
+ @weak_maps = ObjectSpace::WeakKeyMap.new
13
+ @weak_atoms = ObjectSpace::WeakKeyMap.new
14
+ end
15
+
16
+ def run = (run_once while true)
17
+
18
+ def move(key, _value, port)
19
+ respond(port, [true, @data.delete(key)].freeze, move: true)
20
+ end
21
+
22
+ def copy(key, _value, port)
23
+ respond(port, [true, @data[key]].freeze, move: false)
24
+ end
25
+
26
+ def same_value(key, value, port)
27
+ right, identity, right_stored = value
28
+ left = @data[key]
29
+ right = @data[right] if right_stored
30
+ result = identity ?
31
+ BasicObject.instance_method(:equal?).bind_call(left, right) :
32
+ !!(left == right) # rubocop:disable Style/DoubleNegation
33
+ respond(port, [true, result].freeze)
34
+ end
35
+
36
+ def delete(key, _value, port)
37
+ @data.delete(key)
38
+ respond(port, true)
39
+ end
40
+
41
+ def set(key, value, port)
42
+ @data[key] = value
43
+ respond(port, true)
44
+ end
45
+
46
+ def weak_atom(key, value, port)
47
+ command, *arguments = value
48
+ if command == :create
49
+ @weak_atoms[key] = VaultWeakAtomSlot.new(*arguments)
50
+ return respond(port, [true, nil].freeze)
51
+ end
52
+ slot = @weak_atoms[key]
53
+ raise ArgumentError, "unknown weak atom" unless slot
54
+ result = case command
55
+ when :read then slot.value
56
+ when :store then slot.store(arguments.first)
57
+ else raise ArgumentError, "unknown weak-atom action: #{command.inspect}"
58
+ end
59
+ respond(port, [true, result].freeze)
60
+ end
61
+
62
+ def weak_map(key, value, port)
63
+ command, *arguments = value
64
+ if command == :create
65
+ options = arguments.first
66
+ @weak_maps[key] = VaultWeakMapState.new(**options)
67
+ return respond(port, [true, [:ok].freeze].freeze)
68
+ end
69
+ map = @weak_maps[key]
70
+ raise ArgumentError, "unknown weak map" unless map
71
+ respond(port, [true, map.dispatch(command, *arguments)].freeze)
72
+ end
73
+
74
+ private
75
+
76
+ def run_once
77
+ request = receive_request
78
+ action, key, value, port = request
79
+ # Ractor.receive can retain its last result while waiting for another
80
+ # message. Clear the copied request shell before it becomes idle.
81
+ request.clear unless request.frozen?
82
+ public_send(action, key, value, port)
83
+ rescue StandardError => e
84
+ begin
85
+ respond_error(port, e)
86
+ rescue StandardError => e
87
+ warn "Vault error: #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
88
+ end
89
+ end
90
+
91
+ def respond_error(port, error)
92
+ payload = if port.is_a?(Atom)
93
+ [error.class, error.message.freeze, error.backtrace&.map(&:freeze)&.freeze].freeze
94
+ else
95
+ error
96
+ end
97
+ respond(port, [false, payload].freeze)
98
+ rescue StandardError
99
+ # Preserve diagnostics when the exception or its cause cannot cross Ractors.
100
+ remote = ::Ractor::RemoteError.new("#{error.class}: #{error.message}")
101
+ remote.instance_variable_set(:@ractor, ::Ractor.current)
102
+ remote.set_backtrace(error.backtrace&.map { |line| String.new(line) })
103
+ respond(port, ::Ractor.make_shareable([false, remote].freeze))
104
+ end
105
+ end
106
+
107
+ def move_in(key, value) = execute(:set, key, value, move: true)
108
+ def copy_in(key, value) = execute(:set, key, value, move: false)
109
+ def move_out(key) = execute(:move, key)
110
+ def copy_out(key) = execute(:copy, key)
111
+
112
+ def same_value?(left, right, identity: false, right_stored: true)
113
+ execute(:same_value, left, [right, identity, right_stored].freeze)
114
+ end
115
+
116
+ def delete(key) = execute(:delete, key)
117
+
118
+ def weak_map(key, action, *) = shared_request(:weak_map, key, action, *)
119
+ def weak_atom(key, action, *) = shared_request(:weak_atom, key, action, *)
120
+
121
+ private
122
+
123
+ def shared_request(kind, key, action, *arguments)
124
+ raise ThreadError, "deadlock; recursive access from the Vault Ractor" if ::Ractor.current.equal?(@ractor)
125
+ raise Ractor::IsolationError, "key must be shareable" unless ::Ractor.shareable?(key)
126
+
127
+ pending = Object.new.freeze
128
+ reply = Atom.new(pending, compare_by_identity: true)
129
+ @ractor.send([kind, key, [action, *arguments].freeze, reply])
130
+ success, payload = reply.wait_until_changed(pending)
131
+ return payload if success
132
+
133
+ raise payload if payload.is_a?(Exception)
134
+
135
+ error_class, message, backtrace = payload
136
+ error_class = RuntimeError unless error_class.is_a?(Class) && error_class <= StandardError
137
+ error = error_class.allocate
138
+ Exception.instance_method(:initialize).bind_call(error, message)
139
+ error.set_backtrace(backtrace) if backtrace
140
+ raise error
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,336 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ require "farce/engine/shared/unshared_weak_map"
6
+
7
+ module Farce
8
+ # @!visibility private
9
+ module Internal # :nodoc: all
10
+ # A map entry owned by the Vault Ractor. Its change counter is the only
11
+ # part used directly by callers in other Ractors.
12
+ class VaultWeakMapCell
13
+ attr_reader :token
14
+
15
+ def initialize(key_reference, weak_values:)
16
+ @token = Object.new
17
+ @key = key_reference
18
+ @weak_values = weak_values
19
+ @value = nil
20
+ @present = @retired = false
21
+ @claim = nil
22
+ @changes = Atom.new(0)
23
+ end
24
+
25
+ def read(retain_key: false)
26
+ return [:retired] if @retired
27
+ return busy if @claim
28
+ alive, key = @key.read
29
+ return [:dead] unless alive
30
+ unless @present
31
+ state = [:ok, false, nil, @changes, @changes.value]
32
+ state << key if retain_key
33
+ return state
34
+ end
35
+
36
+ alive, value = read_value
37
+ return [:dead] unless alive
38
+
39
+ state = [:ok, true, value, @changes, @changes.value]
40
+ state << key if retain_key
41
+ state
42
+ end
43
+
44
+ def claim(ticket)
45
+ current = read(retain_key: true)
46
+ return current unless current.first == :ok
47
+
48
+ @claim = ticket
49
+ current[0] = :claimed
50
+ current.freeze
51
+ end
52
+
53
+ def finish(ticket, action, value = nil)
54
+ return [:stale] unless @claim.equal?(ticket)
55
+
56
+ remove = false
57
+ if action == :store && @key.read.first
58
+ write_value(value)
59
+ @present = true
60
+ elsif action == :delete || (action == :abort && !@present)
61
+ remove = true
62
+ retire
63
+ end
64
+ @claim = nil
65
+ changed unless @retired
66
+ [remove ? :remove : :ok, @changes, @changes.value].freeze
67
+ end
68
+
69
+ def store(value)
70
+ return if @retired || @claim || !@key.read.first
71
+
72
+ write_value(value)
73
+ @present = true
74
+ changed
75
+ end
76
+
77
+ def delete
78
+ state = read
79
+ return state if state.first == :busy
80
+ return [:missing] unless state.first == :ok && state[1]
81
+
82
+ value = state[2]
83
+ retire
84
+ [:ok, value].freeze
85
+ end
86
+
87
+ def lookup_key
88
+ return [false, nil] if @retired
89
+ alive, key = @key.read
90
+ return [false, nil] unless alive
91
+ return [true, key] if @claim || !@present
92
+
93
+ [read_value.first, key]
94
+ end
95
+
96
+ def retired? = @retired
97
+ def release; end
98
+
99
+ def retire
100
+ return if @retired
101
+
102
+ @retired = true
103
+ @present = false
104
+ @claim = @key = @value = nil
105
+ changed
106
+ end
107
+
108
+ def retire_if_dead
109
+ return [false, false, nil] if @retired || @claim
110
+
111
+ alive, key = @key.read
112
+ return [false, false, nil] if alive && (!@present || read_value.first)
113
+
114
+ retire
115
+ [true, alive, key]
116
+ end
117
+
118
+ private
119
+
120
+ def busy = [:busy, @changes, @changes.value].freeze
121
+
122
+ def changed = @changes.update { |generation| generation + 1 }
123
+
124
+ def read_value
125
+ return [true, @value] unless @weak_values
126
+ @value.read
127
+ end
128
+
129
+ def write_value(value)
130
+ @value = @weak_values ? UnsharedWeakMapWeakReference.for(value) : value
131
+ end
132
+ end
133
+ private_constant :VaultWeakMapCell
134
+
135
+ # Owner-side state for one fallback weak map. It does not retain the token
136
+ # used by the Vault registry.
137
+ class VaultWeakMapState
138
+ def initialize(weak_keys:, weak_values:, compare_keys_by_identity:)
139
+ @weak_values = weak_values
140
+ @changes = Atom.new(0)
141
+ @claims = {}.compare_by_identity
142
+ @live_cursors = {}.compare_by_identity
143
+ index_class =
144
+ if weak_keys
145
+ compare_keys_by_identity ? UnsharedWeakIdentityMapIndex : UnsharedWeakKeyMapIndex
146
+ else
147
+ compare_keys_by_identity ? UnsharedStrongIdentityMapIndex : UnsharedStrongKeyMapIndex
148
+ end
149
+ @index = index_class.new
150
+ end
151
+
152
+ def dispatch(action, *arguments)
153
+ case action
154
+ when :read then read(arguments.first, retain_key: false)
155
+ when :wait_read then read(arguments.first, retain_key: true)
156
+ when :getkey then getkey(arguments.first)
157
+ when :claim then claim(*arguments)
158
+ when :finish then finish(*arguments)
159
+ when :store then store(*arguments)
160
+ when :delete then delete(arguments.first)
161
+ when :size then size
162
+ when :snapshot then snapshot
163
+ when :open_cursor then open_cursor
164
+ when :next_live then next_live(arguments.first)
165
+ when :close_cursor then close_cursor(arguments.first)
166
+ when :clear then clear
167
+ else raise ArgumentError, "unknown weak-map action: #{action.inspect}"
168
+ end
169
+ end
170
+
171
+ private
172
+
173
+ def read(key, retain_key:)
174
+ with_entry(key) do |entry|
175
+ next missing unless entry
176
+
177
+ entry.read(retain_key:)
178
+ end
179
+ end
180
+
181
+ def getkey(key)
182
+ with_entry(key) do |entry|
183
+ next missing unless entry
184
+
185
+ state = entry.read
186
+ next state unless state.first == :ok && state[1]
187
+
188
+ alive, stored_key = entry.lookup_key
189
+ alive ? [:ok, stored_key].freeze : [:dead]
190
+ end
191
+ end
192
+
193
+ def claim(key, ticket, create)
194
+ with_entry(key, create:) do |entry|
195
+ next missing unless entry
196
+
197
+ result = entry.claim(ticket)
198
+ next result unless result.first == :claimed
199
+
200
+ # Retain the canonical key through the callback without placing it in
201
+ # the reply, which can outlive a completed operation.
202
+ @claims[ticket] = [entry, result[5]]
203
+ result.first(5).freeze
204
+ end
205
+ end
206
+
207
+ def finish(_key, ticket, action, value = nil)
208
+ claim = @claims.delete(ticket)
209
+ return [:stale].freeze unless claim
210
+
211
+ entry, key = claim
212
+ result = entry.finish(ticket, action, value)
213
+ remove(key, entry) if result.first == :remove
214
+ result
215
+ end
216
+
217
+ def store(key, value, swap)
218
+ with_entry(key, create: true) do |entry|
219
+ state = entry.read
220
+ next state if state.first == :busy
221
+
222
+ present, current = state[1], state[2]
223
+ entry.store(value)
224
+ [:ok, swap && present ? current : nil].freeze
225
+ end
226
+ end
227
+
228
+ def delete(key)
229
+ with_entry(key) do |entry|
230
+ next [:missing] unless entry
231
+
232
+ result = entry.delete
233
+ remove(key, entry) if result.first == :ok
234
+ result
235
+ end
236
+ end
237
+
238
+ # Count in the owner Ractor so size replies do not keep weak entries alive.
239
+ def size
240
+ entries = @index.snapshot
241
+ count = 0
242
+ entries.each do |entry|
243
+ state = entry.read
244
+ return state if state.first == :busy
245
+ count += 1 if state.first == :ok && state[1]
246
+ end
247
+ @index.sweep(entries)
248
+ [:ok, count].freeze
249
+ end
250
+
251
+ def open_cursor
252
+ token = Object.new.freeze
253
+ @live_cursors[token] = [@index.live_cursor, nil]
254
+ [:ok, token].freeze
255
+ end
256
+
257
+ def next_live(token)
258
+ cursor = @live_cursors.fetch(token)
259
+ while true
260
+ begin
261
+ entry = cursor[1] ||= @index.next_live(cursor[0])
262
+ rescue StopIteration
263
+ return [:done].freeze
264
+ end
265
+ state = entry.read
266
+ return state if state.first == :busy
267
+ cursor[1] = nil
268
+ next unless state.first == :ok && state[1]
269
+ alive, key = entry.lookup_key
270
+ return [:ok, key, state[2]].freeze if alive
271
+ end
272
+ end
273
+
274
+ def close_cursor(token)
275
+ cursor = @live_cursors.delete(token)
276
+ @index.close_cursor(cursor[0]) if cursor
277
+ [:ok].freeze
278
+ end
279
+
280
+ def snapshot
281
+ entries = @index.snapshot
282
+ pairs = []
283
+ entries.each do |entry|
284
+ state = entry.read
285
+ return state if state.first == :busy
286
+ next unless state.first == :ok && state[1]
287
+
288
+ alive, key = entry.lookup_key
289
+ pairs << [key, state[2]].freeze if alive
290
+ end
291
+ @index.sweep(entries)
292
+ [:ok, pairs.freeze].freeze
293
+ end
294
+
295
+ def clear
296
+ @claims.clear
297
+ @index.clear
298
+ changed
299
+ [:ok].freeze
300
+ end
301
+
302
+ def with_entry(key, create: false)
303
+ @index.sweep_one
304
+ loop do
305
+ entry, created = @index.resolve(key, create:) do |key_reference|
306
+ VaultWeakMapCell.new(key_reference, weak_values: @weak_values)
307
+ end
308
+ return yield(nil) unless entry
309
+ changed if created
310
+
311
+ state = yield(entry)
312
+ if state.first == :dead || state.first == :retired
313
+ entry.retire
314
+ remove(key, entry)
315
+ next
316
+ end
317
+ if created && state.first != :claimed && !entry.read.fetch(1, false)
318
+ remove(key, entry)
319
+ entry.retire
320
+ end
321
+ return state
322
+ end
323
+ end
324
+
325
+ def missing = [:missing, @changes, @changes.value].freeze
326
+
327
+ def remove(key, entry)
328
+ @index.remove(key, entry)
329
+ changed
330
+ end
331
+
332
+ def changed = @changes.update { |generation| generation + 1 }
333
+ end
334
+ private_constant :VaultWeakMapState
335
+ end
336
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ require "farce/engine/shared/weak_atom/base"
6
+ require "farce/engine/shared/weak_map/reference"
7
+
8
+ module Farce
9
+ # @!visibility private
10
+ module Internal # :nodoc: all
11
+ # Only the Vault accesses this slot. Publishing belongs here so interrupted
12
+ # callers cannot leave a committed value without notifying its observers.
13
+ class VaultWeakAtomSlot
14
+ def initialize(value, changes, freeze_state)
15
+ @reference = UnsharedWeakMapWeakReference.for(value)
16
+ @changes = changes
17
+ @freeze_state = freeze_state
18
+ end
19
+
20
+ def value = @reference.read.last
21
+
22
+ def store(value)
23
+ raise FrozenError, "can't modify frozen weak atom" if @freeze_state.value
24
+
25
+ @reference = UnsharedWeakMapWeakReference.for(value)
26
+ @changes.update { |generation| generation + 1 }
27
+ nil
28
+ end
29
+ end
30
+ private_constant :VaultWeakAtomSlot
31
+
32
+ class WeakAtom < WeakAtomBase
33
+ OWNER = Atom.new
34
+ private_constant :OWNER
35
+
36
+ private
37
+
38
+ def initialize_storage(value)
39
+ @token = Object.new.freeze
40
+ @vault = OWNER.store_if_absent { Vault.new }
41
+ @vault.weak_atom(@token, :create, value, @changes, @freeze_state)
42
+ Internal::Freeze.publish(self)
43
+ end
44
+
45
+ def validate_value(value)
46
+ return if ::Ractor.shareable?(value)
47
+ raise Ractor::IsolationError, "value must be Ractor-shareable"
48
+ end
49
+
50
+ def read_value = @vault.weak_atom(@token, :read)
51
+ def write_value(value) = @vault.weak_atom(@token, :store, value)
52
+ end
53
+ end
54
+ end