farce 0.0.1.alpha2-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +26 -0
  3. data/CONTRIBUTING.md +71 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +1524 -0
  6. data/SECURITY.md +10 -0
  7. data/docs/benchmarks.md +185 -0
  8. data/docs/gems/dry-types.md +290 -0
  9. data/docs/gems/msgpack.md +70 -0
  10. data/docs/gems/ractor-shim.md +63 -0
  11. data/docs/modes.md +628 -0
  12. data/docs/scopes.md +649 -0
  13. data/docs/variants.md +346 -0
  14. data/lib/farce/_yard/internal.rb +13 -0
  15. data/lib/farce/_yard/macros.rb +61 -0
  16. data/lib/farce/_yard/ractor.rb +46 -0
  17. data/lib/farce/abstract/atom.rb +186 -0
  18. data/lib/farce/abstract/bounded_map.rb +232 -0
  19. data/lib/farce/abstract/collection.rb +151 -0
  20. data/lib/farce/abstract/concurrent_map.rb +381 -0
  21. data/lib/farce/abstract/counter.rb +193 -0
  22. data/lib/farce/abstract/duplicable_map.rb +229 -0
  23. data/lib/farce/abstract/exchanger.rb +26 -0
  24. data/lib/farce/abstract/flag.rb +71 -0
  25. data/lib/farce/abstract/lazy.rb +115 -0
  26. data/lib/farce/abstract/lease.rb +104 -0
  27. data/lib/farce/abstract/lease_map.rb +261 -0
  28. data/lib/farce/abstract/lease_pool.rb +91 -0
  29. data/lib/farce/abstract/lfu_map.rb +20 -0
  30. data/lib/farce/abstract/lru_map.rb +25 -0
  31. data/lib/farce/abstract/map.rb +345 -0
  32. data/lib/farce/abstract/molecule.rb +245 -0
  33. data/lib/farce/abstract/port.rb +74 -0
  34. data/lib/farce/abstract/priority_queue.rb +117 -0
  35. data/lib/farce/abstract/queue.rb +269 -0
  36. data/lib/farce/abstract/scheduler.rb +111 -0
  37. data/lib/farce/abstract/set.rb +910 -0
  38. data/lib/farce/abstract/sorted_set.rb +172 -0
  39. data/lib/farce/abstract/timer_queue.rb +136 -0
  40. data/lib/farce/abstract/tree_map.rb +269 -0
  41. data/lib/farce/abstract/value.rb +68 -0
  42. data/lib/farce/abstract/vector.rb +1126 -0
  43. data/lib/farce/abstract/weak_atom.rb +32 -0
  44. data/lib/farce/abstract/weak_key_map.rb +12 -0
  45. data/lib/farce/abstract/weak_map.rb +13 -0
  46. data/lib/farce/abstract/weak_set.rb +12 -0
  47. data/lib/farce/abstract/weak_value_map.rb +12 -0
  48. data/lib/farce/abstract.rb +17 -0
  49. data/lib/farce/atom.rb +293 -0
  50. data/lib/farce/class_mirror.rb +87 -0
  51. data/lib/farce/clock.rb +121 -0
  52. data/lib/farce/config.rb +229 -0
  53. data/lib/farce/counter.rb +71 -0
  54. data/lib/farce/deduper.rb +122 -0
  55. data/lib/farce/engine/jruby/bounded_map.rb +314 -0
  56. data/lib/farce/engine/jruby/fiber_scheduler.jar +0 -0
  57. data/lib/farce/engine/jruby/fiber_scheduler.rb +119 -0
  58. data/lib/farce/engine/jruby/lease_waiting.rb +19 -0
  59. data/lib/farce/engine/jruby/map.rb +505 -0
  60. data/lib/farce/engine/jruby/mutable_numeric_copy.rb +42 -0
  61. data/lib/farce/engine/jruby/signal.rb +147 -0
  62. data/lib/farce/engine/jruby.rb +63 -0
  63. data/lib/farce/engine/jvm/concurrent_weak_registry.rb +55 -0
  64. data/lib/farce/engine/jvm/counter.rb +102 -0
  65. data/lib/farce/engine/jvm/extension.rb +32 -0
  66. data/lib/farce/engine/jvm/farce.jar +0 -0
  67. data/lib/farce/engine/jvm/flag.rb +79 -0
  68. data/lib/farce/engine/jvm/priority_queue.rb +217 -0
  69. data/lib/farce/engine/jvm/tree_map.rb +350 -0
  70. data/lib/farce/engine/jvm/types.rb +180 -0
  71. data/lib/farce/engine/jvm.rb +19 -0
  72. data/lib/farce/engine/ruby/3.4/fiber_scheduler.rb +20 -0
  73. data/lib/farce/engine/ruby/3.4/port.rb +186 -0
  74. data/lib/farce/engine/ruby/3.4/ractor_methods.rb +26 -0
  75. data/lib/farce/engine/ruby/3.4/ractor_selector.rb +92 -0
  76. data/lib/farce/engine/ruby/3.4/vault.rb +56 -0
  77. data/lib/farce/engine/ruby/4.0/port.rb +19 -0
  78. data/lib/farce/engine/ruby/4.0/ractor_methods.rb +20 -0
  79. data/lib/farce/engine/ruby/4.0/ractor_selector.rb +108 -0
  80. data/lib/farce/engine/ruby/4.0/vault.rb +74 -0
  81. data/lib/farce/engine/ruby/4.1/port.rb +21 -0
  82. data/lib/farce/engine/ruby/4.1/ractor_methods.rb +22 -0
  83. data/lib/farce/engine/ruby/4.1/ractor_selector.rb +25 -0
  84. data/lib/farce/engine/ruby/4.1/vault.rb +5 -0
  85. data/lib/farce/engine/ruby/fiber_scheduler.rb +32 -0
  86. data/lib/farce/engine/ruby/key_lock_map.rb +28 -0
  87. data/lib/farce/engine/ruby/shared/lease.rb +26 -0
  88. data/lib/farce/engine/ruby/shared/lease_pool.rb +24 -0
  89. data/lib/farce/engine/ruby/shared/main_scheduler.rb +9 -0
  90. data/lib/farce/engine/ruby/shared/parallel_scheduler.rb +9 -0
  91. data/lib/farce/engine/ruby/shared/proxy_owner.rb +31 -0
  92. data/lib/farce/engine/ruby/shared/ractor_methods.rb +34 -0
  93. data/lib/farce/engine/ruby/shared/ractor_selector.rb +328 -0
  94. data/lib/farce/engine/ruby/shared/strict_map.rb +13 -0
  95. data/lib/farce/engine/ruby/shared/unshared_vector.rb +14 -0
  96. data/lib/farce/engine/ruby/shared/vault.rb +144 -0
  97. data/lib/farce/engine/ruby/shared/vault_weak_map.rb +336 -0
  98. data/lib/farce/engine/ruby/shared/weak_atom.rb +54 -0
  99. data/lib/farce/engine/ruby/shared/weak_map.rb +413 -0
  100. data/lib/farce/engine/ruby.rb +130 -0
  101. data/lib/farce/engine/shared/atom.rb +10 -0
  102. data/lib/farce/engine/shared/exchanger.rb +130 -0
  103. data/lib/farce/engine/shared/identity_key.rb +22 -0
  104. data/lib/farce/engine/shared/lease.rb +10 -0
  105. data/lib/farce/engine/shared/lease_pool.rb +10 -0
  106. data/lib/farce/engine/shared/main_scheduler.rb +20 -0
  107. data/lib/farce/engine/shared/map_key_coordination.rb +226 -0
  108. data/lib/farce/engine/shared/parallel_scheduler.rb +9 -0
  109. data/lib/farce/engine/shared/port.rb +44 -0
  110. data/lib/farce/engine/shared/portable_bounded_map.rb +619 -0
  111. data/lib/farce/engine/shared/proxy_owner.rb +43 -0
  112. data/lib/farce/engine/shared/queue.rb +233 -0
  113. data/lib/farce/engine/shared/ractor_methods.rb +73 -0
  114. data/lib/farce/engine/shared/rebindable.rb +15 -0
  115. data/lib/farce/engine/shared/strict_atom.rb +73 -0
  116. data/lib/farce/engine/shared/strict_map.rb +117 -0
  117. data/lib/farce/engine/shared/strict_queue_values.rb +27 -0
  118. data/lib/farce/engine/shared/strict_tree_map.rb +56 -0
  119. data/lib/farce/engine/shared/transaction_map_backend.rb +20 -0
  120. data/lib/farce/engine/shared/trie.rb +317 -0
  121. data/lib/farce/engine/shared/trie_builder.rb +199 -0
  122. data/lib/farce/engine/shared/unshareable.rb +14 -0
  123. data/lib/farce/engine/shared/unshared_atom.rb +256 -0
  124. data/lib/farce/engine/shared/unshared_priority_queue.rb +9 -0
  125. data/lib/farce/engine/shared/unshared_queue.rb +18 -0
  126. data/lib/farce/engine/shared/unshared_signal.rb +21 -0
  127. data/lib/farce/engine/shared/unshared_vector.rb +377 -0
  128. data/lib/farce/engine/shared/unshared_weak_atom.rb +30 -0
  129. data/lib/farce/engine/shared/unshared_weak_map.rb +445 -0
  130. data/lib/farce/engine/shared/vault.rb +31 -0
  131. data/lib/farce/engine/shared/vector.rb +83 -0
  132. data/lib/farce/engine/shared/weak_atom/base.rb +189 -0
  133. data/lib/farce/engine/shared/weak_atom.rb +20 -0
  134. data/lib/farce/engine/shared/weak_map/cell.rb +99 -0
  135. data/lib/farce/engine/shared/weak_map/index.rb +249 -0
  136. data/lib/farce/engine/shared/weak_map/lock.rb +80 -0
  137. data/lib/farce/engine/shared/weak_map/reference.rb +33 -0
  138. data/lib/farce/engine/shared.rb +63 -0
  139. data/lib/farce/engine/truffleruby/fiber_scheduler.rb +13 -0
  140. data/lib/farce/engine/truffleruby/lock.rb +121 -0
  141. data/lib/farce/engine/truffleruby/map.rb +656 -0
  142. data/lib/farce/engine/truffleruby/native/counter.rb +105 -0
  143. data/lib/farce/engine/truffleruby/native/flag.rb +77 -0
  144. data/lib/farce/engine/truffleruby/native/ordered_array_support.rb +67 -0
  145. data/lib/farce/engine/truffleruby/native/priority_queue.rb +388 -0
  146. data/lib/farce/engine/truffleruby/native/tree_map.rb +51 -0
  147. data/lib/farce/engine/truffleruby/native/unsafe_tree_map.rb +350 -0
  148. data/lib/farce/engine/truffleruby/signal.rb +77 -0
  149. data/lib/farce/engine/truffleruby.rb +148 -0
  150. data/lib/farce/envelope.rb +335 -0
  151. data/lib/farce/error.rb +35 -0
  152. data/lib/farce/exchanger.rb +41 -0
  153. data/lib/farce/flag.rb +27 -0
  154. data/lib/farce/integrations/active_support/blank.rb +68 -0
  155. data/lib/farce/integrations/active_support/clock.rb +17 -0
  156. data/lib/farce/integrations/active_support/duplicable.rb +78 -0
  157. data/lib/farce/integrations/active_support/map.rb +175 -0
  158. data/lib/farce/integrations/active_support/set.rb +60 -0
  159. data/lib/farce/integrations/active_support/value_serialization.rb +17 -0
  160. data/lib/farce/integrations/active_support/vector.rb +231 -0
  161. data/lib/farce/integrations/active_support.rb +9 -0
  162. data/lib/farce/integrations/activesupport.rb +5 -0
  163. data/lib/farce/integrations/bson.rb +108 -0
  164. data/lib/farce/integrations/cbor.rb +51 -0
  165. data/lib/farce/integrations/concurrent.rb +112 -0
  166. data/lib/farce/integrations/dry-types.rb +5 -0
  167. data/lib/farce/integrations/dry_types.rb +694 -0
  168. data/lib/farce/integrations/json.rb +7 -0
  169. data/lib/farce/integrations/msgpack.rb +112 -0
  170. data/lib/farce/integrations/oj.rb +69 -0
  171. data/lib/farce/integrations/psych.rb +191 -0
  172. data/lib/farce/integrations/ractor-sharing.rb +5 -0
  173. data/lib/farce/integrations/ractor-tmvar.rb +5 -0
  174. data/lib/farce/integrations/ractor_sharing.rb +172 -0
  175. data/lib/farce/integrations/ractor_tmvar.rb +64 -0
  176. data/lib/farce/integrations/shared/to_json.rb +42 -0
  177. data/lib/farce/integrations/sorted_set.rb +11 -0
  178. data/lib/farce/integrations/weakref.rb +38 -0
  179. data/lib/farce/integrations/yajl.rb +10 -0
  180. data/lib/farce/integrations.rb +156 -0
  181. data/lib/farce/internal/_frozen_config.rb +11 -0
  182. data/lib/farce/internal/autoloads.rb +47 -0
  183. data/lib/farce/internal/blocking_priority_queue.rb +122 -0
  184. data/lib/farce/internal/converter.rb +106 -0
  185. data/lib/farce/internal/copyable.rb +31 -0
  186. data/lib/farce/internal/delegation.rb +20 -0
  187. data/lib/farce/internal/external_transaction.rb +59 -0
  188. data/lib/farce/internal/fake_ractor.rb +179 -0
  189. data/lib/farce/internal/freeze.rb +118 -0
  190. data/lib/farce/internal/inspect.rb +157 -0
  191. data/lib/farce/internal/key_lock_map.rb +29 -0
  192. data/lib/farce/internal/key_normalizer.rb +289 -0
  193. data/lib/farce/internal/lease_initialization.rb +115 -0
  194. data/lib/farce/internal/lease_map.rb +441 -0
  195. data/lib/farce/internal/lease_pool_state.rb +228 -0
  196. data/lib/farce/internal/lease_state.rb +342 -0
  197. data/lib/farce/internal/lease_waiting.rb +13 -0
  198. data/lib/farce/internal/managed_queue.rb +26 -0
  199. data/lib/farce/internal/map_value_modes.rb +227 -0
  200. data/lib/farce/internal/marshal_support.rb +227 -0
  201. data/lib/farce/internal/mixin.rb +20 -0
  202. data/lib/farce/internal/mutable_ordered_key_lock_map.rb +63 -0
  203. data/lib/farce/internal/noncopyable.rb +17 -0
  204. data/lib/farce/internal/ordered_key_lock_map.rb +69 -0
  205. data/lib/farce/internal/pool_supervisor.rb +41 -0
  206. data/lib/farce/internal/pool_worker.rb +61 -0
  207. data/lib/farce/internal/portable_transaction/reservation_entry.rb +29 -0
  208. data/lib/farce/internal/portable_transaction/strong_map_entry.rb +137 -0
  209. data/lib/farce/internal/portable_transaction/strong_map_size_entry.rb +44 -0
  210. data/lib/farce/internal/portable_transaction/tree_entry.rb +64 -0
  211. data/lib/farce/internal/portable_transaction.rb +164 -0
  212. data/lib/farce/internal/proxy_owner_notifications.rb +29 -0
  213. data/lib/farce/internal/reservation_waiting.rb +24 -0
  214. data/lib/farce/internal/scheduled_task.rb +48 -0
  215. data/lib/farce/internal/scheduler_io.rb +171 -0
  216. data/lib/farce/internal/scheduler_lifecycle.rb +314 -0
  217. data/lib/farce/internal/select_scheduler.rb +235 -0
  218. data/lib/farce/internal/storage.rb +162 -0
  219. data/lib/farce/internal/strict_lease.rb +30 -0
  220. data/lib/farce/internal/strict_lease_map.rb +20 -0
  221. data/lib/farce/internal/strict_lease_pool.rb +29 -0
  222. data/lib/farce/internal/thread_pool.rb +166 -0
  223. data/lib/farce/internal/transaction_conflict.rb +9 -0
  224. data/lib/farce/internal/transaction_freeze_guard.rb +30 -0
  225. data/lib/farce/internal/transaction_map_snapshot.rb +123 -0
  226. data/lib/farce/internal/undefined.rb +22 -0
  227. data/lib/farce/internal/unshared_lease.rb +29 -0
  228. data/lib/farce/internal/unshared_lease_pool.rb +34 -0
  229. data/lib/farce/internal/unshared_queue_waiting.rb +28 -0
  230. data/lib/farce/internal/value_serialization.rb +13 -0
  231. data/lib/farce/internal/weak_map_value_modes.rb +58 -0
  232. data/lib/farce/internal/weak_mode_manager.rb +26 -0
  233. data/lib/farce/internal.rb +129 -0
  234. data/lib/farce/lazy.rb +100 -0
  235. data/lib/farce/lazy_ref.rb +40 -0
  236. data/lib/farce/lease.rb +28 -0
  237. data/lib/farce/lease_map.rb +34 -0
  238. data/lib/farce/lease_pool.rb +29 -0
  239. data/lib/farce/lfu_map.rb +53 -0
  240. data/lib/farce/local/atom.rb +23 -0
  241. data/lib/farce/local/counter.rb +88 -0
  242. data/lib/farce/local/flag.rb +65 -0
  243. data/lib/farce/local/lazy.rb +38 -0
  244. data/lib/farce/local/lazy_ref.rb +36 -0
  245. data/lib/farce/local/lease.rb +77 -0
  246. data/lib/farce/local/lease_map.rb +80 -0
  247. data/lib/farce/local/lease_pool.rb +38 -0
  248. data/lib/farce/local/lfu_map.rb +55 -0
  249. data/lib/farce/local/lru_map.rb +62 -0
  250. data/lib/farce/local/map.rb +47 -0
  251. data/lib/farce/local/molecule.rb +45 -0
  252. data/lib/farce/local/priority_queue.rb +53 -0
  253. data/lib/farce/local/queue.rb +32 -0
  254. data/lib/farce/local/scoped.rb +166 -0
  255. data/lib/farce/local/set.rb +18 -0
  256. data/lib/farce/local/sorted_set.rb +50 -0
  257. data/lib/farce/local/timer_queue.rb +41 -0
  258. data/lib/farce/local/tree_map.rb +47 -0
  259. data/lib/farce/local/vector.rb +30 -0
  260. data/lib/farce/local/weak_atom.rb +23 -0
  261. data/lib/farce/local/weak_key_map.rb +39 -0
  262. data/lib/farce/local/weak_map.rb +39 -0
  263. data/lib/farce/local/weak_set.rb +18 -0
  264. data/lib/farce/local/weak_value_map.rb +39 -0
  265. data/lib/farce/local.rb +35 -0
  266. data/lib/farce/lock.rb +54 -0
  267. data/lib/farce/lru_map.rb +63 -0
  268. data/lib/farce/map.rb +58 -0
  269. data/lib/farce/mode_manager.rb +142 -0
  270. data/lib/farce/molecule.rb +60 -0
  271. data/lib/farce/mutable.rb +171 -0
  272. data/lib/farce/pool.rb +332 -0
  273. data/lib/farce/port.rb +134 -0
  274. data/lib/farce/priority_queue.rb +70 -0
  275. data/lib/farce/proxy/register.rb +101 -0
  276. data/lib/farce/proxy/supervisor.rb +137 -0
  277. data/lib/farce/proxy/wrapper.rb +49 -0
  278. data/lib/farce/proxy.rb +291 -0
  279. data/lib/farce/queue.rb +60 -0
  280. data/lib/farce/ractor.rb +269 -0
  281. data/lib/farce/read_write_lock.rb +256 -0
  282. data/lib/farce/reference.rb +158 -0
  283. data/lib/farce/resolv/dns.rb +42 -0
  284. data/lib/farce/resolv.rb +85 -0
  285. data/lib/farce/scheduler.rb +536 -0
  286. data/lib/farce/set.rb +39 -0
  287. data/lib/farce/shareable.rb +150 -0
  288. data/lib/farce/signal.rb +97 -0
  289. data/lib/farce/sorted_set.rb +36 -0
  290. data/lib/farce/strict/atom.rb +34 -0
  291. data/lib/farce/strict/counter.rb +10 -0
  292. data/lib/farce/strict/exchanger.rb +25 -0
  293. data/lib/farce/strict/flag.rb +10 -0
  294. data/lib/farce/strict/lazy.rb +26 -0
  295. data/lib/farce/strict/lazy_ref.rb +26 -0
  296. data/lib/farce/strict/lease.rb +27 -0
  297. data/lib/farce/strict/lease_map.rb +33 -0
  298. data/lib/farce/strict/lease_pool.rb +28 -0
  299. data/lib/farce/strict/lfu_map.rb +27 -0
  300. data/lib/farce/strict/lru_map.rb +28 -0
  301. data/lib/farce/strict/map.rb +54 -0
  302. data/lib/farce/strict/molecule.rb +16 -0
  303. data/lib/farce/strict/port.rb +40 -0
  304. data/lib/farce/strict/priority_queue.rb +20 -0
  305. data/lib/farce/strict/queue.rb +17 -0
  306. data/lib/farce/strict/set.rb +14 -0
  307. data/lib/farce/strict/sorted_set.rb +19 -0
  308. data/lib/farce/strict/timer_queue.rb +13 -0
  309. data/lib/farce/strict/tree_map.rb +27 -0
  310. data/lib/farce/strict/vector.rb +24 -0
  311. data/lib/farce/strict/weak_atom.rb +31 -0
  312. data/lib/farce/strict/weak_key_map.rb +49 -0
  313. data/lib/farce/strict/weak_map.rb +49 -0
  314. data/lib/farce/strict/weak_set.rb +14 -0
  315. data/lib/farce/strict/weak_value_map.rb +48 -0
  316. data/lib/farce/strict.rb +28 -0
  317. data/lib/farce/system.rb +40 -0
  318. data/lib/farce/thread_scheduler.rb +70 -0
  319. data/lib/farce/timer_queue.rb +66 -0
  320. data/lib/farce/transaction/atom.rb +73 -0
  321. data/lib/farce/transaction/map.rb +25 -0
  322. data/lib/farce/transaction/map_operations.rb +143 -0
  323. data/lib/farce/transaction/molecule.rb +90 -0
  324. data/lib/farce/transaction/mutable.rb +61 -0
  325. data/lib/farce/transaction/set.rb +17 -0
  326. data/lib/farce/transaction/set_operations.rb +48 -0
  327. data/lib/farce/transaction/sorted_set.rb +18 -0
  328. data/lib/farce/transaction/tree_map.rb +78 -0
  329. data/lib/farce/transaction/vector.rb +139 -0
  330. data/lib/farce/transaction/wrapper.rb +202 -0
  331. data/lib/farce/transaction.rb +343 -0
  332. data/lib/farce/tree_map.rb +56 -0
  333. data/lib/farce/unsafe/lfu_map.rb +36 -0
  334. data/lib/farce/unsafe/lru_map.rb +36 -0
  335. data/lib/farce/unsafe/tree_map.rb +21 -0
  336. data/lib/farce/unsafe.rb +29 -0
  337. data/lib/farce/unshareable.rb +67 -0
  338. data/lib/farce/unshared/atom.rb +24 -0
  339. data/lib/farce/unshared/counter.rb +10 -0
  340. data/lib/farce/unshared/flag.rb +10 -0
  341. data/lib/farce/unshared/lazy.rb +38 -0
  342. data/lib/farce/unshared/lazy_ref.rb +26 -0
  343. data/lib/farce/unshared/lease.rb +27 -0
  344. data/lib/farce/unshared/lease_map.rb +26 -0
  345. data/lib/farce/unshared/lease_pool.rb +25 -0
  346. data/lib/farce/unshared/lfu_map.rb +20 -0
  347. data/lib/farce/unshared/lru_map.rb +20 -0
  348. data/lib/farce/unshared/map.rb +49 -0
  349. data/lib/farce/unshared/molecule.rb +16 -0
  350. data/lib/farce/unshared/priority_queue.rb +16 -0
  351. data/lib/farce/unshared/queue.rb +27 -0
  352. data/lib/farce/unshared/set.rb +14 -0
  353. data/lib/farce/unshared/sorted_set.rb +28 -0
  354. data/lib/farce/unshared/timer_queue.rb +16 -0
  355. data/lib/farce/unshared/tree_map.rb +21 -0
  356. data/lib/farce/unshared/vector.rb +19 -0
  357. data/lib/farce/unshared/weak_atom.rb +31 -0
  358. data/lib/farce/unshared/weak_key_map.rb +44 -0
  359. data/lib/farce/unshared/weak_map.rb +44 -0
  360. data/lib/farce/unshared/weak_set.rb +14 -0
  361. data/lib/farce/unshared/weak_value_map.rb +43 -0
  362. data/lib/farce/unshared.rb +28 -0
  363. data/lib/farce/vector.rb +228 -0
  364. data/lib/farce/version.rb +8 -0
  365. data/lib/farce/walker/definitions.rb +186 -0
  366. data/lib/farce/walker/modification.rb +355 -0
  367. data/lib/farce/walker.rb +319 -0
  368. data/lib/farce/weak_atom.rb +121 -0
  369. data/lib/farce/weak_key_map.rb +31 -0
  370. data/lib/farce/weak_map.rb +33 -0
  371. data/lib/farce/weak_ref.rb +67 -0
  372. data/lib/farce/weak_set.rb +82 -0
  373. data/lib/farce/weak_value.rb +195 -0
  374. data/lib/farce/weak_value_map.rb +32 -0
  375. data/lib/farce.rb +519 -0
  376. metadata +420 -0
