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,289 @@
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 KeyNormalizer
9
+ class CanonicalEntries < Array
10
+ end
11
+
12
+ Restoration = Data.define(:value)
13
+
14
+ private_constant :CanonicalEntries
15
+
16
+ class SymbolNormalizer
17
+ attr_reader :value
18
+
19
+ def initialize(method)
20
+ @value = method
21
+ freeze
22
+ end
23
+
24
+ def call(key) = key.public_send(@value)
25
+ end
26
+
27
+ class ProcNormalizer
28
+ def initialize(callable)
29
+ @callable = callable
30
+ freeze
31
+ end
32
+
33
+ def call(key) = @callable.call(key)
34
+ end
35
+
36
+ class LookupNormalizer
37
+ attr_reader :source
38
+
39
+ def initialize(source)
40
+ @source = source
41
+ freeze
42
+ end
43
+
44
+ def call(key) = @source.fetch(key, key)
45
+ end
46
+
47
+ module CommonOperations
48
+ private def normalize_key(key) = @key_normalizer.call(key)
49
+
50
+ def [](key) = super(normalize_key(key))
51
+
52
+ def []=(key, value)
53
+ super(normalize_key(key), value)
54
+ end
55
+
56
+ def delete(key) = super(normalize_key(key))
57
+ def getkey(key) = super(normalize_key(key))
58
+ def key?(key) = super(normalize_key(key))
59
+
60
+ def fetch(*arguments)
61
+ return super unless arguments.length.between?(1, 2)
62
+
63
+ original, default = arguments
64
+ canonical = normalize_key(original)
65
+ warn "block supersedes default value argument", uplevel: 1 if block_given? && arguments.length == 2
66
+ super(canonical) do
67
+ return yield(original) if block_given?
68
+ return default if arguments.length == 2
69
+ raise KeyError.new("key not found: #{original.inspect}", receiver: self, key: original)
70
+ end
71
+ end
72
+ end
73
+
74
+ class ConcurrentMap
75
+ def initialize(map, normalizer)
76
+ @map = map
77
+ @normalizer = normalizer
78
+ Internal::Freeze.publish(self) if Ractor.shareable?(map)
79
+ end
80
+
81
+ # @api private
82
+ def transaction_source = @map
83
+
84
+ # @api private
85
+ def transaction_key(key) = @normalizer.call(key)
86
+
87
+ def freeze
88
+ @map.freeze
89
+ self
90
+ end
91
+
92
+ def frozen? = @map.frozen?
93
+
94
+ def [](key) = @map[@normalizer.call(key)]
95
+
96
+ def []=(key, value)
97
+ @map[@normalizer.call(key)] = value
98
+ end
99
+
100
+ def fetch(key, &) = @map.fetch(@normalizer.call(key), &)
101
+ def get(key, ...) = @map.get(@normalizer.call(key), ...)
102
+ def store(key, value, ...) = @map.store(@normalizer.call(key), value, ...)
103
+ def swap(key, value, ...) = @map.swap(@normalizer.call(key), value, ...)
104
+ def store_if_absent(key, ...) = @map.store_if_absent(@normalizer.call(key), ...)
105
+
106
+ def compare_and_set(key, expected, replacement, ...)
107
+ @map.compare_and_set(@normalizer.call(key), expected, replacement, ...)
108
+ end
109
+
110
+ def update(key, ...) = @map.update(@normalizer.call(key), ...)
111
+ def modify(key, ...) = @map.modify(@normalizer.call(key), ...)
112
+ def upsert(key, initial, ...) = @map.upsert(@normalizer.call(key), initial, ...)
113
+ def delete(key) = @map.delete(@normalizer.call(key))
114
+ def key?(key) = @map.key?(@normalizer.call(key))
115
+ def getkey(key) = @map.getkey(@normalizer.call(key))
116
+ def wait_until_changed(key, expected, ...) = @map.wait_until_changed(@normalizer.call(key), expected, ...)
117
+ def wait_until_non_nil(key, ...) = @map.wait_until_non_nil(@normalizer.call(key), ...)
118
+ def normalize_external_key(key) = @map.normalize_external_key(@normalizer.call(key))
119
+ def check_mutation = @map.check_mutation
120
+
121
+ def get_prepared(...) = @map.get_prepared(...)
122
+ def store_prepared(...) = @map.store_prepared(...)
123
+ def swap_prepared(...) = @map.swap_prepared(...)
124
+ def update_prepared(...) = @map.update_prepared(...)
125
+ def assignment_prepared(...) = @map.assignment_prepared(...)
126
+ def wait_until_changed_prepared(...) = @map.wait_until_changed_prepared(...)
127
+ def size = @map.size
128
+ def keys = @map.keys
129
+ def each(&) = @map.each(&)
130
+ def each_live(&) = @map.each_live(&)
131
+ def each_key(&) = @map.each_key(&)
132
+ def each_value(&) = @map.each_value(&)
133
+ def clear = @map.clear
134
+ def compare_keys_by_identity? = @map.compare_keys_by_identity?
135
+ def compare_values_by_identity? = @map.compare_values_by_identity?
136
+ def ractor_shareable? = Ractor.shareable?(@map)
137
+
138
+ def prepare_mutation_key(key)
139
+ @map.check_mutation
140
+ @map.prepare_mutation_key(@normalizer.call(key))
141
+ end
142
+ end
143
+
144
+ module ConcurrentBackend
145
+ def self.included(base)
146
+ base.class_eval do
147
+ alias_method :assignment_prepared, :[]=
148
+ alias_method :get_prepared, :get
149
+ alias_method :store_prepared, :store
150
+ alias_method :swap_prepared, :swap
151
+ alias_method :update_prepared, :update
152
+ alias_method :wait_until_changed_prepared, :wait_until_changed
153
+ end
154
+ super
155
+ end
156
+
157
+ def normalize_external_key(key)
158
+ if String === key && !key.frozen? && !compare_keys_by_identity?
159
+ key = String.instance_method(:-@).bind_call(key)
160
+ end
161
+ return key if Ractor.shareable?(key)
162
+ raise Ractor::IsolationError, "key must be Ractor-shareable"
163
+ end
164
+ end
165
+
166
+ module TreeOperations
167
+ include CommonOperations
168
+
169
+ def store_if_absent(key, &) = super(normalize_key(key), &)
170
+ end
171
+
172
+ module BoundedOperations
173
+ include CommonOperations
174
+
175
+ def store_if_absent(key, &) = super(normalize_key(key), &)
176
+ end
177
+
178
+ module LeaseOperations
179
+ include CommonOperations
180
+
181
+ def checkout(key, timeout: nil, &)
182
+ canonical = normalize_key(key)
183
+ checkout_canonical(canonical, missing_key: key, timeout:, &)
184
+ end
185
+
186
+ def try_checkout(key, &)
187
+ canonical = normalize_key(key)
188
+ try_checkout_canonical(canonical, missing_key: key, &)
189
+ end
190
+
191
+ def checkin(key, resource)
192
+ canonical = normalize_key(key)
193
+ checkin_canonical(canonical, resource, missing_key: key)
194
+ end
195
+
196
+ def lease_for(key)
197
+ canonical = normalize_key(key)
198
+ lease_for_canonical(canonical, missing_key: key)
199
+ end
200
+
201
+ def store_if_absent(key, &) = super(normalize_key(key), &)
202
+ def available?(key) = super(normalize_key(key))
203
+ def checked_out?(key) = super(normalize_key(key))
204
+ def owned?(key) = super(normalize_key(key))
205
+ end
206
+
207
+ module_function
208
+
209
+ def restore(value) = Restoration.new(value)
210
+
211
+ def dump(normalizer)
212
+ case normalizer
213
+ when SymbolNormalizer then normalizer.value
214
+ when LookupNormalizer then normalizer.source
215
+ else raise TypeError, "Proc key normalizers cannot be serialized"
216
+ end
217
+ end
218
+
219
+ def build(value, shareable:)
220
+ return if value.nil?
221
+ restoring = value.is_a?(Restoration)
222
+ value = value.value if restoring
223
+
224
+ normalizer =
225
+ case value
226
+ when Symbol
227
+ SymbolNormalizer.new(value)
228
+ when Proc
229
+ value = Ractor.shareable_proc(&value) if shareable && !Ractor.shareable?(value)
230
+ ProcNormalizer.new(value)
231
+ when Hash, Farce::Abstract::Map
232
+ Ractor.make_shareable(value) if restoring && shareable && !Ractor.shareable?(value)
233
+ if shareable && !Ractor.shareable?(value)
234
+ raise Ractor::IsolationError, "normalizer source must already be Ractor-shareable"
235
+ end
236
+ LookupNormalizer.new(value)
237
+ else
238
+ raise TypeError, "normalizer must be a Symbol, Proc, Hash, or Farce map"
239
+ end
240
+
241
+ Ractor.make_shareable(normalizer) if shareable
242
+ normalizer
243
+ end
244
+
245
+ def install(target, normalizer, operations)
246
+ return unless normalizer
247
+ target.instance_variable_set(:@key_normalizer, normalizer)
248
+ target.extend(operations)
249
+ end
250
+
251
+ def install_concurrent(target, normalizer)
252
+ return unless normalizer
253
+ target.instance_variable_set(:@key_normalizer, normalizer)
254
+ map = target.instance_variable_get(:@map)
255
+ target.instance_variable_set(:@map, ConcurrentMap.new(map, normalizer))
256
+ end
257
+
258
+ def prepare_concurrent(map)
259
+ prepare_concurrent_class(map.class)
260
+ map
261
+ end
262
+
263
+ def prepare_concurrent_class(type)
264
+ type.include(ConcurrentBackend) unless type < ConcurrentBackend
265
+ end
266
+
267
+ def wrap_concurrent(map, normalizer) = normalizer ? ConcurrentMap.new(map, normalizer) : map
268
+
269
+ def canonical_entries = CanonicalEntries.new
270
+
271
+ def canonical_entries?(entries) = entries.is_a?(CanonicalEntries)
272
+
273
+ def restoration?(value) = value.is_a?(Restoration)
274
+
275
+ def operations_for(target)
276
+ case target
277
+ when Farce::Abstract::LeaseMap then LeaseOperations
278
+ when Farce::Abstract::BoundedMap then BoundedOperations
279
+ when Farce::Abstract::TreeMap then TreeOperations
280
+ else raise ArgumentError, "concurrent maps use an internal key normalizer"
281
+ end
282
+ end
283
+
284
+ def shareable_target?(target)
285
+ target.respond_to?(:ractor_shareable?) ? target.ractor_shareable? : false
286
+ end
287
+ end
288
+ end
289
+ end
@@ -0,0 +1,115 @@
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
+ # Coordinates lazy Lease construction without running user code under a storage lock.
9
+ class LeaseInitialization
10
+ def initialize
11
+ @mutex = Mutex.new
12
+ @signal = Signal.new
13
+ @lease = nil
14
+ @initializing = false
15
+ @owner_fiber = nil
16
+ @owner_thread = nil
17
+ end
18
+
19
+ def fetch(timeout: nil, wait: true, &initializer)
20
+ raise LocalJumpError, "no block given" unless initializer
21
+ deadline = timeout_deadline(timeout)
22
+
23
+ loop do
24
+ initializing_here = false
25
+ observed = @signal.generation
26
+ begin
27
+ Thread.handle_interrupt(INTERRUPT_MASK) { initializing_here = reserve }
28
+ return @lease unless @lease.nil?
29
+ return initialize_lease(&initializer) if initializing_here
30
+
31
+ reject_recursive_initialization!
32
+ return unless wait
33
+
34
+ remaining = deadline - Clock.now if deadline
35
+ return if remaining && !remaining.positive?
36
+ reject_unscheduled_fiber_wait!
37
+ @signal.wait(observed, timeout: wait_interval(remaining))
38
+ ensure
39
+ cancel_reservation if initializing_here
40
+ end
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def reserve
47
+ @mutex.synchronize do
48
+ return false if @lease || @initializing
49
+
50
+ @initializing = true
51
+ @owner_fiber = Fiber.current
52
+ @owner_thread = Thread.current
53
+ true
54
+ end
55
+ end
56
+
57
+ def initialize_lease(&initializer)
58
+ lease = initializer.call
59
+ Thread.handle_interrupt(INTERRUPT_MASK) do
60
+ @mutex.synchronize do
61
+ @lease = lease
62
+ clear_reservation
63
+ end
64
+ @signal.broadcast
65
+ end
66
+ lease
67
+ end
68
+
69
+ def cancel_reservation
70
+ Thread.handle_interrupt(INTERRUPT_MASK) do
71
+ canceled = @mutex.synchronize do
72
+ next false unless @initializing && @owner_fiber.equal?(Fiber.current)
73
+
74
+ clear_reservation
75
+ true
76
+ end
77
+ @signal.broadcast if canceled
78
+ end
79
+ end
80
+
81
+ def clear_reservation
82
+ @initializing = false
83
+ @owner_fiber = nil
84
+ @owner_thread = nil
85
+ end
86
+
87
+ def reject_unscheduled_fiber_wait!
88
+ return unless @owner_thread.equal?(Thread.current)
89
+ return if Fiber.respond_to?(:scheduler) && Fiber.scheduler
90
+
91
+ raise ThreadError, "deadlock; lease is initialized by another unscheduled Fiber on the same thread"
92
+ end
93
+
94
+ def reject_recursive_initialization!
95
+ return unless @owner_fiber.equal?(Fiber.current)
96
+
97
+ raise ThreadError, "deadlock; recursive lease initialization"
98
+ end
99
+
100
+ def timeout_deadline(timeout)
101
+ return if timeout.nil?
102
+
103
+ timeout = Float(timeout)
104
+ unless timeout.finite? && !timeout.negative?
105
+ raise ArgumentError, "timeout must be a finite, non-negative number or nil"
106
+ end
107
+ Clock.now + timeout
108
+ end
109
+
110
+ def wait_interval(remaining)
111
+ LeaseWaiting.wait_interval(remaining)
112
+ end
113
+ end
114
+ end
115
+ end