farce 0 → 0.1.0

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 (420) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/CODE_OF_CONDUCT.md +26 -0
  4. data/CONTRIBUTING.md +71 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +1525 -0
  7. data/SECURITY.md +10 -0
  8. data/docs/benchmarks.md +185 -0
  9. data/docs/gems/dry-types.md +290 -0
  10. data/docs/gems/msgpack.md +70 -0
  11. data/docs/gems/ractor-shim.md +63 -0
  12. data/docs/modes.md +628 -0
  13. data/docs/scopes.md +649 -0
  14. data/docs/variants.md +346 -0
  15. data/ext/ext_helper.rb +20 -0
  16. data/ext/farce/README.md +21 -0
  17. data/ext/farce/atom.c +1023 -0
  18. data/ext/farce/bounded_map.c +1683 -0
  19. data/ext/farce/containers.h +77 -0
  20. data/ext/farce/counter.c +399 -0
  21. data/ext/farce/darwin.c +100 -0
  22. data/ext/farce/depend +12 -0
  23. data/ext/farce/dict.c +1523 -0
  24. data/ext/farce/dict.h +152 -0
  25. data/ext/farce/drivers.c +237 -0
  26. data/ext/farce/exchanger.c +299 -0
  27. data/ext/farce/extconf.rb +99 -0
  28. data/ext/farce/farce.c +359 -0
  29. data/ext/farce/flag.c +288 -0
  30. data/ext/farce/io.c +338 -0
  31. data/ext/farce/lock.c +510 -0
  32. data/ext/farce/map.c +2240 -0
  33. data/ext/farce/priority_queue.c +2056 -0
  34. data/ext/farce/queue.c +1059 -0
  35. data/ext/farce/reactor.c +820 -0
  36. data/ext/farce/reactor.h +103 -0
  37. data/ext/farce/shareable.h +31 -0
  38. data/ext/farce/signal.c +350 -0
  39. data/ext/farce/transaction.c +354 -0
  40. data/ext/farce/transaction.h +40 -0
  41. data/ext/farce/tree_map.c +1953 -0
  42. data/ext/farce/trie.c +2020 -0
  43. data/ext/farce/unshareable.c +155 -0
  44. data/ext/farce/unshared_io_pool.h +234 -0
  45. data/ext/farce/unshared_signal.c +263 -0
  46. data/ext/farce/unshared_wait.h +193 -0
  47. data/ext/farce/unsupported.c +6 -0
  48. data/ext/farce/vector.c +1195 -0
  49. data/ext/farce/weak_map.c +1714 -0
  50. data/ext/java/org/farce/BoundedMap.java +394 -0
  51. data/ext/java/org/farce/FiberScheduler.java +141 -0
  52. data/ext/java/org/farce/PriorityKey.java +45 -0
  53. data/ext/java/org/farce/PriorityQueue.java +373 -0
  54. data/ext/java/org/farce/QueueSignal.java +28 -0
  55. data/ext/rebind/README.md +14 -0
  56. data/ext/rebind/extconf.rb +10 -0
  57. data/ext/rebind/rebind.c +186 -0
  58. data/lib/farce/_yard/internal.rb +13 -0
  59. data/lib/farce/_yard/macros.rb +61 -0
  60. data/lib/farce/_yard/ractor.rb +46 -0
  61. data/lib/farce/abstract/atom.rb +186 -0
  62. data/lib/farce/abstract/bounded_map.rb +232 -0
  63. data/lib/farce/abstract/collection.rb +151 -0
  64. data/lib/farce/abstract/concurrent_map.rb +381 -0
  65. data/lib/farce/abstract/counter.rb +193 -0
  66. data/lib/farce/abstract/duplicable_map.rb +229 -0
  67. data/lib/farce/abstract/exchanger.rb +26 -0
  68. data/lib/farce/abstract/flag.rb +71 -0
  69. data/lib/farce/abstract/lazy.rb +115 -0
  70. data/lib/farce/abstract/lease.rb +104 -0
  71. data/lib/farce/abstract/lease_map.rb +261 -0
  72. data/lib/farce/abstract/lease_pool.rb +91 -0
  73. data/lib/farce/abstract/lfu_map.rb +20 -0
  74. data/lib/farce/abstract/lru_map.rb +25 -0
  75. data/lib/farce/abstract/map.rb +345 -0
  76. data/lib/farce/abstract/molecule.rb +245 -0
  77. data/lib/farce/abstract/port.rb +74 -0
  78. data/lib/farce/abstract/priority_queue.rb +117 -0
  79. data/lib/farce/abstract/queue.rb +269 -0
  80. data/lib/farce/abstract/scheduler.rb +111 -0
  81. data/lib/farce/abstract/set.rb +910 -0
  82. data/lib/farce/abstract/sorted_set.rb +172 -0
  83. data/lib/farce/abstract/timer_queue.rb +136 -0
  84. data/lib/farce/abstract/tree_map.rb +269 -0
  85. data/lib/farce/abstract/value.rb +68 -0
  86. data/lib/farce/abstract/vector.rb +1126 -0
  87. data/lib/farce/abstract/weak_atom.rb +32 -0
  88. data/lib/farce/abstract/weak_key_map.rb +12 -0
  89. data/lib/farce/abstract/weak_map.rb +13 -0
  90. data/lib/farce/abstract/weak_set.rb +12 -0
  91. data/lib/farce/abstract/weak_value_map.rb +12 -0
  92. data/lib/farce/abstract.rb +17 -0
  93. data/lib/farce/atom.rb +293 -0
  94. data/lib/farce/class_mirror.rb +87 -0
  95. data/lib/farce/clock.rb +121 -0
  96. data/lib/farce/config.rb +229 -0
  97. data/lib/farce/counter.rb +71 -0
  98. data/lib/farce/deduper.rb +122 -0
  99. data/lib/farce/engine/jruby/bounded_map.rb +314 -0
  100. data/lib/farce/engine/jruby/fiber_scheduler.jar +0 -0
  101. data/lib/farce/engine/jruby/fiber_scheduler.rb +119 -0
  102. data/lib/farce/engine/jruby/lease_waiting.rb +19 -0
  103. data/lib/farce/engine/jruby/map.rb +505 -0
  104. data/lib/farce/engine/jruby/mutable_numeric_copy.rb +42 -0
  105. data/lib/farce/engine/jruby/signal.rb +147 -0
  106. data/lib/farce/engine/jruby.rb +63 -0
  107. data/lib/farce/engine/jvm/concurrent_weak_registry.rb +55 -0
  108. data/lib/farce/engine/jvm/counter.rb +102 -0
  109. data/lib/farce/engine/jvm/extension.rb +32 -0
  110. data/lib/farce/engine/jvm/farce.jar +0 -0
  111. data/lib/farce/engine/jvm/flag.rb +79 -0
  112. data/lib/farce/engine/jvm/priority_queue.rb +217 -0
  113. data/lib/farce/engine/jvm/tree_map.rb +350 -0
  114. data/lib/farce/engine/jvm/types.rb +180 -0
  115. data/lib/farce/engine/jvm.rb +19 -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/vault.rb +56 -0
  121. data/lib/farce/engine/ruby/4.0/port.rb +19 -0
  122. data/lib/farce/engine/ruby/4.0/ractor_methods.rb +20 -0
  123. data/lib/farce/engine/ruby/4.0/ractor_selector.rb +108 -0
  124. data/lib/farce/engine/ruby/4.0/vault.rb +74 -0
  125. data/lib/farce/engine/ruby/4.1/port.rb +21 -0
  126. data/lib/farce/engine/ruby/4.1/ractor_methods.rb +22 -0
  127. data/lib/farce/engine/ruby/4.1/ractor_selector.rb +25 -0
  128. data/lib/farce/engine/ruby/4.1/vault.rb +5 -0
  129. data/lib/farce/engine/ruby/fiber_scheduler.rb +32 -0
  130. data/lib/farce/engine/ruby/key_lock_map.rb +28 -0
  131. data/lib/farce/engine/ruby/shared/lease.rb +26 -0
  132. data/lib/farce/engine/ruby/shared/lease_pool.rb +24 -0
  133. data/lib/farce/engine/ruby/shared/main_scheduler.rb +9 -0
  134. data/lib/farce/engine/ruby/shared/parallel_scheduler.rb +9 -0
  135. data/lib/farce/engine/ruby/shared/proxy_owner.rb +31 -0
  136. data/lib/farce/engine/ruby/shared/ractor_methods.rb +34 -0
  137. data/lib/farce/engine/ruby/shared/ractor_selector.rb +328 -0
  138. data/lib/farce/engine/ruby/shared/strict_map.rb +13 -0
  139. data/lib/farce/engine/ruby/shared/unshared_vector.rb +14 -0
  140. data/lib/farce/engine/ruby/shared/vault.rb +144 -0
  141. data/lib/farce/engine/ruby/shared/vault_weak_map.rb +336 -0
  142. data/lib/farce/engine/ruby/shared/weak_atom.rb +54 -0
  143. data/lib/farce/engine/ruby/shared/weak_map.rb +413 -0
  144. data/lib/farce/engine/ruby.rb +130 -0
  145. data/lib/farce/engine/shared/atom.rb +10 -0
  146. data/lib/farce/engine/shared/exchanger.rb +130 -0
  147. data/lib/farce/engine/shared/identity_key.rb +22 -0
  148. data/lib/farce/engine/shared/lease.rb +10 -0
  149. data/lib/farce/engine/shared/lease_pool.rb +10 -0
  150. data/lib/farce/engine/shared/main_scheduler.rb +20 -0
  151. data/lib/farce/engine/shared/map_key_coordination.rb +226 -0
  152. data/lib/farce/engine/shared/parallel_scheduler.rb +9 -0
  153. data/lib/farce/engine/shared/port.rb +44 -0
  154. data/lib/farce/engine/shared/portable_bounded_map.rb +619 -0
  155. data/lib/farce/engine/shared/proxy_owner.rb +43 -0
  156. data/lib/farce/engine/shared/queue.rb +233 -0
  157. data/lib/farce/engine/shared/ractor_methods.rb +73 -0
  158. data/lib/farce/engine/shared/rebindable.rb +15 -0
  159. data/lib/farce/engine/shared/strict_atom.rb +73 -0
  160. data/lib/farce/engine/shared/strict_map.rb +117 -0
  161. data/lib/farce/engine/shared/strict_queue_values.rb +27 -0
  162. data/lib/farce/engine/shared/strict_tree_map.rb +56 -0
  163. data/lib/farce/engine/shared/transaction_map_backend.rb +20 -0
  164. data/lib/farce/engine/shared/trie.rb +317 -0
  165. data/lib/farce/engine/shared/trie_builder.rb +199 -0
  166. data/lib/farce/engine/shared/unshareable.rb +14 -0
  167. data/lib/farce/engine/shared/unshared_atom.rb +256 -0
  168. data/lib/farce/engine/shared/unshared_priority_queue.rb +9 -0
  169. data/lib/farce/engine/shared/unshared_queue.rb +18 -0
  170. data/lib/farce/engine/shared/unshared_signal.rb +21 -0
  171. data/lib/farce/engine/shared/unshared_vector.rb +377 -0
  172. data/lib/farce/engine/shared/unshared_weak_atom.rb +30 -0
  173. data/lib/farce/engine/shared/unshared_weak_map.rb +445 -0
  174. data/lib/farce/engine/shared/vault.rb +31 -0
  175. data/lib/farce/engine/shared/vector.rb +83 -0
  176. data/lib/farce/engine/shared/weak_atom/base.rb +189 -0
  177. data/lib/farce/engine/shared/weak_atom.rb +20 -0
  178. data/lib/farce/engine/shared/weak_map/cell.rb +99 -0
  179. data/lib/farce/engine/shared/weak_map/index.rb +249 -0
  180. data/lib/farce/engine/shared/weak_map/lock.rb +80 -0
  181. data/lib/farce/engine/shared/weak_map/reference.rb +33 -0
  182. data/lib/farce/engine/shared.rb +63 -0
  183. data/lib/farce/engine/truffleruby/fiber_scheduler.rb +13 -0
  184. data/lib/farce/engine/truffleruby/lock.rb +121 -0
  185. data/lib/farce/engine/truffleruby/map.rb +656 -0
  186. data/lib/farce/engine/truffleruby/native/counter.rb +105 -0
  187. data/lib/farce/engine/truffleruby/native/flag.rb +77 -0
  188. data/lib/farce/engine/truffleruby/native/ordered_array_support.rb +67 -0
  189. data/lib/farce/engine/truffleruby/native/priority_queue.rb +388 -0
  190. data/lib/farce/engine/truffleruby/native/tree_map.rb +51 -0
  191. data/lib/farce/engine/truffleruby/native/unsafe_tree_map.rb +350 -0
  192. data/lib/farce/engine/truffleruby/signal.rb +77 -0
  193. data/lib/farce/engine/truffleruby.rb +148 -0
  194. data/lib/farce/envelope.rb +335 -0
  195. data/lib/farce/error.rb +35 -0
  196. data/lib/farce/exchanger.rb +41 -0
  197. data/lib/farce/flag.rb +27 -0
  198. data/lib/farce/integrations/active_support/blank.rb +68 -0
  199. data/lib/farce/integrations/active_support/clock.rb +17 -0
  200. data/lib/farce/integrations/active_support/duplicable.rb +78 -0
  201. data/lib/farce/integrations/active_support/map.rb +175 -0
  202. data/lib/farce/integrations/active_support/set.rb +60 -0
  203. data/lib/farce/integrations/active_support/value_serialization.rb +17 -0
  204. data/lib/farce/integrations/active_support/vector.rb +231 -0
  205. data/lib/farce/integrations/active_support.rb +9 -0
  206. data/lib/farce/integrations/activesupport.rb +5 -0
  207. data/lib/farce/integrations/bson.rb +108 -0
  208. data/lib/farce/integrations/cbor.rb +51 -0
  209. data/lib/farce/integrations/concurrent.rb +112 -0
  210. data/lib/farce/integrations/dry-types.rb +5 -0
  211. data/lib/farce/integrations/dry_types.rb +694 -0
  212. data/lib/farce/integrations/json.rb +7 -0
  213. data/lib/farce/integrations/msgpack.rb +112 -0
  214. data/lib/farce/integrations/oj.rb +69 -0
  215. data/lib/farce/integrations/psych.rb +191 -0
  216. data/lib/farce/integrations/ractor-sharing.rb +5 -0
  217. data/lib/farce/integrations/ractor-tmvar.rb +5 -0
  218. data/lib/farce/integrations/ractor_sharing.rb +172 -0
  219. data/lib/farce/integrations/ractor_tmvar.rb +64 -0
  220. data/lib/farce/integrations/shared/to_json.rb +42 -0
  221. data/lib/farce/integrations/sorted_set.rb +11 -0
  222. data/lib/farce/integrations/weakref.rb +38 -0
  223. data/lib/farce/integrations/yajl.rb +10 -0
  224. data/lib/farce/integrations.rb +156 -0
  225. data/lib/farce/internal/_frozen_config.rb +11 -0
  226. data/lib/farce/internal/autoloads.rb +47 -0
  227. data/lib/farce/internal/blocking_priority_queue.rb +122 -0
  228. data/lib/farce/internal/converter.rb +106 -0
  229. data/lib/farce/internal/copyable.rb +31 -0
  230. data/lib/farce/internal/delegation.rb +20 -0
  231. data/lib/farce/internal/external_transaction.rb +59 -0
  232. data/lib/farce/internal/fake_ractor.rb +179 -0
  233. data/lib/farce/internal/freeze.rb +118 -0
  234. data/lib/farce/internal/inspect.rb +157 -0
  235. data/lib/farce/internal/key_lock_map.rb +29 -0
  236. data/lib/farce/internal/key_normalizer.rb +289 -0
  237. data/lib/farce/internal/lease_initialization.rb +115 -0
  238. data/lib/farce/internal/lease_map.rb +441 -0
  239. data/lib/farce/internal/lease_pool_state.rb +228 -0
  240. data/lib/farce/internal/lease_state.rb +342 -0
  241. data/lib/farce/internal/lease_waiting.rb +13 -0
  242. data/lib/farce/internal/managed_queue.rb +26 -0
  243. data/lib/farce/internal/map_value_modes.rb +227 -0
  244. data/lib/farce/internal/marshal_support.rb +227 -0
  245. data/lib/farce/internal/mixin.rb +20 -0
  246. data/lib/farce/internal/mutable_ordered_key_lock_map.rb +63 -0
  247. data/lib/farce/internal/noncopyable.rb +17 -0
  248. data/lib/farce/internal/ordered_key_lock_map.rb +69 -0
  249. data/lib/farce/internal/pool_supervisor.rb +41 -0
  250. data/lib/farce/internal/pool_worker.rb +61 -0
  251. data/lib/farce/internal/portable_transaction/reservation_entry.rb +29 -0
  252. data/lib/farce/internal/portable_transaction/strong_map_entry.rb +137 -0
  253. data/lib/farce/internal/portable_transaction/strong_map_size_entry.rb +44 -0
  254. data/lib/farce/internal/portable_transaction/tree_entry.rb +64 -0
  255. data/lib/farce/internal/portable_transaction.rb +164 -0
  256. data/lib/farce/internal/proxy_owner_notifications.rb +29 -0
  257. data/lib/farce/internal/reservation_waiting.rb +24 -0
  258. data/lib/farce/internal/scheduled_task.rb +48 -0
  259. data/lib/farce/internal/scheduler_io.rb +171 -0
  260. data/lib/farce/internal/scheduler_lifecycle.rb +314 -0
  261. data/lib/farce/internal/select_scheduler.rb +235 -0
  262. data/lib/farce/internal/storage.rb +162 -0
  263. data/lib/farce/internal/strict_lease.rb +30 -0
  264. data/lib/farce/internal/strict_lease_map.rb +20 -0
  265. data/lib/farce/internal/strict_lease_pool.rb +29 -0
  266. data/lib/farce/internal/thread_pool.rb +166 -0
  267. data/lib/farce/internal/transaction_conflict.rb +9 -0
  268. data/lib/farce/internal/transaction_freeze_guard.rb +30 -0
  269. data/lib/farce/internal/transaction_map_snapshot.rb +123 -0
  270. data/lib/farce/internal/undefined.rb +22 -0
  271. data/lib/farce/internal/unshared_lease.rb +29 -0
  272. data/lib/farce/internal/unshared_lease_pool.rb +34 -0
  273. data/lib/farce/internal/unshared_queue_waiting.rb +28 -0
  274. data/lib/farce/internal/value_serialization.rb +13 -0
  275. data/lib/farce/internal/weak_map_value_modes.rb +58 -0
  276. data/lib/farce/internal/weak_mode_manager.rb +26 -0
  277. data/lib/farce/internal.rb +129 -0
  278. data/lib/farce/lazy.rb +100 -0
  279. data/lib/farce/lazy_ref.rb +40 -0
  280. data/lib/farce/lease.rb +28 -0
  281. data/lib/farce/lease_map.rb +34 -0
  282. data/lib/farce/lease_pool.rb +29 -0
  283. data/lib/farce/lfu_map.rb +53 -0
  284. data/lib/farce/local/atom.rb +23 -0
  285. data/lib/farce/local/counter.rb +88 -0
  286. data/lib/farce/local/flag.rb +65 -0
  287. data/lib/farce/local/lazy.rb +38 -0
  288. data/lib/farce/local/lazy_ref.rb +36 -0
  289. data/lib/farce/local/lease.rb +77 -0
  290. data/lib/farce/local/lease_map.rb +80 -0
  291. data/lib/farce/local/lease_pool.rb +38 -0
  292. data/lib/farce/local/lfu_map.rb +55 -0
  293. data/lib/farce/local/lru_map.rb +62 -0
  294. data/lib/farce/local/map.rb +47 -0
  295. data/lib/farce/local/molecule.rb +45 -0
  296. data/lib/farce/local/priority_queue.rb +53 -0
  297. data/lib/farce/local/queue.rb +32 -0
  298. data/lib/farce/local/scoped.rb +166 -0
  299. data/lib/farce/local/set.rb +18 -0
  300. data/lib/farce/local/sorted_set.rb +50 -0
  301. data/lib/farce/local/timer_queue.rb +41 -0
  302. data/lib/farce/local/tree_map.rb +47 -0
  303. data/lib/farce/local/vector.rb +30 -0
  304. data/lib/farce/local/weak_atom.rb +23 -0
  305. data/lib/farce/local/weak_key_map.rb +39 -0
  306. data/lib/farce/local/weak_map.rb +39 -0
  307. data/lib/farce/local/weak_set.rb +18 -0
  308. data/lib/farce/local/weak_value_map.rb +39 -0
  309. data/lib/farce/local.rb +35 -0
  310. data/lib/farce/lock.rb +54 -0
  311. data/lib/farce/lru_map.rb +63 -0
  312. data/lib/farce/map.rb +58 -0
  313. data/lib/farce/mode_manager.rb +142 -0
  314. data/lib/farce/molecule.rb +60 -0
  315. data/lib/farce/mutable.rb +171 -0
  316. data/lib/farce/pool.rb +332 -0
  317. data/lib/farce/port.rb +134 -0
  318. data/lib/farce/priority_queue.rb +70 -0
  319. data/lib/farce/proxy/register.rb +101 -0
  320. data/lib/farce/proxy/supervisor.rb +137 -0
  321. data/lib/farce/proxy/wrapper.rb +49 -0
  322. data/lib/farce/proxy.rb +291 -0
  323. data/lib/farce/queue.rb +60 -0
  324. data/lib/farce/ractor.rb +269 -0
  325. data/lib/farce/read_write_lock.rb +256 -0
  326. data/lib/farce/reference.rb +158 -0
  327. data/lib/farce/resolv/dns.rb +42 -0
  328. data/lib/farce/resolv.rb +85 -0
  329. data/lib/farce/scheduler.rb +536 -0
  330. data/lib/farce/set.rb +39 -0
  331. data/lib/farce/shareable.rb +150 -0
  332. data/lib/farce/signal.rb +97 -0
  333. data/lib/farce/sorted_set.rb +36 -0
  334. data/lib/farce/strict/atom.rb +34 -0
  335. data/lib/farce/strict/counter.rb +10 -0
  336. data/lib/farce/strict/exchanger.rb +25 -0
  337. data/lib/farce/strict/flag.rb +10 -0
  338. data/lib/farce/strict/lazy.rb +26 -0
  339. data/lib/farce/strict/lazy_ref.rb +26 -0
  340. data/lib/farce/strict/lease.rb +27 -0
  341. data/lib/farce/strict/lease_map.rb +33 -0
  342. data/lib/farce/strict/lease_pool.rb +28 -0
  343. data/lib/farce/strict/lfu_map.rb +27 -0
  344. data/lib/farce/strict/lru_map.rb +28 -0
  345. data/lib/farce/strict/map.rb +54 -0
  346. data/lib/farce/strict/molecule.rb +16 -0
  347. data/lib/farce/strict/port.rb +40 -0
  348. data/lib/farce/strict/priority_queue.rb +20 -0
  349. data/lib/farce/strict/queue.rb +17 -0
  350. data/lib/farce/strict/set.rb +14 -0
  351. data/lib/farce/strict/sorted_set.rb +19 -0
  352. data/lib/farce/strict/timer_queue.rb +13 -0
  353. data/lib/farce/strict/tree_map.rb +27 -0
  354. data/lib/farce/strict/vector.rb +24 -0
  355. data/lib/farce/strict/weak_atom.rb +31 -0
  356. data/lib/farce/strict/weak_key_map.rb +49 -0
  357. data/lib/farce/strict/weak_map.rb +49 -0
  358. data/lib/farce/strict/weak_set.rb +14 -0
  359. data/lib/farce/strict/weak_value_map.rb +48 -0
  360. data/lib/farce/strict.rb +28 -0
  361. data/lib/farce/system.rb +40 -0
  362. data/lib/farce/thread_scheduler.rb +70 -0
  363. data/lib/farce/timer_queue.rb +66 -0
  364. data/lib/farce/transaction/atom.rb +73 -0
  365. data/lib/farce/transaction/map.rb +25 -0
  366. data/lib/farce/transaction/map_operations.rb +143 -0
  367. data/lib/farce/transaction/molecule.rb +90 -0
  368. data/lib/farce/transaction/mutable.rb +61 -0
  369. data/lib/farce/transaction/set.rb +17 -0
  370. data/lib/farce/transaction/set_operations.rb +48 -0
  371. data/lib/farce/transaction/sorted_set.rb +18 -0
  372. data/lib/farce/transaction/tree_map.rb +78 -0
  373. data/lib/farce/transaction/vector.rb +139 -0
  374. data/lib/farce/transaction/wrapper.rb +202 -0
  375. data/lib/farce/transaction.rb +343 -0
  376. data/lib/farce/tree_map.rb +56 -0
  377. data/lib/farce/unsafe/lfu_map.rb +36 -0
  378. data/lib/farce/unsafe/lru_map.rb +36 -0
  379. data/lib/farce/unsafe/tree_map.rb +21 -0
  380. data/lib/farce/unsafe.rb +29 -0
  381. data/lib/farce/unshareable.rb +67 -0
  382. data/lib/farce/unshared/atom.rb +24 -0
  383. data/lib/farce/unshared/counter.rb +10 -0
  384. data/lib/farce/unshared/flag.rb +10 -0
  385. data/lib/farce/unshared/lazy.rb +38 -0
  386. data/lib/farce/unshared/lazy_ref.rb +26 -0
  387. data/lib/farce/unshared/lease.rb +27 -0
  388. data/lib/farce/unshared/lease_map.rb +26 -0
  389. data/lib/farce/unshared/lease_pool.rb +25 -0
  390. data/lib/farce/unshared/lfu_map.rb +20 -0
  391. data/lib/farce/unshared/lru_map.rb +20 -0
  392. data/lib/farce/unshared/map.rb +49 -0
  393. data/lib/farce/unshared/molecule.rb +16 -0
  394. data/lib/farce/unshared/priority_queue.rb +16 -0
  395. data/lib/farce/unshared/queue.rb +27 -0
  396. data/lib/farce/unshared/set.rb +14 -0
  397. data/lib/farce/unshared/sorted_set.rb +28 -0
  398. data/lib/farce/unshared/timer_queue.rb +16 -0
  399. data/lib/farce/unshared/tree_map.rb +21 -0
  400. data/lib/farce/unshared/vector.rb +19 -0
  401. data/lib/farce/unshared/weak_atom.rb +31 -0
  402. data/lib/farce/unshared/weak_key_map.rb +44 -0
  403. data/lib/farce/unshared/weak_map.rb +44 -0
  404. data/lib/farce/unshared/weak_set.rb +14 -0
  405. data/lib/farce/unshared/weak_value_map.rb +43 -0
  406. data/lib/farce/unshared.rb +28 -0
  407. data/lib/farce/vector.rb +228 -0
  408. data/lib/farce/version.rb +8 -0
  409. data/lib/farce/walker/definitions.rb +186 -0
  410. data/lib/farce/walker/modification.rb +355 -0
  411. data/lib/farce/walker.rb +319 -0
  412. data/lib/farce/weak_atom.rb +121 -0
  413. data/lib/farce/weak_key_map.rb +31 -0
  414. data/lib/farce/weak_map.rb +33 -0
  415. data/lib/farce/weak_ref.rb +67 -0
  416. data/lib/farce/weak_set.rb +82 -0
  417. data/lib/farce/weak_value.rb +195 -0
  418. data/lib/farce/weak_value_map.rb +32 -0
  419. data/lib/farce.rb +519 -0
  420. metadata +435 -8
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Unshared
7
+ # A thread-safe set that retains mutable elements weakly within one Ractor.
8
+ class WeakSet < Farce::Abstract::WeakSet
9
+ include Unshareable
10
+
11
+ private def new_map(...) = Farce::Unshared::WeakMap.new(...)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Unshared
7
+ # A thread-safe map with weak values for use within one Ractor.
8
+ #
9
+ # @example Caching a mutable value without keeping it alive
10
+ # value = []
11
+ # map = Farce::Unshared::WeakValueMap.new({ result: value })
12
+ # map[:result].equal?(value) # => true
13
+ #
14
+ # # The entry can disappear once its value is collected.
15
+ # value = nil
16
+ class WeakValueMap < Abstract::WeakValueMap
17
+ include Unshareable
18
+
19
+ def initialize(
20
+ initial_mapping = nil,
21
+ normalize_keys: nil,
22
+ compare_by_identity: false,
23
+ compare_keys_by_identity: compare_by_identity,
24
+ compare_values_by_identity: compare_by_identity
25
+ )
26
+ initial_mapping = convert_entries(initial_mapping)
27
+ restoring = Internal::KeyNormalizer.restoration?(normalize_keys)
28
+ normalizer = Internal::KeyNormalizer.build(normalize_keys, shareable: false)
29
+ populate = initial_mapping && ((normalizer && !restoring) || !initial_mapping.is_a?(Hash))
30
+ @map = Internal::UnsharedWeakValueMap.new(
31
+ populate ? nil : initial_mapping,
32
+ compare_by_identity:,
33
+ compare_keys_by_identity:,
34
+ compare_values_by_identity:,
35
+ )
36
+ Internal::KeyNormalizer.install_concurrent(self, normalizer) unless restoring
37
+ initial_mapping.each { |key, value| self[key] = value } if populate
38
+ Internal::KeyNormalizer.install_concurrent(self, normalizer) if restoring
39
+ super()
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ # Thread-safe containers for values used within one Ractor.
7
+ module Unshared
8
+ include Internal::Autoloads
9
+
10
+ # @overload enfarce(object, freeze: nil)
11
+ # Converts vanilla Ruby objects into their {Farce::Unshared} equivalents.
12
+ #
13
+ # @example
14
+ # Farce::Unshared.enfarce({ foo: ["bar"] })
15
+ # # => #<Farce::Unshared::Map {foo: #<Farce::Unshared::Vector ["bar"]>}>
16
+ #
17
+ # @yield [object] Optional block, called with any object that doesn't have a specific conversion defined.
18
+ # @yieldparam object [BasicObject] the object to convert
19
+ # @yieldreturn [BasicObject] the converted object
20
+ # @param object [BasicObject] The root object to convert
21
+ # @param freeze [Boolean, nil]
22
+ # Whether to freeze the converted objects.
23
+ # If set to `nil` (default), the freezing behavior will depend on the original object's frozen state.
24
+ # @return [BasicObject] the converted object
25
+ # @see Farce.enfarce
26
+ def self.enfarce(object, **, &) = Internal::Converter.new(self, **, &).convert(object)
27
+ end
28
+ end
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ # A Ractor-shareable vector with transfer modes for mutable values.
7
+ # Values stored through this vector's mode manager are automatically unwrapped.
8
+ #
9
+ # @example Atomically updating a collection
10
+ # vector = Farce::Vector.new([[]], mode: :make_shareable)
11
+ # vector.update(0) { |jobs| jobs + [:finished] } # => [:finished]
12
+ #
13
+ # @!method append(value, mode: nil, timeout: nil)
14
+ # Append one value using the same options as {#push}.
15
+ # @param value [BasicObject] The value to append.
16
+ # @param mode [Symbol, nil] The transfer mode, or nil to use the default.
17
+ # @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
18
+ # @return [self, false] Self on success, or false on timeout.
19
+ class Vector < Farce::Abstract::Vector
20
+ include Shareable::Delegated
21
+
22
+ # @!macro modes
23
+ # @param source [Array, nil] Initial values. The source array is not retained.
24
+ # @param mode [Symbol] The default value transfer mode.
25
+ # @param compare_by_identity [Boolean] Whether values are compared by identity.
26
+ def initialize(source = nil, mode: :copy, compare_by_identity: false)
27
+ raise TypeError, "source must be an Array" unless source.nil? || source.is_a?(Array)
28
+ unless true.equal?(compare_by_identity) || false.equal?(compare_by_identity)
29
+ raise ArgumentError, "compare_by_identity must be true or false"
30
+ end
31
+
32
+ @compare_by_identity = compare_by_identity
33
+ @manager = ModeManager.new(mode:)
34
+ @vector = Internal::Vector.new(source&.map { @manager.wrap(it) }, compare_by_identity: true)
35
+ super()
36
+ end
37
+
38
+ # @api private
39
+ def transaction_wrapper(transaction) = Transaction::Vector.new(transaction, self, @vector, manager: @manager)
40
+
41
+ # @return [Symbol] The default transfer mode.
42
+ def mode = @manager.mode
43
+
44
+ # @api private
45
+ def marshal_dump
46
+ entries = @vector.snapshot.map { Internal::MarshalSupport.value(it) }
47
+ [1, entries, @manager, compare_by_identity?, frozen?]
48
+ end
49
+
50
+ # @api private
51
+ def marshal_load(data)
52
+ entries, @manager, identity, frozen = Internal::MarshalSupport.payload(data, 4)
53
+ @compare_by_identity = identity
54
+ @vector = Internal::Vector.new(compare_by_identity: true)
55
+ publish_shareable
56
+ entries.each { @vector.push(Internal::MarshalSupport.restore_value(it)) }
57
+ Internal::MarshalSupport.freeze(self, frozen)
58
+ end
59
+
60
+ # (see Farce::Abstract::Vector#compare_by_identity?)
61
+ def compare_by_identity? = @compare_by_identity
62
+
63
+ # (see Farce::Abstract::Vector#shareable_values?)
64
+ def shareable_values? = true
65
+
66
+ # (see Farce::Abstract::Vector#[])
67
+ def [](index) = @manager.unwrap(@vector[index])
68
+
69
+ # (see Farce::Abstract::Vector#[]=)
70
+ def []=(index, value)
71
+ check_frozen!
72
+ @vector[index] = @manager.wrap(value)
73
+ value
74
+ end
75
+
76
+ # (see Farce::Abstract::Vector#get)
77
+ def get(index, timeout: nil) = @manager.unwrap(@vector.get(index, timeout:))
78
+
79
+ # (see Farce::Abstract::Vector#store)
80
+ # @param mode [Symbol, nil] The transfer mode, or nil to use the default.
81
+ def store(index, value, mode: nil, timeout: nil)
82
+ check_frozen!
83
+ @manager.unwrap(@vector.store(index, @manager.wrap(value, mode:), timeout:))
84
+ end
85
+
86
+ # (see Farce::Abstract::Vector#push)
87
+ # @param mode [Symbol, nil] The transfer mode, or nil to use the default.
88
+ def push(value, mode: nil, timeout: nil)
89
+ check_frozen!
90
+ @vector.push(@manager.wrap(value, mode:), timeout:) ? self : false
91
+ end
92
+
93
+ # (see Farce::Abstract::Vector#pop)
94
+ def pop(timeout: nil) = @manager.unwrap(@vector.pop(timeout:))
95
+
96
+ # (see Farce::Abstract::Vector#swap)
97
+ # @!macro modes
98
+ # @param mode [Symbol, nil] The replacement's transfer mode, or nil to use the default.
99
+ def swap(index, replacement, mode: nil, timeout: nil)
100
+ check_frozen!
101
+ @manager.unwrap(@vector.swap(index, @manager.wrap(replacement, mode:), timeout:))
102
+ end
103
+
104
+ # (see Farce::Abstract::Vector#store_if_absent)
105
+ # @param mode [Symbol, nil] The result's transfer mode, or nil to use the default.
106
+ def store_if_absent(index, mode: nil, timeout: nil)
107
+ raise LocalJumpError, "no block given" unless block_given?
108
+ check_frozen!
109
+ @manager.unwrap(@vector.store_if_absent(index, timeout:) do
110
+ value = yield
111
+ check_frozen!
112
+ @manager.wrap(value, mode:)
113
+ end)
114
+ end
115
+
116
+ # (see Farce::Abstract::Vector#update)
117
+ # @!macro modes
118
+ # @param mode [Symbol, nil] The result's transfer mode, or nil to use the default.
119
+ def update(index, mode: nil, timeout: nil)
120
+ raise LocalJumpError, "no block given" unless block_given?
121
+ check_frozen!
122
+ @manager.unwrap(@vector.update(index, timeout:) do |current|
123
+ value = yield(@manager.unwrap(current))
124
+ check_frozen!
125
+ @manager.wrap(value, mode:)
126
+ end)
127
+ end
128
+
129
+ # (see Farce::Abstract::Vector#upsert)
130
+ # @!macro modes
131
+ # @param mode [Symbol, nil] The value transfer mode, or nil to use the default.
132
+ def upsert(index, initial, mode: nil, timeout: nil)
133
+ raise LocalJumpError, "no block given" unless block_given?
134
+ check_frozen!
135
+ @manager.unwrap(@vector.update(index, timeout:) do |current|
136
+ value = if nil.equal?(current)
137
+ initial
138
+ else
139
+ yielded = yield(@manager.unwrap(current))
140
+ check_frozen!
141
+ yielded
142
+ end
143
+ @manager.wrap(value, mode:)
144
+ end)
145
+ end
146
+
147
+ # (see Farce::Abstract::Vector#compare_and_set)
148
+ # @!macro modes
149
+ # @param mode [Symbol, nil] The replacement's transfer mode, or nil to use the default.
150
+ def compare_and_set(index, expected, replacement, mode: nil, timeout: nil)
151
+ check_frozen!
152
+ deadline = timeout_deadline(timeout)
153
+ expected = wrap_comparison(expected)
154
+ wrapped = false
155
+ loop do
156
+ current = @vector[index]
157
+ equal = values_equal?(current, expected)
158
+ check_frozen!
159
+ return false unless equal
160
+ unless wrapped
161
+ replacement = @manager.wrap(replacement, mode:)
162
+ wrapped = true
163
+ end
164
+ return true if @vector.compare_and_set(index, current, replacement, timeout: remaining_timeout(deadline))
165
+ return false if nil.equal?(current) || (deadline && Clock.now >= deadline)
166
+ end
167
+ end
168
+
169
+ # (see Farce::Abstract::Vector#wait_until_changed)
170
+ def wait_until_changed(index, expected, timeout: nil)
171
+ deadline = timeout_deadline(timeout)
172
+ expected = wrap_comparison(expected)
173
+ loop do
174
+ current = @vector[index]
175
+ return @manager.unwrap(current) unless values_equal?(current, expected)
176
+ return if deadline && Clock.now >= deadline
177
+ @vector.wait_until_changed(index, current, timeout: remaining_timeout(deadline))
178
+ end
179
+ end
180
+
181
+ # (see Farce::Abstract::Vector#wait_until_non_nil)
182
+ def wait_until_non_nil(index, timeout: nil) = @manager.unwrap(@vector.wait_until_non_nil(index, timeout:))
183
+
184
+ protected
185
+
186
+ def logical_value(value) = @manager.unwrap(value)
187
+
188
+ def build_derived_vector(values)
189
+ self.class.allocate.initialize_derived_vector(values, @manager, @compare_by_identity)
190
+ end
191
+
192
+ def initialize_derived_vector(values, manager, compare_by_identity)
193
+ @manager = manager
194
+ @compare_by_identity = compare_by_identity
195
+ @vector = Internal::Vector.new(values, compare_by_identity: true)
196
+ publish_shareable
197
+ end
198
+
199
+ attr_reader :manager
200
+
201
+ def reusable_operand_snapshot(other)
202
+ return unless other.is_a?(Farce::Vector)
203
+ return unless other.manager.equal?(@manager)
204
+ other.internal_vector.snapshot
205
+ end
206
+
207
+ private
208
+
209
+ def inspect_value(inspector, value) = super(inspector, value, @manager)
210
+ def derived_storage(value) = @manager.wrap(value)
211
+ def freeze_backend = @vector
212
+ def wrap_comparison(value) = @manager.wrap(value, mode: compare_by_identity? ? :local : :copy)
213
+ def values_equal?(left, right) = @manager.same_value?(left, right, identity: compare_by_identity?)
214
+
215
+ def timeout_deadline(timeout)
216
+ return if timeout.nil?
217
+ timeout = Float(timeout)
218
+ raise ArgumentError, "timeout must be finite and non-negative" unless timeout.finite? && !timeout.negative?
219
+ Clock.now + timeout
220
+ end
221
+
222
+ def remaining_timeout(deadline)
223
+ return unless deadline
224
+ remaining = deadline - Clock.now
225
+ remaining.negative? ? 0 : remaining
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ # @return [String] the current version of Farce
7
+ VERSION = "0.1.0"
8
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ class Walker
7
+ define(BasicObject) do |object, walker|
8
+ names = send_to(object, :instance_variables)
9
+ next object if names.empty?
10
+ unless walker.modify
11
+ names.each { walker.visit(send_to(object, :instance_variable_get, it)) }
12
+ next object
13
+ end
14
+ values = names.map { send_to(object, :instance_variable_get, it) }
15
+ walker.update(object, values) do |target, results|
16
+ names.each_with_index do |name, index|
17
+ next if send_to(target, :instance_variable_get, name).equal?(results[index])
18
+ send_to(target, :instance_variable_set, name, results[index])
19
+ end
20
+ target
21
+ end
22
+ end
23
+
24
+ define(Module) do |object, walker|
25
+ if walker.constants
26
+ inherit = walker.constants == :inherited
27
+ constant_names = Internal.walker_constants(object, inherit).reject { object.autoload?(it, inherit) }
28
+ values = constant_names.map { object.const_get(it, inherit) }
29
+ object = walker.update(object, values) do |target, results|
30
+ constant_names.each_with_index do |name, index|
31
+ target.const_set(name, results[index]) unless target.const_get(name, inherit).equal?(results[index])
32
+ end
33
+ target
34
+ end
35
+ end
36
+ if walker.class_variables
37
+ variable_names = object.class_variables(walker.class_variables == :inherited)
38
+ values = variable_names.map { object.class_variable_get(it) }
39
+ object = walker.update(object, values) do |target, results|
40
+ variable_names.each_with_index do |name, index|
41
+ unless target.class_variable_get(name).equal?(results[index])
42
+ target.class_variable_set(name,
43
+ results[index])
44
+ end
45
+ end
46
+ target
47
+ end
48
+ end
49
+ super(object, walker)
50
+ end
51
+
52
+ define(Internal::Atom, Abstract::Atom) do |object, walker|
53
+ walker.update(object, [object.value]) do |target, results|
54
+ target.value = results.first unless target.value.equal?(results.first)
55
+ target
56
+ end
57
+ end
58
+
59
+ define(Array, Internal::Vector, Abstract::Vector) do |object, walker|
60
+ unless walker.modify
61
+ values = Internal::Vector === object ? object.snapshot : object
62
+ values.each { walker.visit(it) }
63
+ next(Array === object ? super(object, walker) : object)
64
+ end
65
+ values = Internal::Vector === object ? object.snapshot : object.to_a
66
+ result = walker.update(object, values) do |target, results|
67
+ results.each_with_index { |value, index| target[index] = value unless target[index].equal?(value) }
68
+ target
69
+ end
70
+ Array === object ? super(result, walker) : result
71
+ end
72
+
73
+ define(::Set, Abstract::Set) do |object, walker|
74
+ unless walker.modify
75
+ object.each { walker.visit(it) }
76
+ next object
77
+ end
78
+ walker.update(object, object.to_a, hash_keys: !object.compare_by_identity?) do |target, results|
79
+ results.each { walker.check_hash_key(it) } unless target.compare_by_identity?
80
+ target.clear
81
+ results.each { target.add(it) }
82
+ target
83
+ end
84
+ end
85
+
86
+ define(Hash, Abstract::Map) do |object, walker|
87
+ unless walker.modify
88
+ object.each do |key, value|
89
+ walker.visit(key)
90
+ walker.visit(value)
91
+ end
92
+ next(Hash === object ? super(object, walker) : object)
93
+ end
94
+ values = object.each.flat_map { |key, value| [key, value] }
95
+ identity = Hash === object ? object.compare_by_identity? : object.compare_keys_by_identity?
96
+ result = walker.update(object, values, hash_keys: !identity, key_stride: 2) do |target, results|
97
+ results.each_slice(2) { |key, _| walker.check_hash_key(key) } unless identity
98
+ target.clear
99
+ results.each_slice(2) { |key, value| target[key] = value }
100
+ target
101
+ end
102
+ Hash === object ? super(result, walker) : result
103
+ end
104
+
105
+ define(Abstract::ConcurrentMap) do |object, walker|
106
+ values = object.each.flat_map { |key, value| [key, value] }
107
+ walker.update(object, values, hash_keys: !object.compare_keys_by_identity?, key_stride: 2) do |target, results|
108
+ if !target.compare_keys_by_identity? && values.each_slice(2).any? { |key, _| walker.changed?(key) }
109
+ results.each_slice(2) { |key, _| walker.check_hash_key(key) }
110
+ target.clear
111
+ results.each_slice(2) { |key, value| target[key] = value }
112
+ next target
113
+ end
114
+ entries = []
115
+ values.each_slice(2).with_index do |(key, value), index|
116
+ new_key, result = results[index * 2, 2]
117
+ walker.check_hash_key(new_key) unless target.compare_keys_by_identity?
118
+ if !key.equal?(new_key)
119
+ entries << [key, new_key, result]
120
+ elsif !value.equal?(result)
121
+ until target.compare_and_set(key, value, result)
122
+ value = target[key]
123
+ result = walker.visit(value)
124
+ end
125
+ end
126
+ end
127
+ entries.each { |key, _, _| target.delete(key) }
128
+ entries.each { |_, key, value| target[key] = value } # rubocop:disable Style/CombinableLoops
129
+ target
130
+ end
131
+ end
132
+
133
+ define(Abstract::LeaseMap) do |object, walker|
134
+ object.auto_lease do
135
+ values = object.keys.flat_map { |key| [key, object[key]] }
136
+ walker.update(object, values, hash_keys: !object.compare_keys_by_identity?, key_stride: 2) do |target, results|
137
+ target.auto_lease do
138
+ results.each_slice(2) { |key, _| walker.check_hash_key(key) } unless target.compare_keys_by_identity?
139
+ values.each_slice(2).with_index do |(key, _), index|
140
+ target.delete(key) unless key.equal?(results[index * 2])
141
+ end
142
+ results.each_slice(2) { |key, value| target[key] = value }
143
+ end
144
+ target
145
+ end
146
+ end
147
+ end
148
+
149
+ define(Abstract::Lease) do |object, walker|
150
+ value = object.checkout
151
+ checked_out = true
152
+ walker.update(object, [value]) do |target, results|
153
+ unless checked_out
154
+ value = target.checkout
155
+ checked_out = true
156
+ end
157
+ begin
158
+ target.checkin(results.first)
159
+ checked_out = false
160
+ target
161
+ ensure
162
+ if checked_out
163
+ target.checkin(value)
164
+ checked_out = false
165
+ end
166
+ end
167
+ end
168
+ ensure
169
+ object.checkin(value) if checked_out
170
+ checked_out = false
171
+ end
172
+
173
+ define(Proc) do |object, walker|
174
+ if Internal.rebindable?(object)
175
+ object = walker.update(object, [object.binding.receiver]) do |target, results|
176
+ Farce.rebind(target, self: results.first)
177
+ end
178
+ end
179
+ super(object, walker)
180
+ end
181
+
182
+ define(Data) do |object, walker|
183
+ walker.rebuild_data(object)
184
+ end
185
+ end
186
+ end