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,445 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ require "farce/engine/shared/weak_map/lock"
6
+ require "farce/engine/shared/weak_map/cell"
7
+ require "farce/engine/shared/weak_map/index"
8
+
9
+ module Farce
10
+ # @!visibility private
11
+ module Internal # :nodoc: all
12
+ class UnsharedMapBase < Abstract::ConcurrentMap
13
+ def initialize(
14
+ initial_mapping = nil,
15
+ compare_by_identity: false,
16
+ compare_keys_by_identity: compare_by_identity,
17
+ compare_values_by_identity: compare_by_identity
18
+ )
19
+ validate_boolean(compare_by_identity, "compare_by_identity")
20
+ validate_boolean(compare_keys_by_identity, "compare_keys_by_identity")
21
+ validate_boolean(compare_values_by_identity, "compare_values_by_identity")
22
+ raise TypeError, "initial mapping must be a Hash" unless initial_mapping.nil? || initial_mapping.is_a?(Hash)
23
+
24
+ super()
25
+
26
+ @compare_keys_by_identity = compare_keys_by_identity
27
+ @compare_values_by_identity = compare_values_by_identity
28
+ @cell_class = weak_values? ? UnsharedWeakValueMapCell : UnsharedWeakMapCell
29
+
30
+ index_class = if weak_keys?
31
+ compare_keys_by_identity? ? UnsharedWeakIdentityMapIndex : UnsharedWeakKeyMapIndex
32
+ else
33
+ compare_keys_by_identity? ? UnsharedStrongIdentityMapIndex : UnsharedStrongKeyMapIndex
34
+ end
35
+ @index = index_class.new
36
+ initial_mapping&.each { self[it.first] = it.last }
37
+ end
38
+
39
+ def [](key) = read_unreserved(key)[1]
40
+
41
+ def check_mutation = check_frozen!
42
+
43
+ def prepare_mutation_key(key)
44
+ check_frozen!
45
+ canonical_key(key)
46
+ end
47
+
48
+ def []=(key, value)
49
+ store(key, value)
50
+ end
51
+
52
+ def fetch(*arguments)
53
+ unless arguments.length.between?(1, 2)
54
+ raise ArgumentError, "wrong number of arguments (given #{arguments.length}, expected 1..2)"
55
+ end
56
+
57
+ key, default = arguments
58
+ default_given = arguments.length == 2
59
+ warn "block supersedes default value argument", uplevel: 1 if block_given? && default_given
60
+ present, value = read(key, nil)
61
+ return value if present
62
+ return yield(key) if block_given?
63
+ return default if default_given
64
+
65
+ raise KeyError.new("key not found: #{key.inspect}", receiver: self, key: key)
66
+ end
67
+
68
+ def get(key, timeout: nil, &fallback)
69
+ deadline = timeout_deadline(timeout)
70
+ _present, value, timed_out = read(key, deadline)
71
+ timed_out ? fallback&.call : value
72
+ end
73
+
74
+ def store(key, value, timeout: nil, &fallback)
75
+ check_frozen!
76
+ deadline = timeout_deadline(timeout)
77
+ completed, result = with_entry(key, deadline, create: true, mutating: true) do |_present, _current, entry|
78
+ value if entry.store(value)
79
+ end
80
+ completed ? result : fallback&.call
81
+ end
82
+
83
+ def swap(key, replacement, timeout: nil, &fallback)
84
+ check_frozen!
85
+ deadline = timeout_deadline(timeout)
86
+ completed, result = with_entry(key, deadline, create: true, mutating: true) do |present, current, entry|
87
+ stored = entry.store(replacement)
88
+ current if stored && present
89
+ end
90
+ completed ? result : fallback&.call
91
+ end
92
+
93
+ def store_if_absent(key, timeout: nil)
94
+ raise LocalJumpError, "no block given" unless block_given?
95
+ check_frozen!
96
+
97
+ deadline = timeout_deadline(timeout)
98
+ completed, result = with_entry(key, deadline, create: true, mutating: true) do |present, current, entry|
99
+ next current if present
100
+ value = yield
101
+ check_frozen!
102
+ value if entry.store(value)
103
+ end
104
+ completed ? result : nil
105
+ end
106
+
107
+ def compare_and_set(key, expected, replacement, timeout: nil)
108
+ check_frozen!
109
+ deadline = timeout_deadline(timeout)
110
+ completed, result = with_entry(key, deadline, create: false, mutating: true) do |present, current, entry|
111
+ next false unless present && values_equal?(current, expected)
112
+
113
+ check_frozen!
114
+ entry.store(replacement)
115
+ end
116
+ completed && result
117
+ end
118
+
119
+ def update(key, timeout: nil)
120
+ raise LocalJumpError, "no block given" unless block_given?
121
+ check_frozen!
122
+
123
+ deadline = timeout_deadline(timeout)
124
+ completed, result = with_entry(key, deadline, create: true, mutating: true) do |_present, current, entry|
125
+ value = yield(current)
126
+ check_frozen!
127
+ value if entry.store(value)
128
+ end
129
+ completed ? result : nil
130
+ end
131
+
132
+ def upsert(key, initial_value, timeout: nil)
133
+ raise LocalJumpError, "no block given" unless block_given?
134
+ check_frozen!
135
+
136
+ deadline = timeout_deadline(timeout)
137
+ completed, result = with_entry(key, deadline, create: true, mutating: true) do |present, current, entry|
138
+ value = present ? yield(current) : initial_value
139
+ check_frozen!
140
+ value if entry.store(value)
141
+ end
142
+ completed ? result : nil
143
+ end
144
+
145
+ # Yield presence and value under the entry reservation.
146
+ # MAP_KEEP and MAP_DELETE are control results. Other results replace the value.
147
+ # Return whether a change committed.
148
+ def modify(key) # rubocop:disable Naming/PredicateMethod
149
+ raise LocalJumpError, "no block given" unless block_given?
150
+ check_frozen!
151
+ _, result = with_entry(key, nil, create: true, mutating: true) do |present, current, entry, index|
152
+ value = yield(present, current)
153
+ check_frozen!
154
+ if MAP_KEEP.equal?(value)
155
+ false
156
+ elsif MAP_DELETE.equal?(value)
157
+ next false unless present
158
+ index.remove(key, entry)
159
+ entry.retire
160
+ else
161
+ entry.store(value)
162
+ end
163
+ end
164
+ !!result
165
+ end
166
+
167
+ def wait_until_changed(key, expected, timeout: nil, &fallback)
168
+ wait_for_value(key, expected, timeout_deadline(timeout), fallback, non_nil: false)
169
+ end
170
+
171
+ def wait_until_non_nil(key, timeout: nil, &fallback)
172
+ wait_for_value(key, nil, timeout_deadline(timeout), fallback, non_nil: true)
173
+ end
174
+
175
+ def key?(key) = read(key, nil).first
176
+ def compare_keys_by_identity? = @compare_keys_by_identity
177
+ def compare_values_by_identity? = @compare_values_by_identity
178
+ def size = entries_snapshot.size
179
+ def keys = entries_snapshot.map(&:first)
180
+
181
+ def each(&block)
182
+ return enum_for(__callee__) { size } unless block
183
+ entries_snapshot.each { block.call(it) }
184
+ self
185
+ end
186
+ alias each_pair each
187
+
188
+ def each_live
189
+ return enum_for(__method__) { size } unless block_given?
190
+ cursor = @index.live_cursor
191
+ begin
192
+ while true
193
+ begin
194
+ entry = @index.next_live(cursor)
195
+ rescue StopIteration
196
+ break
197
+ end
198
+ next unless entry.reserve(nil) == :acquired
199
+ pair = begin
200
+ state, present, value = entry.state
201
+ alive, key = entry.lookup_key if state == :ok && present
202
+ [key, value] if alive
203
+ ensure
204
+ entry.release
205
+ end
206
+ yield pair if pair
207
+ end
208
+ ensure
209
+ @index.close_cursor(cursor)
210
+ end
211
+ self
212
+ end
213
+
214
+ def each_key(&block)
215
+ return enum_for(__callee__) { size } unless block
216
+ entries_snapshot.each { block.call(it.first) }
217
+ self
218
+ end
219
+
220
+ def each_value(&block)
221
+ return enum_for(__callee__) { size } unless block
222
+ entries_snapshot.each { block.call(it.last) }
223
+ self
224
+ end
225
+
226
+ def delete(key)
227
+ check_frozen!
228
+ completed, result = with_entry(key, nil, create: false, mutating: true) do |present, current, entry, index|
229
+ next nil unless present
230
+ index.remove(key, entry)
231
+ entry.retire
232
+ current if present
233
+ end
234
+ result if completed
235
+ end
236
+
237
+ def getkey(key)
238
+ @index.sweep_one
239
+ entry, created = @index.resolve(key)
240
+ return if !entry || created == :timed_out
241
+
242
+ alive, stored_key = entry.lookup_key
243
+ stored_key if alive
244
+ end
245
+
246
+ def clear
247
+ check_frozen!
248
+ @index.clear
249
+ self
250
+ end
251
+
252
+ private
253
+
254
+ def check_frozen! = Internal::Freeze.check(self)
255
+
256
+ def canonical_key(key)
257
+ return key unless String === key && !key.frozen? && !compare_keys_by_identity?
258
+
259
+ String.instance_method(:-@).bind_call(key)
260
+ end
261
+
262
+ def read_unreserved(key)
263
+ @index.sweep_one
264
+ loop do
265
+ entry, = @index.resolve(key)
266
+ return [false, nil] unless entry
267
+
268
+ state, present, value = entry.state
269
+ return [present, value] if state == :ok
270
+
271
+ @index.remove(key, entry)
272
+ entry.retire
273
+ end
274
+ end
275
+
276
+ def read(key, deadline)
277
+ completed, result = with_entry(key, deadline, create: false) { |present, value| [present, value] }
278
+ completed ? [*result, false] : [false, nil, result == :timed_out]
279
+ end
280
+
281
+ def with_entry(key, deadline, create:, mutating: false)
282
+ key = canonical_key(key)
283
+ @index.sweep_one
284
+ while true
285
+ entry, created = @index.resolve(key, deadline:, create:) do |key_reference|
286
+ cell = @cell_class.new(key_reference)
287
+ cell.reserve(nil)
288
+ cell
289
+ end
290
+ return [false, :timed_out] if created == :timed_out
291
+ unless entry
292
+ check_frozen! if mutating
293
+ return [true, yield(false, nil, nil, @index)]
294
+ end
295
+
296
+ unless created
297
+ status = entry.reserve(deadline)
298
+ return [false, :timed_out] if status == :timed_out
299
+ next if status == :retired
300
+ end
301
+
302
+ retry_entry = false
303
+ begin
304
+ state, present, current = entry.state
305
+ if state == :ok
306
+ check_frozen! if mutating
307
+ return [true, yield(present, current, entry, @index)]
308
+ end
309
+ retry_entry = true
310
+ ensure
311
+ begin
312
+ if created && !entry.present?
313
+ @index.remove(key, entry)
314
+ entry.retire
315
+ end
316
+ ensure
317
+ entry.release
318
+ end
319
+ end
320
+ if retry_entry
321
+ @index.remove(key, entry)
322
+ entry.retire
323
+ end
324
+ end
325
+ end
326
+
327
+ def entries_snapshot
328
+ entries = @index.snapshot
329
+ pairs = entries.filter_map do |entry|
330
+ status = entry.reserve(nil)
331
+ next unless status == :acquired
332
+
333
+ begin
334
+ state, present, value = entry.state
335
+ next unless state == :ok && present
336
+ alive, key = entry.lookup_key
337
+ [key, value] if alive
338
+ ensure
339
+ entry.release
340
+ end
341
+ end
342
+ @index.sweep(entries)
343
+ pairs
344
+ end
345
+
346
+ def wait_for_value(key, expected, deadline, fallback, non_nil:)
347
+ key = String.instance_method(:-@).bind_call(key) if String === key && !key.frozen? && !compare_keys_by_identity?
348
+ while true
349
+ @index.sweep_one
350
+ observed = @index.change_signal.generation
351
+ entry, timed_out = @index.resolve(key, deadline:)
352
+ return fallback&.call if timed_out == :timed_out
353
+
354
+ unless entry
355
+ return nil unless values_equal?(nil, expected)
356
+ return fallback&.call unless signal_changed?(@index.change_signal, observed, deadline)
357
+ next
358
+ end
359
+
360
+ changed = entry.change_generation
361
+ status = entry.reserve(deadline)
362
+ return fallback&.call if status == :timed_out
363
+ next if status == :retired
364
+
365
+ begin
366
+ alive, stored_key = entry.lookup_key
367
+ state, present, current = entry.state
368
+ ensure
369
+ entry.release
370
+ end
371
+ next if !alive || state == :retired || state == :dead
372
+ # Retain the canonical key across the wait, including for an equal
373
+ # lookup object. Otherwise GC could orphan the entry's change signal.
374
+ key = stored_key
375
+ current = nil unless present
376
+ return current if non_nil ? !current.nil? : !values_equal?(current, expected)
377
+ return fallback&.call unless entry.wait_for_change?(changed, deadline)
378
+ end
379
+ end
380
+
381
+ def signal_changed?(signal, observed, deadline)
382
+ timeout = deadline - Clock.now if deadline
383
+ return false if timeout && !timeout.positive?
384
+
385
+ timed_out = Object.new
386
+ result = signal.wait(observed, timeout:) { timed_out }
387
+ !timed_out.equal?(result)
388
+ end
389
+
390
+ def timeout_deadline(timeout)
391
+ return if timeout.nil?
392
+
393
+ timeout = Float(timeout)
394
+ if !timeout.finite? || timeout.negative?
395
+ raise ArgumentError, "timeout must be a finite, non-negative number or nil"
396
+ end
397
+ Clock.now + timeout
398
+ end
399
+
400
+ def values_equal?(left, right)
401
+ return BasicObject.instance_method(:equal?).bind_call(left, right) if compare_values_by_identity?
402
+ left == right
403
+ end
404
+
405
+ def validate_boolean(value, name)
406
+ equal = BasicObject.instance_method(:equal?)
407
+ return if equal.bind_call(value, true) || equal.bind_call(value, false)
408
+ raise ArgumentError, "#{name} must be true or false"
409
+ end
410
+ end
411
+ private_constant :UnsharedMapBase
412
+
413
+ unless const_defined?(:UnsharedMap, false)
414
+ class UnsharedMap < UnsharedMapBase
415
+ def transaction_snapshot = PortableTransaction.snapshot(self, :strong_map)
416
+ def transaction_size_snapshot(size) = PortableTransaction::StrongMapSizeEntry.new(self, size)
417
+ def transaction_size = PortableTransaction::StrongMapEntry.size(@index)
418
+ def transaction_read(key) = read_unreserved(key)
419
+
420
+ def transaction_pairs
421
+ PortableTransaction::StrongMapEntry.pairs(@index)
422
+ end
423
+ end
424
+ end
425
+
426
+ class UnsharedWeakKeyMap < UnsharedMapBase
427
+ def weak_keys? = true
428
+ end
429
+
430
+ class UnsharedWeakValueMap < UnsharedMapBase
431
+ def weak_values? = true
432
+ end
433
+
434
+ class UnsharedWeakMap < UnsharedMapBase
435
+ def weak_keys? = true
436
+ def weak_values? = true
437
+ end
438
+
439
+ unless RUBY_ENGINE == "ruby"
440
+ WeakKeyMap = UnsharedWeakKeyMap
441
+ WeakValueMap = UnsharedWeakValueMap
442
+ WeakMap = UnsharedWeakMap
443
+ end
444
+ end
445
+ end
@@ -0,0 +1,31 @@
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
+ class Vault
9
+ include Freeze::Unfreezable
10
+
11
+ def initialize = @data = ObjectSpace::WeakKeyMap.new
12
+ def move_in(key, value) = @data[key] = value
13
+ def copy_in(key, value) = @data[key] = value.dup
14
+ def move_out(key) = @data.delete(key)
15
+ def copy_out(key) = @data[key].dup
16
+
17
+ def same_value?(left, right, identity: false, right_stored: true)
18
+ left = @data[left]
19
+ right = @data[right] if right_stored
20
+ return BasicObject.instance_method(:equal?).bind_call(left, right) if identity
21
+
22
+ !!(left == right)
23
+ end
24
+
25
+ def delete(key)
26
+ @data.delete(key)
27
+ nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,83 @@
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
+ class Vector < UnsharedVector
9
+ def initialize(source = nil, **)
10
+ source.each { check_value(it) } if source.is_a?(Array)
11
+ super
12
+ end
13
+
14
+ def []=(index, value)
15
+ check_frozen!
16
+ check_value(value)
17
+ super
18
+ end
19
+
20
+ def store(index, value, **)
21
+ check_frozen!
22
+ check_value(value)
23
+ super
24
+ end
25
+
26
+ def push(value, **)
27
+ check_frozen!
28
+ check_value(value)
29
+ super
30
+ end
31
+
32
+ def swap(index, replacement, **)
33
+ check_frozen!
34
+ check_value(replacement)
35
+ super
36
+ end
37
+
38
+ def compare_and_set(index, expected, replacement, **)
39
+ check_frozen!
40
+ check_value(replacement)
41
+ super
42
+ end
43
+
44
+ def store_if_absent(index, **)
45
+ raise LocalJumpError, "no block given" unless block_given?
46
+ check_frozen!
47
+ super do
48
+ value = yield
49
+ check_frozen!
50
+ check_value(value)
51
+ end
52
+ end
53
+
54
+ def update(index, **)
55
+ raise LocalJumpError, "no block given" unless block_given?
56
+ check_frozen!
57
+ super do |current|
58
+ value = yield(current)
59
+ check_frozen!
60
+ check_value(value)
61
+ end
62
+ end
63
+
64
+ def upsert(index, initial, **)
65
+ raise LocalJumpError, "no block given" unless block_given?
66
+ check_frozen!
67
+ check_value(initial)
68
+ super do |current|
69
+ value = yield(current)
70
+ check_frozen!
71
+ check_value(value)
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def check_value(value)
78
+ raise Ractor::IsolationError, "value is not Ractor-shareable" unless Ractor.shareable?(value)
79
+ value
80
+ end
81
+ end
82
+ end
83
+ end