@@ -0,0 +1,179 @@
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 FakeRactor
9
+ State = Struct.new(:id, :name, :main_thread, :default_port, :status, :mutex, :monitors, :source_location)
10
+
11
+ GROUPS = {}.compare_by_identity
12
+ RACTOR_MAPPING = ObjectSpace::WeakKeyMap.new
13
+ STATES = ObjectSpace::WeakKeyMap.new
14
+
15
+ class Main
16
+ include Farce::Ractor
17
+ include Freeze::Unfreezable
18
+ extend RactorMethods
19
+
20
+ private_class_method :new
21
+ INSTANCE = Freeze.publish(new)
22
+ DEFAULT_PORT = BasePort.new
23
+
24
+ def default_port = DEFAULT_PORT
25
+ def inspect = "#<Farce::Ractor#1 running>"
26
+ def join = sleep
27
+ def main? = true
28
+ def monitor(_) = true # rubocop:disable Naming/PredicateMethod
29
+ def name = nil
30
+ def receive(...) = DEFAULT_PORT.receive(...)
31
+ def send(...) = DEFAULT_PORT.send(...)
32
+ def unmonitor(_) = self
33
+ def value = sleep
34
+
35
+ alias << send
36
+ alias recv receive
37
+ end
38
+
39
+ class NotMain
40
+ include Farce::Ractor
41
+ include Freeze::Unfreezable
42
+ extend RactorMethods
43
+
44
+ @@ractor_counter = 1
45
+ @@ractor_counter_mutex = Mutex.new
46
+
47
+ def initialize(*, name: nil, &block)
48
+ raise ArgumentError, "must be called with a block" unless block_given?
49
+ group = ThreadGroup.new
50
+ state = State.new(
51
+ default_port: BasePort.new,
52
+ id: @@ractor_counter_mutex.synchronize { @@ractor_counter += 1 },
53
+ monitors: ::Set.new,
54
+ mutex: Mutex.new,
55
+ name: name,
56
+ source_location: -(block.source_location&.join(":") || "(unknown)"),
57
+ status: :running,
58
+ )
59
+
60
+ STATES[self] = state
61
+ GROUPS[group] = self
62
+
63
+ state.main_thread = Thread.new do # rubocop:disable Lint/UselessSetterCall
64
+ current = Thread.current
65
+ group.add(current)
66
+ current.freeze
67
+
68
+ RACTOR_MAPPING[current] = self
69
+ result = instance_exec(*, &block)
70
+
71
+ # this will trigger a fiber scheduler main loop if one is set
72
+ Fiber.set_scheduler(nil) if Fiber.respond_to?(:set_scheduler)
73
+ state.status = :exited
74
+ result
75
+ rescue Exception => e # rubocop:disable Lint/RescueException
76
+ state.status = :aborted
77
+ raise e
78
+ ensure
79
+ state.mutex.synchronize do
80
+ state.monitors.each do |monitor|
81
+ monitor << state.status
82
+ end
83
+ state.monitors = nil
84
+ end
85
+ group.list.each { it.kill unless it == current }
86
+ GROUPS.delete(group)
87
+ end
88
+ end
89
+
90
+ def [](key)
91
+ raise "Cannot get ractor local storage for non-current ractor" unless self == FakeRactor.current
92
+ Farce::Ractor[key]
93
+ end
94
+
95
+ def []=(key, value)
96
+ raise "Cannot set ractor local storage for non-current ractor" unless self == FakeRactor.current
97
+ Farce::Ractor[key] = value
98
+ end
99
+
100
+ def monitor(port) # rubocop:disable Naming/PredicateMethod
101
+ state = STATES[self]
102
+
103
+ if state.status == :running
104
+ state.mutex.synchronize do
105
+ next if state.status != :running
106
+ state.monitors << port
107
+ return true
108
+ end
109
+ end
110
+
111
+ port << state.status
112
+ false
113
+ end
114
+
115
+ def unmonitor(port)
116
+ state = STATES[self]
117
+ state.mutex.synchronize { state.monitors&.delete(port) }
118
+ self
119
+ end
120
+
121
+ def inspect
122
+ return super unless state = STATES[self]
123
+ status = state.status == :running ? "running" : "terminated"
124
+ "#<Farce::Ractor##{state.id}#{" #{state.name}" if state.name} #{state.source_location} #{status}>"
125
+ end
126
+
127
+ def join
128
+ STATES[self].main_thread.join
129
+ self
130
+ end
131
+
132
+ def send(...)
133
+ default_port.send(...)
134
+ self
135
+ end
136
+
137
+ def default_port = STATES[self].default_port
138
+ def main? = false
139
+ def name = STATES[self].name
140
+ def receive(...) = default_port.receive(...)
141
+ def value = STATES[self].main_thread.value
142
+
143
+ alias << send
144
+ alias recv receive
145
+ alias to_s inspect
146
+
147
+ undef dup
148
+ undef clone
149
+ end
150
+
151
+ def self.current
152
+ # JRuby fibers expose a backing thread with a different thread group.
153
+ thread = Internal.storage_thread(Thread.current)
154
+ override = Storage.thread(thread)[:current_ractor]
155
+ override || GROUPS.fetch(thread.group) { Main::INSTANCE }
156
+ end
157
+
158
+ def self.main_thread = STATES[current]&.main_thread || Thread.main
159
+
160
+ # Fibers on this Ruby thread share the override. New threads do not inherit it.
161
+ def self.with_current(ractor)
162
+ storage = Storage.thread
163
+ previous = storage[:current_ractor]
164
+ storage[:current_ractor] = ractor
165
+ yield
166
+ ensure
167
+ storage[:current_ractor] = previous
168
+ end
169
+
170
+ def self.threads
171
+ group = Internal.storage_thread(Thread.current).group
172
+ return group.list if GROUPS.key?(group)
173
+ list = ThreadGroup::Default.list
174
+ list += group.list if group != ThreadGroup::Default
175
+ list
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal
7
+ # Shared implementation for the explicit frozen-state policies in {Shareable}.
8
+ module Freeze
9
+ # Structurally freeze a Ruby facade, then validate and publish its object graph.
10
+ # This deliberately bypasses an override that controls logical frozen state.
11
+ def self.publish(object)
12
+ Object.instance_method(:freeze).bind_call(object)
13
+ ::Ractor.make_shareable(object) if Internal.native_ractors?
14
+ object
15
+ end
16
+
17
+ def self.check(object)
18
+ return object unless object.frozen?
19
+
20
+ raise FrozenError.new("can't modify frozen #{object.class}", receiver: object)
21
+ end
22
+
23
+ # Delegate logical frozen state to storage owned by the wrapper.
24
+ module Delegated
25
+ def freeze
26
+ backend = freeze_backend
27
+ raise "#{self.class} is not initialized" unless backend
28
+
29
+ backend.freeze
30
+ self
31
+ end
32
+
33
+ def frozen?
34
+ backend = freeze_backend
35
+ backend ? backend.frozen? : Object.instance_method(:frozen?).bind_call(self)
36
+ end
37
+
38
+ private
39
+
40
+ def check_frozen! = Internal::Freeze.check(self)
41
+
42
+ def publish_shareable_copy(other, operation:, freeze: nil)
43
+ logically_frozen = operation == :clone && (freeze.nil? ? other.frozen? : freeze)
44
+ self.freeze if logically_frozen
45
+ publish_shareable
46
+ end
47
+ end
48
+
49
+ # Track one logical frozen state shared by all storage resolved through a facade.
50
+ module Tracked
51
+ def initialize(...)
52
+ @farce_freeze_state = Internal::Flag.new(false)
53
+ super
54
+ end
55
+
56
+ def freeze
57
+ @farce_freeze_state.set
58
+ self
59
+ end
60
+
61
+ def frozen?
62
+ state = @farce_freeze_state
63
+ state ? state.value : Object.instance_method(:frozen?).bind_call(self)
64
+ end
65
+
66
+ private
67
+
68
+ def check_frozen! = Internal::Freeze.check(self)
69
+
70
+ def initialize_copy(other, **)
71
+ super
72
+ state = other.instance_variable_get(:@farce_freeze_state)
73
+ guard = state.respond_to?(:native_flag) ? state.class : Internal::Flag
74
+ @farce_freeze_state = guard.new(false)
75
+ end
76
+
77
+ def publish_shareable_copy(other, operation:, freeze: nil)
78
+ logically_frozen = operation == :clone && (freeze.nil? ? other.frozen? : freeze)
79
+ self.freeze if logically_frozen
80
+ publish_shareable
81
+ end
82
+ end
83
+
84
+ # Keep a live service structurally published while rejecting logical freezing.
85
+ module Unfreezable
86
+ def freeze = raise(TypeError, "#{self.class} cannot be frozen")
87
+ def frozen? = false
88
+
89
+ private
90
+
91
+ def publish_shareable_copy(_other, operation:, freeze: nil)
92
+ self.freeze if operation == :clone && freeze == true
93
+ publish_shareable
94
+ end
95
+ end
96
+
97
+ # Let a purpose-built native object publish itself after payload initialization.
98
+ module Native
99
+ private
100
+
101
+ def publish_shareable = self
102
+
103
+ def publish_shareable_copy(other, operation:, freeze: nil)
104
+ logically_frozen = operation == :clone && (freeze.nil? ? other.frozen? : freeze)
105
+ self.freeze if logically_frozen
106
+ publish_shareable
107
+ end
108
+ end
109
+
110
+ # Keep ordinary Ruby frozen state as the public state.
111
+ module Immutable
112
+ private
113
+
114
+ def publish_shareable_copy(*) = publish_shareable
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal
7
+ module Inspect
8
+ module Mixin
9
+ def inspect
10
+ inspector = StringInspector.create
11
+ inspector.inspect(self)
12
+ end
13
+
14
+ def pretty_print(pp)
15
+ inspector = PrettyPrinter.create(pp)
16
+ inspector.object(self)
17
+ end
18
+
19
+ def pretty_print_cycle(pp)
20
+ inspector = PrettyPrinter.create(pp)
21
+ inspector.object_with_address(self)
22
+ end
23
+
24
+ def inspect_with(inspector, &)
25
+ return inspector.object_group(self, &) if block_given?
26
+ inspector.object_with_address(self)
27
+ end
28
+ end
29
+
30
+ class Inspector
31
+ def self.current = Storage.fiber[-name]
32
+ def self.create = current || new
33
+ def initialize = @seen = ::Set.new.compare_by_identity
34
+ def attributes(attributes, ...) = attributes.each { attribute(_1, _2, ...) }
35
+ def object_group(object, &) = group("#<#{object.class.name}", ">", &)
36
+ def object_with_address(object) = text(Kernel.instance_method(:to_s).bind_call(object))
37
+
38
+ def activate
39
+ name = -self.class.name
40
+ old = Storage.fiber[name]
41
+
42
+ begin
43
+ Storage.fiber[name] = self
44
+ yield
45
+ ensure
46
+ Storage.fiber[name] = old
47
+ end
48
+ end
49
+
50
+ def attribute(key, value, mode_manager = nil)
51
+ breakable
52
+ text "#{key}="
53
+ object(value, mode_manager)
54
+ end
55
+
56
+ def from_envelope(envelope, prefix = nil)
57
+ if envelope.owned?
58
+ text(prefix) if prefix
59
+ object(envelope.value)
60
+ else
61
+ text(envelope.claimed? ? "claimed" : "unclaimed")
62
+ end
63
+ self
64
+ end
65
+
66
+ def object(object, mode_manager = nil)
67
+ return object_with_address(object) if @seen.include?(object)
68
+ return from_envelope(object) if mode_manager&.managed_envelope?(object)
69
+ return foreign_inspect(object) unless object.is_a?(Mixin)
70
+
71
+ activate do
72
+ @seen << object
73
+ object.inspect_with(self)
74
+ end
75
+
76
+ self
77
+ end
78
+
79
+ def hash_pair(key, ...)
80
+ if Symbol === key
81
+ key = key.to_s.inspect if key.inspect.match?(%r{\A:["$@!]|[%&*+\-/<=>@\]^`|~]\z})
82
+ text("#{key}: ")
83
+ else
84
+ text("#{key.inspect} => ")
85
+ end
86
+ block_given? ? yield : object(...)
87
+ end
88
+ end
89
+
90
+ class StringInspector < Inspector
91
+ def initialize
92
+ @output = +""
93
+ super
94
+ end
95
+
96
+ def breakable(str = " ") = text(str)
97
+ def text(str) = @output << str
98
+ def to_s = -@output
99
+
100
+ def inspect(object)
101
+ previous_output = @output
102
+ @output = +""
103
+ object(object)
104
+ to_s
105
+ ensure
106
+ @output = previous_output
107
+ end
108
+
109
+ def foreign_inspect(object)
110
+ text(object.inspect)
111
+ rescue StandardError
112
+ object_with_address(object)
113
+ end
114
+
115
+ def group(before = nil, after = nil)
116
+ text(before) if before
117
+ yield
118
+ text(after) if after
119
+ end
120
+
121
+ def seplist(list, sep = nil, iter_method = :each)
122
+ sep ||= -> { text(", ") }
123
+ first = true
124
+ list.__send__(iter_method) do |*args|
125
+ sep.call unless first
126
+ first = false
127
+ yield(*args)
128
+ end
129
+ end
130
+ end
131
+
132
+ class PrettyPrinter < Inspector
133
+ def self.create(pp) = current&.pp == pp ? current : new(pp)
134
+
135
+ attr_reader :pp
136
+
137
+ Internal.delegate(self, :@pp, :text, :object_group, :breakable, :seplist)
138
+
139
+ def initialize(pp)
140
+ @pp = pp
141
+ super()
142
+ end
143
+
144
+ def foreign_inspect(object)
145
+ pp.pp(object)
146
+ rescue StandardError
147
+ object_with_address(object)
148
+ end
149
+
150
+ def group(...) = @pp.group(1, ...)
151
+ end
152
+
153
+ def self.append_features(base) = base.include(Mixin)
154
+ private_constant :Mixin, :Inspector, :PrettyPrinter
155
+ end
156
+ end
157
+ 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
+ # Coordinate equal keys without retaining entries after an operation finishes.
9
+ class KeyLockMap
10
+ include Freeze::Unfreezable
11
+
12
+ def initialize(registry_class:, **comparison_options)
13
+ @registry = registry_class.new(**comparison_options)
14
+ Freeze.publish(self) if @registry.ractor_shareable?
15
+ end
16
+
17
+ def synchronize(key)
18
+ raise LocalJumpError, "no block given" unless block_given?
19
+
20
+ completed = Object.new
21
+ catch(completed) do
22
+ # Nonlocal exit releases the reservation without publishing a value.
23
+ # The block result stays with the caller, even for shareable registries.
24
+ @registry.store_if_absent(key) { throw completed, yield }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end