farce 0.0.1.alpha2-x86-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,30 @@
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
+ # Lease storage that retains shareable resource references directly.
9
+ class StrictLease < LeaseState
10
+ include Freeze::Unfreezable
11
+
12
+ private
13
+
14
+ def initialize_resource(resource)
15
+ @resource = StrictAtom.new(resource)
16
+ Freeze.publish(self)
17
+ end
18
+
19
+ def take_resource = @resource.swap(nil)
20
+ def return_resource(resource) = @resource.store(resource)
21
+
22
+ def validate_resource!(resource)
23
+ super
24
+ return if Ractor.shareable?(resource)
25
+
26
+ raise Ractor::IsolationError, "lease resource must be Ractor-shareable"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,20 @@
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
+ # Validate shareable resources before publishing or replacing map leases.
9
+ class StrictLeaseMap < LeaseMap
10
+ private
11
+
12
+ def validate_resource!(resource)
13
+ super
14
+ return if Ractor.shareable?(resource)
15
+
16
+ raise Ractor::IsolationError, "lease resource must be Ractor-shareable"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,29 @@
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
+ # Lease pool storage that retains shareable resource references directly.
9
+ class StrictLeasePool < LeasePoolState
10
+ include Freeze::Unfreezable
11
+
12
+ private
13
+
14
+ def initialize_storage = @resources = StrictMap.new(compare_by_identity: true)
15
+ def finalize_initialization = Freeze.publish(self)
16
+ def store_resource(token, resource) = @resources.store(token, resource)
17
+ def take_resource(token) = @resources.delete(token)
18
+ def return_resource(token, resource) = store_resource(token, resource)
19
+ def discard_resource(token) = @resources.delete(token)
20
+
21
+ def validate_resource!(resource)
22
+ super
23
+ return if Ractor.shareable?(resource)
24
+
25
+ raise Ractor::IsolationError, "lease pool resource must be Ractor-shareable"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal
7
+ # Run blocks on a bounded set of reusable threads.
8
+ # Workers start on demand. Capacity limits the total running and queued jobs.
9
+ # Each caller waits for its block's result and receives any exception it raises.
10
+ # Queue waits can yield through Ruby's scheduler hooks when those are available.
11
+ #
12
+ # An interrupted caller cancels its job if it has not started. Once a job has
13
+ # started, the caller waits for it to finish before unwinding its own cleanup.
14
+ # Closing stops new submissions, finishes accepted jobs, and joins the workers.
15
+ class ThreadPool
16
+ # Fetch or create the pool shared by all threads and fibers in this Ractor.
17
+ # Closing it is explicit and terminal. Later calls return the same closed pool.
18
+ def self.current
19
+ Ractor.store_if_absent(name) { new }
20
+ end
21
+
22
+ # Read the configured worker limit for the current Ractor.
23
+ def self.default_max_threads
24
+ Ractor.main? ? FROZEN_CONFIG.main_thread_pool_size : FROZEN_CONFIG.additional_thread_pool_size
25
+ end
26
+
27
+ class Job
28
+ def initialize(operation)
29
+ @operation = operation
30
+ @mutex = Thread::Mutex.new
31
+ @result = Thread::Queue.new
32
+ @done = Thread::Queue.new
33
+ @started = @cancelled = false
34
+ end
35
+
36
+ def run
37
+ operation = @mutex.synchronize do
38
+ @started = true
39
+ @operation unless @cancelled
40
+ end
41
+ @value = operation&.call
42
+ rescue Exception => e # rubocop:disable Lint/RescueException -- deliver job failures without losing a worker
43
+ @error = e
44
+ ensure
45
+ @operation = nil
46
+ end
47
+
48
+ def finish
49
+ @done << true
50
+ @result << [@value, @error]
51
+ end
52
+
53
+ def value
54
+ value, error = @result.pop
55
+ raise error if error
56
+ value
57
+ end
58
+
59
+ def cancel_and_wait
60
+ # Skip a job that has not started. Otherwise wait for its block to finish
61
+ # before the caller can clean up resources that the block still uses.
62
+ Thread.handle_interrupt(INTERRUPT_MASK) do
63
+ skipped = @mutex.synchronize do
64
+ unless @started
65
+ @cancelled = true
66
+ @operation = nil
67
+ true
68
+ end
69
+ end
70
+ unless skipped
71
+ Fiber.respond_to?(:blocking) ? Fiber.blocking { @done.pop } : @done.pop
72
+ end
73
+ end
74
+ end
75
+ end
76
+ private_constant :Job
77
+
78
+ attr_reader :max_threads, :capacity
79
+
80
+ # Limit worker threads and accepted jobs. Capacity defaults to twice the thread limit.
81
+ def initialize(max_threads: ThreadPool.default_max_threads, capacity: nil)
82
+ @max_threads = Integer(max_threads)
83
+ @capacity = capacity.nil? ? @max_threads * 2 : Integer(capacity)
84
+
85
+ raise ArgumentError, "max_threads must be positive" unless @max_threads.positive?
86
+ raise ArgumentError, "capacity must be at least max_threads" if @capacity < @max_threads
87
+
88
+ @mutex = Thread::Mutex.new
89
+ @jobs = Thread::Queue.new
90
+ @slots = Thread::SizedQueue.new(@capacity)
91
+ @workers = []
92
+ @pending = 0
93
+ @closed = false
94
+
95
+ @capacity.times { @slots << true }
96
+ end
97
+
98
+ # Wait for capacity, run the block on a worker, and return its value or raise its exception.
99
+ def call(&operation)
100
+ raise ArgumentError, "no block given" unless operation
101
+ admitted = @slots.pop
102
+ raise IOError, "thread pool is closed" unless admitted
103
+ job = Job.new(operation)
104
+ submitted = false
105
+ Thread.handle_interrupt(INTERRUPT_MASK) do
106
+ submit(job)
107
+ submitted = true
108
+ end
109
+ job.value
110
+ ensure
111
+ if submitted
112
+ job.cancel_and_wait
113
+ elsif admitted
114
+ release_slot
115
+ end
116
+ end
117
+
118
+ # Return the number of workers created so far.
119
+ def size = @mutex.synchronize { @workers.size }
120
+
121
+ # Report whether the pool has stopped accepting jobs.
122
+ def closed? = @mutex.synchronize { @closed }
123
+
124
+ # Stop accepting jobs, wake callers waiting for capacity, and finish accepted jobs.
125
+ def close
126
+ workers = @mutex.synchronize do
127
+ raise ThreadError, "a worker cannot close its own pool" if @workers.include?(Thread.current)
128
+ @closed = true
129
+ @slots.close
130
+ @jobs.close
131
+ @workers.dup
132
+ end
133
+ Fiber.respond_to?(:blocking) ? Fiber.blocking { workers.each(&:join) } : workers.each(&:join)
134
+ nil
135
+ end
136
+
137
+ private
138
+
139
+ def submit(job)
140
+ @mutex.synchronize do
141
+ raise IOError, "thread pool is closed" if @closed
142
+ @workers << Thread.new { work } if @workers.size < @max_threads && @workers.size <= @pending
143
+ @pending += 1
144
+ @jobs << job
145
+ end
146
+ end
147
+
148
+ def work
149
+ while job = @jobs.pop
150
+ job.run
151
+ @mutex.synchronize { @pending -= 1 }
152
+ release_slot
153
+ job.finish
154
+ job = nil
155
+ end
156
+ end
157
+
158
+ def release_slot
159
+ @slots << true
160
+ rescue ::ClosedQueueError
161
+ # Closing the pool has already woken callers waiting for capacity.
162
+ nil
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal # :nodoc: all
7
+ TransactionConflict = Class.new(StandardError)
8
+ end
9
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal # :nodoc: all
7
+ # Keep a Local handle's shared freeze state stable across a foreign commit.
8
+ # Reads retain the atomic flag. Only freeze and mixed commits take the lock.
9
+ class TransactionFreezeGuard
10
+ include Shareable::Immutable
11
+
12
+ attr_reader :native_flag, :lock
13
+
14
+ def initialize(value)
15
+ @native_flag = Flag.new(value)
16
+ @lock = Farce::Lock.new
17
+ super()
18
+ end
19
+
20
+ def value = @native_flag.value
21
+
22
+ def set
23
+ @lock.synchronize do
24
+ yield if block_given?
25
+ @native_flag.set
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal # :nodoc: all
7
+ # Records map dependencies without copying unobserved entries during the block.
8
+ # Full-map operations validate those dependencies before capturing all entries.
9
+ # Commit overlays staged writes onto a current snapshot for atomic publication.
10
+ class TransactionMapSnapshot
11
+ ABSENT = Object.new.freeze
12
+ private_constant :ABSENT
13
+
14
+ def initialize(source)
15
+ @source = source
16
+ @partial = source.class.new(
17
+ compare_keys_by_identity: source.compare_keys_by_identity?,
18
+ compare_values_by_identity: source.compare_values_by_identity?,
19
+ )
20
+ @observations = {}
21
+ @writes = {}
22
+ if source.compare_keys_by_identity?
23
+ @observations.compare_by_identity
24
+ @writes.compare_by_identity
25
+ end
26
+ @observed_present = 0
27
+ @base_size = nil
28
+ @dirty = false
29
+ @full = nil
30
+ end
31
+
32
+ def working = self
33
+
34
+ def write!
35
+ @dirty = true
36
+ @full&.write!
37
+ end
38
+
39
+ def [](key) = observe(key)[key]
40
+ def key?(key) = observe(key).key?(key)
41
+ def store(key, value) = changed(key).store(key, value)
42
+ def swap(key, value) = changed(key).swap(key, value)
43
+ def compare_and_set(key, expected, replacement) = changed(key).compare_and_set(key, expected, replacement)
44
+
45
+ def delete(key)
46
+ map = changed(key)
47
+ @writes[key] = true unless @full
48
+ map.delete(key)
49
+ end
50
+
51
+ def size
52
+ return @full.working.size if @full
53
+ @base_size ||= @source.respond_to?(:transaction_size) ? @source.transaction_size : @source.size
54
+ @base_size + @partial.size - @observed_present
55
+ end
56
+
57
+ def getkey(key) = promote.working.getkey(key)
58
+ def keys = promote.working.keys
59
+ def clear = promote.working.clear
60
+ def each(&) = promote.working.each(&)
61
+
62
+ def prepare_commit
63
+ return @full if @full
64
+ if !@dirty && @observations.empty?
65
+ return unless @base_size
66
+ return @source.transaction_size_snapshot(@base_size) if @source.respond_to?(:transaction_size_snapshot)
67
+ end
68
+ promote
69
+ end
70
+
71
+ private
72
+
73
+ def read(source, key)
74
+ return source.transaction_read(key) if source.respond_to?(:transaction_read)
75
+ value = source.fetch(key, ABSENT)
76
+ [!PortableTransaction.same?(value, ABSENT), value]
77
+ end
78
+
79
+ def observe(key)
80
+ return @full.working if @full
81
+ unless @observations.key?(key)
82
+ present, value = read(@source, key)
83
+ @observations[key] = [present, value]
84
+ if present
85
+ @partial.store(key, value)
86
+ @observed_present += 1
87
+ end
88
+ end
89
+ @partial
90
+ end
91
+
92
+ def changed(key)
93
+ map = observe(key)
94
+ @writes[key] = false unless @full || @writes.key?(key)
95
+ map
96
+ end
97
+
98
+ def promote
99
+ return @full if @full
100
+ snapshot = @source.transaction_snapshot
101
+ current = snapshot.working
102
+ raise TransactionConflict, "map size changed" if @base_size && current.size != @base_size
103
+ @observations.each do |key, (present, value)|
104
+ current_present, current_value = read(current, key)
105
+ unless present == current_present && (!present || PortableTransaction.same?(value, current_value))
106
+ raise TransactionConflict, "map observation changed"
107
+ end
108
+ end
109
+ @writes.each do |key, deleted|
110
+ # Deletion followed by reinsertion must replace the stored key object.
111
+ current.delete(key) if deleted
112
+ if @partial.key?(key)
113
+ current.store(@partial.getkey(key), @partial[key])
114
+ else
115
+ current.delete(key)
116
+ end
117
+ end
118
+ snapshot.write! if @dirty
119
+ @full = snapshot
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Farce
4
+ # @!visibility private
5
+ module Internal # :nodoc: all
6
+ class Undefined < BasicObject
7
+ define_method(:freeze, ::Object.instance_method(:freeze))
8
+ define_method(:frozen?, ::Object.instance_method(:frozen?))
9
+
10
+ def initialize(inspect)
11
+ @inspect = inspect
12
+ Ractor.make_shareable(self) if defined?(Ractor)
13
+ freeze
14
+ end
15
+
16
+ attr_reader :inspect
17
+
18
+ def nil? = false
19
+ alias === equal?
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
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
+ # Lease storage that passes its resource directly within one Ractor.
9
+ class UnsharedLease < LeaseState
10
+ include Freeze::Unfreezable
11
+
12
+ private
13
+
14
+ def initialize_resource(resource)
15
+ @resource = resource
16
+ end
17
+
18
+ def take_resource
19
+ resource = @resource
20
+ @resource = nil
21
+ resource
22
+ end
23
+
24
+ def return_resource(resource)
25
+ @resource = resource
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
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
+ # Lease pool storage that passes resource references within one Ractor.
9
+ class UnsharedLeasePool < LeasePoolState
10
+ include Freeze::Unfreezable
11
+
12
+ private
13
+
14
+ def initialize_storage
15
+ @resource_lock = Mutex.new
16
+ @resources = {}
17
+ end
18
+
19
+ def store_resource(token, resource)
20
+ @resource_lock.synchronize { @resources[token] = resource }
21
+ end
22
+
23
+ def take_resource(token)
24
+ @resource_lock.synchronize { @resources.delete(token) }
25
+ end
26
+
27
+ alias return_resource store_resource
28
+
29
+ def discard_resource(token)
30
+ @resource_lock.synchronize { @resources.delete(token) }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal # :nodoc: all
7
+ module UnsharedQueueWaiting
8
+ # The resolved fiber waiting strategy. Other Ruby engines may return :auto.
9
+ attr_reader :fiber_wait
10
+
11
+ # @param fiber_wait [:auto, :io, :block] how scheduled fibers wait on CRuby
12
+ def initialize(fiber_wait: :auto, **)
13
+ @fiber_wait = fiber_wait
14
+ super(**)
15
+ end
16
+
17
+ private
18
+
19
+ def queue_signal
20
+ signal = Internal::UnsharedSignal.for(@fiber_wait)
21
+ @fiber_wait = signal.fiber_wait
22
+ signal
23
+ end
24
+
25
+ def queue_storage_class = Internal::UnsharedPriorityQueue
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
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
+ # Extension point for integrations that serialize a container's current value.
9
+ # @api private
10
+ module ValueSerialization
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,58 @@
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
+ module WeakMapValueModes
9
+ include MapValueModes
10
+
11
+ # Values follow the selected mode. Keys must already be shareable.
12
+ # @param mode [Symbol] :raise, :make_shareable, or :dedup
13
+ def initialize(initial_mapping = nil, mode: :raise, **options)
14
+ super
15
+ end
16
+
17
+ def store(key, value, mode: nil, **)
18
+ @manager.validate_mode!(mode)
19
+ super
20
+ end
21
+
22
+ def swap(key, replacement, mode: nil, **)
23
+ @manager.validate_mode!(mode)
24
+ super
25
+ end
26
+
27
+ def store_if_absent(key, mode: nil, **)
28
+ raise LocalJumpError, "no block given" unless block_given?
29
+ @manager.validate_mode!(mode)
30
+ super
31
+ end
32
+
33
+ def update(key, mode: nil, **)
34
+ raise LocalJumpError, "no block given" unless block_given?
35
+ @manager.validate_mode!(mode)
36
+ super
37
+ end
38
+
39
+ def upsert(key, initial, mode: nil, **)
40
+ raise LocalJumpError, "no block given" unless block_given?
41
+ @manager.validate_mode!(mode)
42
+ super
43
+ end
44
+
45
+ def compare_and_set(key, expected, replacement, mode: nil, **)
46
+ @manager.validate_mode!(mode)
47
+ super
48
+ end
49
+
50
+ private
51
+
52
+ def new_mode_manager(mode:) = WeakModeManager.new(mode:)
53
+
54
+ # Expected values are comparison operands, not values to publish.
55
+ def wrap_comparison(value) = nil.equal?(value) ? NIL_VALUE : value
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,26 @@
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
+ # Prepare values without introducing a wrapper with an independent lifetime.
9
+ class WeakModeManager < ModeManager
10
+ MODES = %i[raise make_shareable dedup].freeze
11
+
12
+ def initialize(mode: :raise)
13
+ validate_mode!(mode)
14
+ super
15
+ end
16
+
17
+ def validate_mode!(mode)
18
+ selected = nil.equal?(mode) ? self.mode : mode
19
+ return selected if MODES.include?(selected)
20
+ raise ArgumentError, "unsupported weak value mode: #{selected.inspect}"
21
+ end
22
+
23
+ def wrap(value, mode: nil) = super(value, mode: validate_mode!(mode))
24
+ end
25
+ end
26
+ end