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
data/docs/variants.md ADDED
@@ -0,0 +1,346 @@
1
+ <!--
2
+ # @title Variants
3
+ -->
4
+
5
+ # Variants
6
+
7
+ Most Farce classes implement a set of variants as separate subclasses within module namespaces.
8
+
9
+ These namespaces and variants are:
10
+
11
+ * **Farce**: Data containers that support both shareable and unshareable content. Unshareable content is usually handled by implementing [mode support](modes.md). Keep in mind that this is also the top level namespace for Farce in general, so it contains other classes and modules not implementing variants (including the variant namespaces themselves).
12
+ * **Farce::Strict**: Variants that enforce strict sharing rules. Unshareable content will be rejected.
13
+ * **Farce::Local**: Variants that hold concrete, independent data for each [scope](scopes.md) (i.e., one copy per ractor, thread, etc). As no scope stretches across multiple ractors, these may contain unshareable content without issue.
14
+ * **Farce::Unshared**: Variants that explicitly allow unshareable content. These cannot be shared across multiple ractors.
15
+ * **Farce::Unsafe**: Variants that aren't shareable but moreover aren't guaranteed to be thread-safe either. They only exist if they give a significant performance or usability benefit despite these limitations.
16
+ * **Farce::Transaction**: Variants generated by transactions.
17
+
18
+ You can choose the variant based on your needs:
19
+
20
+ ```ruby
21
+ global_map = Farce::Map.new
22
+ local_map = Farce::Local::Map.new(scope: :thread)
23
+ ```
24
+
25
+ None of the namespaces define any instance methods, so they are safe to include:
26
+
27
+ ```ruby
28
+ class MyClass
29
+ include Farce::Strict
30
+
31
+ @register = Map.new
32
+ @cache = LRUMap.new
33
+ end
34
+ ```
35
+
36
+ ## Classes implementing Variants
37
+
38
+ <table>
39
+ <thead>
40
+ <tr>
41
+ <th></th>
42
+ <th width="120" align="center" style="text-align: center">Farce</th>
43
+ <th width="120" align="center" style="text-align: center">Strict</th>
44
+ <th width="120" align="center" style="text-align: center">Local</th>
45
+ <th width="120" align="center" style="text-align: center">Unshared</th>
46
+ <th width="120" align="center" style="text-align: center">Unsafe</th>
47
+ <th width="120" align="center" style="text-align: center">Transaction</th>
48
+ </tr>
49
+ </thead>
50
+ <tbody>
51
+ <tr>
52
+ <td><tt>Atom</tt></td>
53
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
54
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
55
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
56
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
57
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
58
+ <td align="center" style="text-align: center">✅</td> <!-- Transaction -->
59
+ </tr>
60
+ <tr>
61
+ <td><tt>Counter</tt></td>
62
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
63
+ <td align="center" style="text-align: center">🔗</td> <!-- Strict -->
64
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
65
+ <td align="center" style="text-align: center">🔗</td> <!-- Unshared -->
66
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
67
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
68
+ </tr>
69
+ <tr>
70
+ <td><tt>Exchanger</tt></td>
71
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
72
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
73
+ <td align="center" style="text-align: center">➖</td> <!-- Local -->
74
+ <td align="center" style="text-align: center">➖</td> <!-- Unshared -->
75
+ <td align="center" style="text-align: center">➖</td> <!-- Unsafe -->
76
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
77
+ </tr>
78
+ <tr>
79
+ <td><tt>Flag</tt></td>
80
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
81
+ <td align="center" style="text-align: center">🔗</td> <!-- Strict -->
82
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
83
+ <td align="center" style="text-align: center">🔗</td> <!-- Unshared -->
84
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
85
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
86
+ </tr>
87
+ <tr>
88
+ <td><tt>Lazy</tt></td>
89
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
90
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
91
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
92
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
93
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
94
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
95
+ </tr>
96
+ <tr>
97
+ <td><tt>LazyRef</tt></td>
98
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
99
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
100
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
101
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
102
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
103
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
104
+ </tr>
105
+ <tr>
106
+ <td><tt>Lease</tt></td>
107
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
108
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
109
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
110
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
111
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
112
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
113
+ </tr>
114
+ <tr>
115
+ <td><tt>LeaseMap</tt></td>
116
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
117
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
118
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
119
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
120
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
121
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
122
+ </tr>
123
+ <tr>
124
+ <td><tt>LeasePool</tt></td>
125
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
126
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
127
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
128
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
129
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
130
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
131
+ </tr>
132
+ <tr>
133
+ <td><tt>LFUMap</tt></td>
134
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
135
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
136
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
137
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
138
+ <td align="center" style="text-align: center">✅</td> <!-- Unsafe -->
139
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
140
+ </tr>
141
+ <tr>
142
+ <td><tt>LRUMap</tt></td>
143
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
144
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
145
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
146
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
147
+ <td align="center" style="text-align: center">✅</td> <!-- Unsafe -->
148
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
149
+ </tr>
150
+ <tr>
151
+ <td><tt>Molecule</tt></td>
152
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
153
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
154
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
155
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
156
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
157
+ <td align="center" style="text-align: center">✅</td> <!-- Transaction -->
158
+ </tr>
159
+ <tr>
160
+ <td><tt>Map</tt></td>
161
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
162
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
163
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
164
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
165
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
166
+ <td align="center" style="text-align: center">✅</td> <!-- Transaction -->
167
+ </tr>
168
+ <tr>
169
+ <td><tt>Mutable</tt></td>
170
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
171
+ <td align="center" style="text-align: center">➖</td> <!-- Strict -->
172
+ <td align="center" style="text-align: center">➖</td> <!-- Local -->
173
+ <td align="center" style="text-align: center">➖</td> <!-- Unshared -->
174
+ <td align="center" style="text-align: center">➖</td> <!-- Unsafe -->
175
+ <td align="center" style="text-align: center">✅</td> <!-- Transaction -->
176
+ </tr>
177
+ <tr>
178
+ <td><tt>Port</tt></td>
179
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
180
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
181
+ <td align="center" style="text-align: center">➖</td> <!-- Local -->
182
+ <td align="center" style="text-align: center">➖</td> <!-- Unshared -->
183
+ <td align="center" style="text-align: center">➖</td> <!-- Unsafe -->
184
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
185
+ </tr>
186
+ <tr>
187
+ <td><tt>PriorityQueue</tt></td>
188
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
189
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
190
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
191
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
192
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
193
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
194
+ </tr>
195
+ <tr>
196
+ <td><tt>Queue</tt></td>
197
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
198
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
199
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
200
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
201
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
202
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
203
+ </tr>
204
+ <tr>
205
+ <td><tt>Set</tt></td>
206
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
207
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
208
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
209
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
210
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
211
+ <td align="center" style="text-align: center">✅</td> <!-- Transaction -->
212
+ </tr>
213
+ <tr>
214
+ <td><tt>SortedSet</tt></td>
215
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
216
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
217
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
218
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
219
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
220
+ <td align="center" style="text-align: center">✅</td> <!-- Transaction -->
221
+ </tr>
222
+ <tr>
223
+ <td><tt>TimerQueue</tt></td>
224
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
225
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
226
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
227
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
228
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
229
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
230
+ </tr>
231
+ <tr>
232
+ <td><tt>TreeMap</tt></td>
233
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
234
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
235
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
236
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
237
+ <td align="center" style="text-align: center">✅</td> <!-- Unsafe -->
238
+ <td align="center" style="text-align: center">✅</td> <!-- Transaction -->
239
+ </tr>
240
+ <tr>
241
+ <td><tt>Vector</tt></td>
242
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
243
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
244
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
245
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
246
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
247
+ <td align="center" style="text-align: center">✅</td> <!-- Transaction -->
248
+ </tr>
249
+ <tr>
250
+ <td><tt>WeakAtom</tt></td>
251
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
252
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
253
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
254
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
255
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
256
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
257
+ </tr>
258
+ <tr>
259
+ <td><tt>WeakKeyMap</tt></td>
260
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
261
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
262
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
263
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
264
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
265
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
266
+ </tr>
267
+ <tr>
268
+ <td><tt>WeakMap</tt></td>
269
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
270
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
271
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
272
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
273
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
274
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
275
+ </tr>
276
+ <tr>
277
+ <td><tt>WeakSet</tt></td>
278
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
279
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
280
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
281
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
282
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
283
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
284
+ </tr>
285
+ <tr>
286
+ <td><tt>WeakValueMap</tt></td>
287
+ <td align="center" style="text-align: center">✅</td> <!-- Farce -->
288
+ <td align="center" style="text-align: center">✅</td> <!-- Strict -->
289
+ <td align="center" style="text-align: center">✅</td> <!-- Local -->
290
+ <td align="center" style="text-align: center">✅</td> <!-- Unshared -->
291
+ <td align="center" style="text-align: center">🔗</td> <!-- Unsafe -->
292
+ <td align="center" style="text-align: center">➖</td> <!-- Transaction -->
293
+ </tr>
294
+ </tbody>
295
+ </table>
296
+
297
+ Legend:
298
+ * ✅ Defined
299
+ * ➖ Not defined
300
+ * 🔗 Alias for another variant
301
+
302
+ ## Classes without Variants
303
+
304
+ When using the variant namespaces interchangeably, keep in mind that some classes do not come with variants.
305
+
306
+ This is obvious for classes that aren't data containers, like `Signal` or `Lock`, but also include classes like `Envelope` and `Scheduler`, which support modes, and `WeakValue` and `WeakRef`, which will choose (and switch) between the correct `WeakAtom` variants automatically.
307
+
308
+ ## Abstract Classes and Modules
309
+
310
+ Classes with variants will typically have at least one abstract class or module that they implement.
311
+ This is helpful for type checking and as a possible extension point, while doing a better job at substitution.
312
+
313
+ For example, `Farce::Map` subclasses should all implement mode support, but the same cannot be said for all `Farce::Abstract::Map` subclasses.
314
+
315
+ This makes type checking easy:
316
+
317
+ ```ruby
318
+ def self.increment_counter(counter)
319
+ case counter
320
+ when Farce::Abstract::Counter then counter.increment
321
+ when Ratomic::Counter then counter.increment(1) # required argument
322
+ else raise "Unsupported counter type"
323
+ end
324
+ end
325
+
326
+ counter = Farce::Counter.new
327
+ increment_counter(counter)
328
+
329
+ counter = Farce::Local::Counter.new(scope: :fiber)
330
+ increment_counter(counter)
331
+ ```
332
+
333
+ Abstract classes may in turn have abstract subclasses to group functionality. For instance, all `PriorityQueue` variants inherit from `Farce::Abstract::PriorityQueue`, which in turn is a subclass of `Farce::Abstract::Queue`.
334
+
335
+ A noticeably more complex abstract hierarchy exists for maps:
336
+
337
+ * `Farce::Abstract::Map`: Superclass for all map variants. Contains the almost complete set of Hash-compatible methods, as well as some additional methods like `store_if_absent`.
338
+ * `Farce::Abstract::ConcurrentMap`: Superclass for maps with an extended concurrency API, including `Farce::Map` and its variants.
339
+ * `Farce::Abstract::WeakMap`: Superclass for all `WeakMap` variants.
340
+ * `Farce::Abstract::WeakKeyMap`: Superclass for all `WeakKeyMap` variants.
341
+ * `Farce::Abstract::WeakValueMap`: Superclass for all `WeakValueMap` variants.
342
+ * `Farce::Abstract::BoundedMap`: Superclass for all map variants with an enforced size limit. All current variants enforce this limit via eviction, but a subclass rejecting writes could be a valid implementation.
343
+ * `Farce::Abstract::LFUMap`: Superclass for all Least Frequently Used (LFU) map variants.
344
+ * `Farce::Abstract::LRUMap`: Superclass for all Least Recently Used (LRU) map variants.
345
+ * `Farce::Abstract::LeaseMap`: Superclass for all `LeaseMap` variants.
346
+ * `Farce::Abstract::TreeMap`: Superclass for all `TreeMap` variants.
@@ -0,0 +1,13 @@
1
+ return if true
2
+
3
+ module Farce
4
+ # @!visibility private
5
+ module Internal # :nodoc: all
6
+ # @!visibility private
7
+ module Autoloads end
8
+ # @!visibility private
9
+ module RactorMethods end
10
+ # @!visibility private
11
+ class Atom end
12
+ end
13
+ end
@@ -0,0 +1,61 @@
1
+ # @!macro unsafe
2
+ # @note
3
+ # Instances of this class are **not thread-safe** and should not be shared concurrently.
4
+ # This does not just apply to Ractors, but also Threads and possibly Fibers.
5
+ #
6
+ # Only use them if you are absolutely certain of this and they do not leave a tightly controlled scope.
7
+ # They can provide a memory or performance advantage over their thread-safe counterparts, so they
8
+ # might be useful for hot path optimizations.
9
+ #
10
+ # Concurrent access, especially modifications, may corrupt the internal state of the object.
11
+
12
+ # @!macro modes
13
+ # Valid modes are:
14
+ # * `:copy` - The value will be copied between Ractors. This is the default mode.
15
+ # * `:make_shareable` - The value will be made Ractor-shareable using {Ractor.make_shareable}.
16
+ # * `:move` - The value will be moved between Ractors. This saves memory compared to copying, and supports values
17
+ # that can't be copied but moved (like IO objects). However, the value will no longer be accessible on the Ractor
18
+ # that pushed it.
19
+ # * `:mutable` - A {Farce::Mutable} instance will be created for the value. This isn't done recursively and thus will fail for nested unshareable values.
20
+ # * `:local` - The value will be kept local to the Ractor that pushed it. Another ractor trying to receive it will
21
+ # get an error. Useful for usage contained within a single Ractor.
22
+ # * `:proxy` - The value will be wrapped in a `Farce::Proxy` that executes calls in the original Ractor.
23
+ # * `:raise` - An error will be raised if the value is not Ractor-shareable. Useful for enforcing shareability.
24
+ # * `:dedup` - The value will be deduplicated using {Farce.dedup}, then made Ractor-shareable.
25
+ # This may update and freeze the original. Already-shareable values pass through unchanged.
26
+ # * `:shareable_copy` - The value will be copied and the copy will be made Ractor-shareable.
27
+
28
+ # @!macro scopes
29
+ # Valid scopes are:
30
+ # * `:ractor` - The value is shared by all threads within the same Ractor.
31
+ # * `:thread_group` - The value is shared by all threads within the same thread group.
32
+ # * `:thread` - The value is shared by all fibers within the same thread.
33
+ # * `:fiber_storage` - The value is shared by all fibers using the same storage.
34
+ # Unless explicitly specified, storage is inherited from the parent fiber for blocking fibers,
35
+ # but not for non-blocking fibers (such as those created by {Scheduler#schedule}).
36
+ # * `:fiber` - Each fiber has its own independent value.
37
+
38
+ # @!macro key_normalization
39
+ # @param normalize_keys [Symbol, Proc, Hash, Farce::Abstract::Map, nil]
40
+ # Converts incoming keys to their canonical stored form:
41
+ # * If a `Symbol` is provided, it will be used as a method name to call on each key.
42
+ # * If a `Proc` is provided, it will be called with each key and should return the normalized key.
43
+ # * If a `Hash` or {Farce::Abstract::Map Map} is provided, it will be used to look up the normalized key for each incoming key.
44
+
45
+ # @!macro map_initialization
46
+ # Create a map with optional initial entries.
47
+ # @param initial_mapping [Hash, Farce::Abstract::Map, #each, nil]
48
+ # The entries to store initially. Each iteration must yield a key-value pair.
49
+ # Nil creates an empty map.
50
+ # @!macro key_normalization
51
+ # @param compare_by_identity [Boolean]
52
+ # The default identity-comparison setting for keys and values. Defaults to false.
53
+ # @param compare_keys_by_identity [Boolean]
54
+ # Whether keys use object identity instead of `hash` and `eql?`.
55
+ # Defaults to `compare_by_identity`.
56
+ # @param compare_values_by_identity [Boolean]
57
+ # Whether values use object identity instead of `==`.
58
+ # Defaults to `compare_by_identity`.
59
+
60
+ # @!macro active_support
61
+ # @note This methods is only available if ActiveSupport has been loaded.
@@ -0,0 +1,46 @@
1
+ return if true
2
+
3
+ # @!visibility private
4
+ class Ractor
5
+ end
6
+
7
+ module Farce
8
+ module Ractor
9
+ # Either `Ractor::Port` or a shim for it. It is recommended to use {Farce::Port Farce::Port} instead,
10
+ # which will always be a subclass of this class, but has added safety and functionality.
11
+ class Port
12
+ # Closes the port. Sending to a closed port is prohibited. Receiving is also prohibited if there are no
13
+ # messages in its message queue. Only the Ractor which created the port is allowed to close it.
14
+ # @return [void]
15
+ def close = super
16
+
17
+ # Checks it the port is closed.
18
+ # @return [Boolean] `true` if the port is closed, `false` otherwise.
19
+ # @see #close
20
+ def closed? = super
21
+
22
+ # @overload receive
23
+ # Receives a message from the port.
24
+ # @return [BasicObject] The received message.
25
+ # @overload receive(timeout: nil)
26
+ # Receives a message from the port. Blocks until a message is available or the timeout is reached.
27
+ # @note
28
+ # Use {Farce::Port Farce::Port} instead to guarantee a timeout argument on all Ruby implementations.
29
+ # @ruby CRuby 4.1+, JRuby, TruffleRuby
30
+ # @param timeout [Numeric, nil] The timeout in seconds, or `nil` for no timeout.
31
+ # @return [BasicObject, nil] The received message, or `nil` if the timeout has been reached.
32
+ #
33
+ # @return [BasicObject]
34
+ # @raise [Farce::Ractor::ClosedError] if the port is closed and there are no messages in the queue.
35
+ def receive = super
36
+
37
+ # Sends a message over the port.
38
+ # @param message [BasicObject] The message to send.
39
+ # @param move [Boolean] Whether to move the message to the Ractor if it isn't sharable.
40
+ # @return [self]
41
+ # @raise [Farce::Ractor::ClosedError] if the port is closed.
42
+ def send(message, move: false) = super
43
+ alias << send
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # @abstract Common interface and behavior for atomic references.
8
+ #
9
+ # Concrete implementations decide how values are retained and transferred.
10
+ # A value may become `nil` without an explicit update when an implementation
11
+ # retains it weakly.
12
+ class Atom
13
+ include Internal::MarshalSupport::Atom
14
+ include Internal::Copyable
15
+ include Internal::Inspect
16
+ include Value
17
+ include Internal::ValueSerialization
18
+
19
+ # @api private
20
+ def transaction_wrapper(transaction) = Transaction::Atom.new(transaction, self, internal_atom)
21
+
22
+ # Whether comparisons use object identity instead of equality.
23
+ # @return [Boolean]
24
+ def compare_by_identity? = internal_atom.compare_by_identity?
25
+
26
+ # Return the current value without waiting for an update in progress.
27
+ # @return [BasicObject, nil] the current value
28
+ def value = internal_atom.value
29
+
30
+ # Store a new value.
31
+ # @param new_value [BasicObject, nil] the new value
32
+ # @return [BasicObject, nil] the new value
33
+ def value=(new_value)
34
+ store(new_value)
35
+ end
36
+
37
+ # Return the current value, waiting for any update in progress.
38
+ # @param timeout [Numeric, nil] the maximum number of seconds to wait
39
+ # @yield called when the timeout expires
40
+ # @return [BasicObject, nil] the current value or the fallback result
41
+ def get(timeout: nil, &) = internal_atom.get(timeout:, &)
42
+
43
+ # Store a new value, waiting for any update in progress.
44
+ # @param new_value [BasicObject, nil] the new value
45
+ # @param timeout [Numeric, nil] the maximum number of seconds to wait
46
+ # @yield called when the timeout expires
47
+ # @return [BasicObject, nil] the stored value or the fallback result
48
+ def store(new_value, timeout: nil, &) = internal_atom.store(new_value, timeout:, &)
49
+
50
+ # Replace the current value and return the previous value.
51
+ # @param new_value [BasicObject, nil] the new value
52
+ # @param timeout [Numeric, nil] the maximum number of seconds to wait
53
+ # @yield called when the timeout expires
54
+ # @return [BasicObject, nil] the previous value or the fallback result
55
+ def swap(new_value, timeout: nil, &) = internal_atom.swap(new_value, timeout:, &)
56
+
57
+ # Compute and store a value if the current value is nil.
58
+ # @param timeout [Numeric, nil] the maximum number of seconds to wait
59
+ # @yield computes the value to store when the current value is nil
60
+ # @yieldreturn [BasicObject, nil] the value to store
61
+ # @return [BasicObject, nil] the current or newly stored value, or nil when the timeout expires
62
+ def store_if_absent(timeout: nil, &) = internal_atom.store_if_absent(timeout:, &)
63
+
64
+ # Atomically replace the current value if it matches the expected value.
65
+ # @param expected [BasicObject, nil] the value to compare with the current value
66
+ # @param new_value [BasicObject, nil] the replacement value
67
+ # @param timeout [Numeric, nil] the maximum number of seconds to wait
68
+ # @return [Boolean] whether the value was replaced
69
+ def compare_and_set(expected, new_value, timeout: nil)
70
+ internal_atom.compare_and_set(expected, new_value, timeout:)
71
+ end
72
+
73
+ # Atomically replace the current value with the result of a block.
74
+ # @param timeout [Numeric, nil] the maximum number of seconds to wait
75
+ # @yield receives the current value and computes its replacement
76
+ # @yieldparam current [BasicObject, nil] the current value
77
+ # @yieldreturn [BasicObject, nil] the replacement value
78
+ # @return [BasicObject, nil] the replacement value, or nil when the timeout expires
79
+ def update(timeout: nil, &) = internal_atom.update(timeout:, &)
80
+
81
+ # Store an initial value if the current value is nil, otherwise replace it with the result of a block.
82
+ # @param initial_value [BasicObject, nil] the value to store when the current value is nil
83
+ # @param timeout [Numeric, nil] the maximum number of seconds to wait
84
+ # @yield receives a non-nil current value and computes its replacement
85
+ # @yieldparam current [BasicObject] the current value
86
+ # @yieldreturn [BasicObject, nil] the replacement value
87
+ # @return [BasicObject, nil] the replacement or initial value, or nil when the timeout expires
88
+ def upsert(initial_value, timeout: nil, &) = internal_atom.upsert(initial_value, timeout:, &)
89
+
90
+ # Wait until a block condition matches the current value.
91
+ # One timeout budget covers all checks and waits. The block is not interrupted.
92
+ # @yieldparam value [BasicObject, nil] the current value
93
+ # @yieldreturn [Boolean] whether the value matches
94
+ # @param timeout [Numeric, nil] the total seconds available
95
+ # @return [BasicObject, nil] the matching value, or nil on timeout
96
+ # @raise [LocalJumpError] if no block is given
97
+ def wait_until(timeout: nil, &) = Internal.wait_until(self, timeout:, &)
98
+
99
+ # Wait while the block returns a truthy value.
100
+ # @yieldparam value [BasicObject, nil] the current value
101
+ # @yieldreturn [BasicObject] a truthy value to keep waiting, or nil or false to stop
102
+ # @param timeout [Numeric, nil] the total seconds available
103
+ # @return [BasicObject, nil] the value when the condition becomes false, or nil on timeout
104
+ # @raise [LocalJumpError] if no block is given
105
+ def wait_while(timeout: nil)
106
+ raise LocalJumpError, "no block given" unless block_given?
107
+ wait_until(timeout:) { |value| !yield(value) }
108
+ end
109
+
110
+ # Wait while `object === value` is true.
111
+ # @param object [#===] the pattern to stop matching
112
+ # @param timeout [Numeric, nil] the total seconds available
113
+ # @return [BasicObject, nil] the first nonmatching value, or nil on timeout
114
+ def wait_while_match(object, timeout: nil)
115
+ wait_while(timeout:) { |value| object === value } # rubocop:disable Style/CaseEquality
116
+ end
117
+
118
+ # (see #wait_until_changed)
119
+ def wait_while_value(...) = wait_until_changed(...)
120
+
121
+ # Wait until the current value equals an object using the configured comparison mode.
122
+ # @param object [BasicObject, nil] the value to compare with the current value
123
+ # @param timeout [Numeric, nil] the total seconds available
124
+ # @return [BasicObject, nil] the matching value, or nil on timeout
125
+ def wait_until_value(object, timeout: nil)
126
+ wait_until(timeout:) { |value| compare_by_identity? ? object.equal?(value) : object == value }
127
+ end
128
+
129
+ # Wait until `object === value` is true.
130
+ # @param object [#===] the pattern to match
131
+ # @param timeout [Numeric, nil] the total seconds available
132
+ # @return [BasicObject, nil] the matching value, or nil on timeout
133
+ def wait_until_match(object, timeout: nil)
134
+ wait_until(timeout:) { |value| object === value } # rubocop:disable Style/CaseEquality
135
+ end
136
+
137
+ # Wait until the current value no longer matches an expected value.
138
+ # @param expected [BasicObject, nil] the value to compare with the current value
139
+ # @param timeout [Numeric, nil] the maximum number of seconds to wait
140
+ # @yield called when the timeout expires
141
+ # @return [BasicObject, nil] the changed value or the fallback result
142
+ def wait_until_changed(expected, timeout: nil, &)
143
+ internal_atom.wait_until_changed(expected, timeout:, &)
144
+ end
145
+
146
+ # Wait until the current value is not nil.
147
+ # @param timeout [Numeric, nil] the maximum number of seconds to wait
148
+ # @yield called when the timeout expires
149
+ # @return [BasicObject, nil] the non-nil value or the fallback result
150
+ def wait_until_non_nil(timeout: nil, &) = internal_atom.wait_until_non_nil(timeout:, &)
151
+
152
+ # @api private
153
+ def inspect_with(inspector)
154
+ super do
155
+ yield if block_given?
156
+ inspect_value(inspector)
157
+ end
158
+ end
159
+
160
+ protected
161
+
162
+ def internal_atom = @atom
163
+
164
+ private
165
+
166
+ def inspect_value(inspector, prefix = "value=")
167
+ if prefix
168
+ inspector.breakable
169
+ inspector.text(prefix)
170
+ end
171
+ inspector.object(value)
172
+ end
173
+
174
+ def initialize_copy(other)
175
+ super
176
+ source = other.internal_atom
177
+ copy = source.class.new(source.value, compare_by_identity: source.compare_by_identity?)
178
+ if is_a?(Local::Scoped)
179
+ Internal::Storage.scope(scope)[self] = copy
180
+ else
181
+ @atom = copy
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end