farce 0.0.1.alpha2-x86-linux-musl

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,229 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ require "farce/internal/autoloads"
6
+
7
+ # Checks against RUBY_ENGINE, RUBY_VERSION, RUBY_PLATFORM, and ENV are explicitly allowed in this file.
8
+ # Checks against RUBY_ENGINE and similar should be avoided within lib outside this file, lib/farce/engine,
9
+ # and the one require in lib/farce.rb
10
+ # Checks against ENV should be avoided entirely within lib outside of this file
11
+ #-
12
+
13
+ module Farce
14
+ # Configuration for Farce. Will be frozen by Farce once it is accessed, to prevent accidental changes and make it
15
+ # shareable across Ractors.
16
+ #
17
+ # ```ruby
18
+ # require "farce"
19
+ #
20
+ # Farce.config do |c|
21
+ # c.fiber_scheduler = :select
22
+ # end
23
+ # ```
24
+ class Config
25
+ # Automatically load integrations when their dependencies are loaded. Defaults to true.
26
+ # Can also be set via `FARCE_AUTOLOAD_INTEGRATIONS` (`true`/`false` or `1`/`0`).
27
+ # Set before requiring Farce to also disable startup integration loading.
28
+ # @return [Boolean]
29
+ attr_reader :autoload_integrations
30
+
31
+ # Maximum workers in a pool created on the main Ractor. Workers start lazily.
32
+ # Can also be set via `FARCE_MAIN_THREAD_POOL_SIZE`. Defaults to 4.
33
+ attr_reader :main_thread_pool_size
34
+
35
+ # Maximum workers in a pool created on another Ractor. Workers start lazily.
36
+ # Can also be set via `FARCE_ADDITIONAL_THREAD_POOL_SIZE`. Defaults to 2.
37
+ attr_reader :additional_thread_pool_size
38
+
39
+ # @yield [config] block to modify the configuration
40
+ # @yieldparam config [Config] the configuration object to configure
41
+ def initialize
42
+ yield self if block_given?
43
+ self.autoload_integrations = ENV.fetch("FARCE_AUTOLOAD_INTEGRATIONS", true) if autoload_integrations.nil?
44
+ self.fiber_scheduler = ENV["FARCE_FIBER_SCHEDULER"] unless instance_variable_defined?(:@fiber_scheduler)
45
+ self.main_thread_pool_size ||= ENV.fetch("FARCE_MAIN_THREAD_POOL_SIZE", 4)
46
+ self.additional_thread_pool_size ||= ENV.fetch("FARCE_ADDITIONAL_THREAD_POOL_SIZE", 2)
47
+ end
48
+
49
+ # @api private
50
+ def marshal_dump
51
+ [1, autoload_integrations, fiber_scheduler, main_thread_pool_size, additional_thread_pool_size, frozen?]
52
+ end
53
+
54
+ # @api private
55
+ def marshal_load(data)
56
+ autoload, scheduler, main_size, additional_size, frozen = Internal::MarshalSupport.payload(data, 5)
57
+
58
+ self.autoload_integrations = autoload
59
+ self.fiber_scheduler = scheduler
60
+ self.main_thread_pool_size = main_size
61
+ self.additional_thread_pool_size = additional_size
62
+ freeze if frozen
63
+ end
64
+
65
+ # Enable or disable automatic integration loading. Already loaded integrations remain active.
66
+ # @param value [Boolean, String] true, false, or their environment variable representations.
67
+ # @raise [ArgumentError] If the value is not a supported boolean.
68
+ def autoload_integrations=(value)
69
+ @autoload_integrations = case value
70
+ when true, "true", "1" then true
71
+ when false, "false", "0" then false
72
+ else raise ArgumentError, "autoload_integrations must be a boolean"
73
+ end
74
+ end
75
+
76
+ # Default fiber scheduler for Pool and Scheduler.
77
+ # Explicit constructor blocks override it.
78
+ #
79
+ # Uses `FARCE_FIBER_SCHEDULER` unless assigned explicitly, including an explicit nil.
80
+ #
81
+ # Built-in choices are `:auto`, `:native`, `:jvm`, `:select`, `:kqueue`, `:epoll`,
82
+ # `:io_uring`, and `:nio`. Strings are also accepted. `nil` or an empty string are treated like `:auto`.
83
+ #
84
+ # Other names resolve constants, such as `carbon_fiber` to `CarbonFiber`.
85
+ # If the constant is not defined, it attempts to require the corresponding file.
86
+ # Modules must define their own `Scheduler` class.
87
+ #
88
+ # Classes are constructed without arguments in each worker. Procs must be shareable.
89
+ # Custom schedulers must support the executor used by the Pool or Scheduler.
90
+ #
91
+ # @return [Symbol, Class, Proc] normalized choice
92
+ def fiber_scheduler(&constructor)
93
+ self.fiber_scheduler = constructor if constructor
94
+ @fiber_scheduler
95
+ end
96
+
97
+ # Sets the default scheduler. Use `config.fiber_scheduler { MyScheduler.new }`
98
+ # or assign a proc to configure construction. Invalid assignments preserve the old value.
99
+ def fiber_scheduler=(value)
100
+ raise FrozenError, "can't modify frozen Config" if frozen?
101
+ @fiber_scheduler = normalize_fiber_scheduler(value)
102
+ end
103
+
104
+ # Implementation used by Farce's built-in scheduler.
105
+ # @return [Symbol] one of `:native`, `:select`, or `:jvm`
106
+ def fiber_scheduler_implementation
107
+ case @fiber_scheduler
108
+ when :native, :jvm, :select then @fiber_scheduler
109
+ when :kqueue, :epoll, :io_uring then :native
110
+ when :nio then :jvm
111
+ else detected_fiber_scheduler_implementation
112
+ end
113
+ end
114
+
115
+ # IO backend used by the built-in scheduler. Explicit `backend:` options override it.
116
+ # Availability is checked when a scheduler is created.
117
+ # @return [Symbol] the configured backend or `:auto`
118
+ def io_backend
119
+ case @fiber_scheduler
120
+ when :kqueue, :epoll, :io_uring, :nio, :select then @fiber_scheduler
121
+ else :auto
122
+ end
123
+ end
124
+
125
+ # Constructor for a custom scheduler, or nil for the built-in scheduler.
126
+ # @api private
127
+ def fiber_scheduler_constructor
128
+ case @fiber_scheduler
129
+ when Class
130
+ require "farce" unless Farce.const_defined?(:Ractor, false)
131
+ Ractor.shareable_proc(self: @fiber_scheduler) { new }
132
+ when Proc then @fiber_scheduler
133
+ end
134
+ end
135
+
136
+ # Sets a positive worker limit for pools created on the main Ractor.
137
+ def main_thread_pool_size=(value)
138
+ @main_thread_pool_size = normalize_thread_pool_size(value)
139
+ end
140
+
141
+ # Sets a positive worker limit for pools created on other Ractors.
142
+ def additional_thread_pool_size=(value)
143
+ @additional_thread_pool_size = normalize_thread_pool_size(value)
144
+ end
145
+
146
+ # Called internally once the configuration is applied.
147
+ def freeze
148
+ return self if frozen?
149
+ super # need to call this first to avoid infinite recursion in the next line
150
+ ::Ractor.make_shareable(self) if defined?(::Ractor.make_shareable)
151
+ self
152
+ end
153
+
154
+ private
155
+
156
+ def normalize_thread_pool_size(value)
157
+ size = value.is_a?(String) ? Integer(value, 10) : value
158
+ raise ArgumentError, "thread pool size must be a positive integer" unless size.is_a?(Integer) && size.positive?
159
+ size
160
+ end
161
+
162
+ def normalize_fiber_scheduler(value, original = value)
163
+ case value
164
+ when nil, "", "auto", :auto
165
+ return :auto
166
+
167
+ when :native, :jvm, :select, :kqueue, :epoll, :io_uring, :nio, Class
168
+ return value
169
+
170
+ when "native", "jvm", "select", "kqueue", "epoll", "io_uring", "nio"
171
+ return value.to_sym
172
+
173
+ when Symbol, String
174
+ constant = Internal::Autoloads.inflect(value.to_s)
175
+ path = original.to_s if original.is_a?(String) || original.is_a?(Symbol)
176
+
177
+ begin
178
+ require path if path && !Object.const_defined?(constant)
179
+ rescue LoadError => e
180
+ raise e unless e.path == path
181
+ end
182
+
183
+ value = Object.const_get(constant)
184
+ return normalize_fiber_scheduler(value, original) if value.is_a?(Module) || value.is_a?(Proc)
185
+
186
+ when Module
187
+ if value.const_defined?(:Scheduler, false)
188
+ scheduler = value.const_get(:Scheduler, false)
189
+ return scheduler if scheduler.is_a?(Class)
190
+ end
191
+
192
+ when Proc
193
+ require "farce" unless Farce.const_defined?(:Ractor, false)
194
+ return Ractor.shareable?(value) ? value : Ractor.shareable_proc(&value)
195
+ end
196
+
197
+ raise ArgumentError, "invalid fiber scheduler: #{value.inspect}"
198
+ rescue NameError => e
199
+ raise ArgumentError, "unknown fiber scheduler: #{original.inspect} (#{e.message})"
200
+ end
201
+
202
+ def detected_fiber_scheduler_implementation
203
+ case RUBY_ENGINE
204
+ when "ruby" then RUBY_PLATFORM.match?(/linux|darwin|bsd/) ? :native : :select
205
+ when "jruby" then :jvm
206
+ else :select
207
+ end
208
+ end
209
+ end
210
+
211
+ # shareable_constant_value: none
212
+ CONFIG = Config.new
213
+ private_constant :CONFIG
214
+
215
+ # Configures Farce.
216
+ # @example
217
+ # Farce.configure do |config|
218
+ # config.fiber_scheduler = :carbon_fiber
219
+ # end
220
+ # @yield [config] the configuration object
221
+ def self.configure = yield CONFIG
222
+
223
+ # @overload config
224
+ # @return [Config] the global Farce configuration
225
+ def self.config(&)
226
+ configure(&) if block_given?
227
+ CONFIG
228
+ end
229
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ # Ractor-shareable, atomic counter.
7
+ # This is a stateful, numeric object.
8
+ #
9
+ # Values are converted to Integers. On CRuby, the stored value and arithmetic
10
+ # deltas must fit in a signed 64-bit integer. An overflow raises RangeError without
11
+ # changing the stored value. Conditional-operation bounds may be wider, but a
12
+ # resulting stored value must still fit.
13
+ #
14
+ # On CRuby, subclasses must not add Ruby instance variables.
15
+ #
16
+ # @!method initial
17
+ # @return [Integer] The initial value retained by reset and copies.
18
+ #
19
+ # @!method value
20
+ # @return [Integer] The current value of the counter.
21
+ #
22
+ # @!method increment(by = 1)
23
+ # Increment the counter by the given amount (default is 1).
24
+ # @param [Numeric, String, #to_int] by The amount, converted to an Integer.
25
+ # @return [self] Returns self for chaining.
26
+ #
27
+ # @!method decrement(by = 1)
28
+ # Decrement the counter by the given amount (default is 1).
29
+ # @param [Numeric, String, #to_int] by The amount, converted to an Integer.
30
+ # @return [self] Returns self for chaining.
31
+ #
32
+ # @example Cross-Ractor counting
33
+ # counter = Farce::Counter.new
34
+ # counter.value # => 0
35
+ #
36
+ # # Increase the counter by 1
37
+ # counter.increment
38
+ # counter.value # => 1
39
+ #
40
+ # # Increase the counter by 5 on another Ractor
41
+ # Ractor.new(counter) { it.add(5) }
42
+ #
43
+ # # Give the other ractor time to run
44
+ # sleep 0.1
45
+ #
46
+ # counter.value # => 6
47
+ #
48
+ # @example Counter as a numeric value
49
+ # counter = Farce::Counter.new(10.0)
50
+ # counter.to_i # => 10
51
+ # counter + 5 # => 15
52
+ # 2.5 * counter # => 25.0
53
+ #
54
+ # require "active_support/all"
55
+ # counter.minutes.to_i # => 600
56
+ class Counter < Internal::Counter
57
+ include Abstract::Counter
58
+ include Shareable::Native
59
+
60
+ # @param [Numeric, String, #to_int] value The initial value, converted to an Integer.
61
+ def initialize(value = 0)
62
+ raise FrozenError.new("can't initialize a frozen counter", receiver: self) if frozen?
63
+ super(Integer(value))
64
+ end
65
+
66
+ alias subtract decrement
67
+ alias remove decrement
68
+
69
+ private :change_signal
70
+ end
71
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ # Reuse equal frozen values throughout object graphs.
7
+ # Plain strings use Ruby's string deduplication. Arrays, hashes, and Ruby Sets are frozen
8
+ # and cached by default. Other objects are traversed but are not cached unless
9
+ # their class matches {#store}. Modules and classes are skipped by default.
10
+ #
11
+ # Cached objects are held weakly. Keep a reference to a returned object if its
12
+ # identity matters. Shareable results can be reused across Ractors. Other
13
+ # results are cached within the current Ractor.
14
+ #
15
+ # Cyclic containers are frozen after their references are connected and are
16
+ # not cached. This keeps canonical replacements from breaking back references.
17
+ #
18
+ # @example Use an independent cache
19
+ # deduper = Farce::Deduper.new
20
+ # first = deduper.dedup(["name"], copy: true)
21
+ # deduper.dedup(["name"]).equal?(first) # => true
22
+ class Deduper
23
+ include Shareable::Immutable
24
+
25
+ # @api private
26
+ # Create an independent cache with the default skip and store classes.
27
+ def initialize
28
+ @shared = Strict::WeakKeyMap.new
29
+ @local = Local::WeakKeyMap.new
30
+ @skip = Strict::Vector[Module]
31
+ @store = Strict::Vector[Hash, Array, ::Set]
32
+ super
33
+ end
34
+
35
+ # @api private
36
+ def marshal_dump = [1, @skip.to_a, @store.to_a]
37
+
38
+ # @api private
39
+ def marshal_load(data)
40
+ skip, store = Internal::MarshalSupport.payload(data, 2)
41
+ @shared = Strict::WeakKeyMap.new
42
+ @local = Local::WeakKeyMap.new
43
+ @skip = Strict::Vector.new(skip)
44
+ @store = Strict::Vector.new(store)
45
+ publish_shareable
46
+ end
47
+
48
+ # Exclude matching objects and their children from subsequent calls.
49
+ # @param modules [Array<Module>] classes or modules matched with is_a?
50
+ # @return [self]
51
+ def skip(*modules)
52
+ @skip.concat(modules)
53
+ self
54
+ end
55
+
56
+ # Also freeze and cache objects matching these classes or modules.
57
+ # Define consistent hash, eql?, and == methods for custom value classes.
58
+ # These methods must remain stable after deduplication.
59
+ # @param modules [Array<Module>] classes or modules matched with is_a?
60
+ # @return [self]
61
+ def store(*modules)
62
+ @store.concat(modules)
63
+ self
64
+ end
65
+
66
+ # Replace equal values with cached instances, including nested keys and values.
67
+ # By default, mutable containers are updated and cached containers are frozen.
68
+ # Use copy: true to preserve the input. Skipped objects are always returned
69
+ # unchanged. Strings are deduplicated before skip rules are checked.
70
+ # Noncopyable coordination objects follow {Walker.modify}'s in-place behavior.
71
+ # @param object [Object] the root object
72
+ # @param copy [Boolean, Symbol] copying policy passed to {Walker.modify}
73
+ # @param skip [Module, Array<Module>, nil] additional exclusions for this call
74
+ # @return [Object] the deduplicated result
75
+ # @see Walker.modify
76
+ def dedup(object, copy: false, skip: nil)
77
+ skip = skip ? [*@skip, *skip] : @skip.to_a
78
+ dedup!(object, skip, @store.to_a, copy)
79
+ end
80
+
81
+ private
82
+
83
+ def dedup!(object, skip, store, copy, walker = nil)
84
+ return -object if object.instance_of?(String)
85
+ return object unless Internal.garbage_collectable?(object)
86
+
87
+ if skip.any? { object.is_a?(it) }
88
+ walker&.skip(object)
89
+ return object
90
+ end
91
+
92
+ if !walker || walker.hashable?(object)
93
+ shareable = Ractor.shareable?(object)
94
+ canonical = (shareable ? @shared : @local).getkey(object)
95
+ return canonical if canonical
96
+ end
97
+
98
+ return Walker.modify(object, copy:, freeze: false) { dedup!(_1, skip, store, copy, _2) } unless walker
99
+
100
+ canonical = walker.traverse
101
+ return canonical unless store.any? { canonical.is_a?(it) }
102
+
103
+ walker.freeze_result
104
+ walker.finalize do |result, cyclic|
105
+ cyclic ? result : intern(result)
106
+ end
107
+ end
108
+
109
+ def intern(canonical)
110
+ if Ractor.shareable?(canonical)
111
+ @shared.store_if_absent(canonical) { true }
112
+ canonical = @shared.getkey(canonical) || canonical
113
+ end
114
+
115
+ @local[canonical] = true
116
+ canonical
117
+ end
118
+ end
119
+
120
+ DEDUPER = Deduper.new
121
+ private_constant :DEDUPER
122
+ end