farce 0.0.1.alpha2-x86-linux-gnu

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 (423) 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/ext/ext_helper.rb +20 -0
  15. data/ext/farce/README.md +21 -0
  16. data/ext/farce/atom.c +1023 -0
  17. data/ext/farce/bounded_map.c +1683 -0
  18. data/ext/farce/containers.h +77 -0
  19. data/ext/farce/counter.c +399 -0
  20. data/ext/farce/darwin.c +100 -0
  21. data/ext/farce/depend +12 -0
  22. data/ext/farce/dict.c +1523 -0
  23. data/ext/farce/dict.h +152 -0
  24. data/ext/farce/drivers.c +237 -0
  25. data/ext/farce/exchanger.c +299 -0
  26. data/ext/farce/extconf.rb +99 -0
  27. data/ext/farce/farce.c +359 -0
  28. data/ext/farce/flag.c +288 -0
  29. data/ext/farce/io.c +338 -0
  30. data/ext/farce/lock.c +510 -0
  31. data/ext/farce/map.c +2240 -0
  32. data/ext/farce/priority_queue.c +2056 -0
  33. data/ext/farce/queue.c +1059 -0
  34. data/ext/farce/reactor.c +820 -0
  35. data/ext/farce/reactor.h +103 -0
  36. data/ext/farce/shareable.h +31 -0
  37. data/ext/farce/signal.c +350 -0
  38. data/ext/farce/transaction.c +354 -0
  39. data/ext/farce/transaction.h +40 -0
  40. data/ext/farce/tree_map.c +1953 -0
  41. data/ext/farce/trie.c +2020 -0
  42. data/ext/farce/unshareable.c +155 -0
  43. data/ext/farce/unshared_io_pool.h +234 -0
  44. data/ext/farce/unshared_signal.c +263 -0
  45. data/ext/farce/unshared_wait.h +193 -0
  46. data/ext/farce/unsupported.c +6 -0
  47. data/ext/farce/vector.c +1195 -0
  48. data/ext/farce/weak_map.c +1714 -0
  49. data/ext/java/org/farce/BoundedMap.java +394 -0
  50. data/ext/java/org/farce/FiberScheduler.java +141 -0
  51. data/ext/java/org/farce/PriorityKey.java +45 -0
  52. data/ext/java/org/farce/PriorityQueue.java +373 -0
  53. data/ext/java/org/farce/QueueSignal.java +28 -0
  54. data/ext/rebind/README.md +14 -0
  55. data/ext/rebind/extconf.rb +10 -0
  56. data/ext/rebind/rebind.c +186 -0
  57. data/lib/farce/_yard/internal.rb +13 -0
  58. data/lib/farce/_yard/macros.rb +61 -0
  59. data/lib/farce/_yard/ractor.rb +46 -0
  60. data/lib/farce/abstract/atom.rb +186 -0
  61. data/lib/farce/abstract/bounded_map.rb +232 -0
  62. data/lib/farce/abstract/collection.rb +151 -0
  63. data/lib/farce/abstract/concurrent_map.rb +381 -0
  64. data/lib/farce/abstract/counter.rb +193 -0
  65. data/lib/farce/abstract/duplicable_map.rb +229 -0
  66. data/lib/farce/abstract/exchanger.rb +26 -0
  67. data/lib/farce/abstract/flag.rb +71 -0
  68. data/lib/farce/abstract/lazy.rb +115 -0
  69. data/lib/farce/abstract/lease.rb +104 -0
  70. data/lib/farce/abstract/lease_map.rb +261 -0
  71. data/lib/farce/abstract/lease_pool.rb +91 -0
  72. data/lib/farce/abstract/lfu_map.rb +20 -0
  73. data/lib/farce/abstract/lru_map.rb +25 -0
  74. data/lib/farce/abstract/map.rb +345 -0
  75. data/lib/farce/abstract/molecule.rb +245 -0
  76. data/lib/farce/abstract/port.rb +74 -0
  77. data/lib/farce/abstract/priority_queue.rb +117 -0
  78. data/lib/farce/abstract/queue.rb +269 -0
  79. data/lib/farce/abstract/scheduler.rb +111 -0
  80. data/lib/farce/abstract/set.rb +910 -0
  81. data/lib/farce/abstract/sorted_set.rb +172 -0
  82. data/lib/farce/abstract/timer_queue.rb +136 -0
  83. data/lib/farce/abstract/tree_map.rb +269 -0
  84. data/lib/farce/abstract/value.rb +68 -0
  85. data/lib/farce/abstract/vector.rb +1126 -0
  86. data/lib/farce/abstract/weak_atom.rb +32 -0
  87. data/lib/farce/abstract/weak_key_map.rb +12 -0
  88. data/lib/farce/abstract/weak_map.rb +13 -0
  89. data/lib/farce/abstract/weak_set.rb +12 -0
  90. data/lib/farce/abstract/weak_value_map.rb +12 -0
  91. data/lib/farce/abstract.rb +17 -0
  92. data/lib/farce/atom.rb +293 -0
  93. data/lib/farce/class_mirror.rb +87 -0
  94. data/lib/farce/clock.rb +121 -0
  95. data/lib/farce/config.rb +229 -0
  96. data/lib/farce/counter.rb +71 -0
  97. data/lib/farce/deduper.rb +122 -0
  98. data/lib/farce/engine/jruby/bounded_map.rb +314 -0
  99. data/lib/farce/engine/jruby/fiber_scheduler.jar +0 -0
  100. data/lib/farce/engine/jruby/fiber_scheduler.rb +119 -0
  101. data/lib/farce/engine/jruby/lease_waiting.rb +19 -0
  102. data/lib/farce/engine/jruby/map.rb +505 -0
  103. data/lib/farce/engine/jruby/mutable_numeric_copy.rb +42 -0
  104. data/lib/farce/engine/jruby/signal.rb +147 -0
  105. data/lib/farce/engine/jruby.rb +63 -0
  106. data/lib/farce/engine/jvm/concurrent_weak_registry.rb +55 -0
  107. data/lib/farce/engine/jvm/counter.rb +102 -0
  108. data/lib/farce/engine/jvm/extension.rb +32 -0
  109. data/lib/farce/engine/jvm/farce.jar +0 -0
  110. data/lib/farce/engine/jvm/flag.rb +79 -0
  111. data/lib/farce/engine/jvm/priority_queue.rb +217 -0
  112. data/lib/farce/engine/jvm/tree_map.rb +350 -0
  113. data/lib/farce/engine/jvm/types.rb +180 -0
  114. data/lib/farce/engine/jvm.rb +19 -0
  115. data/lib/farce/engine/ruby/3.4/farce.so +0 -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/rebind.so +0 -0
  121. data/lib/farce/engine/ruby/3.4/vault.rb +56 -0
  122. data/lib/farce/engine/ruby/4.0/farce.so +0 -0
  123. data/lib/farce/engine/ruby/4.0/port.rb +19 -0
  124. data/lib/farce/engine/ruby/4.0/ractor_methods.rb +20 -0
  125. data/lib/farce/engine/ruby/4.0/ractor_selector.rb +108 -0
  126. data/lib/farce/engine/ruby/4.0/rebind.so +0 -0
  127. data/lib/farce/engine/ruby/4.0/vault.rb +74 -0
  128. data/lib/farce/engine/ruby/4.1/port.rb +21 -0
  129. data/lib/farce/engine/ruby/4.1/ractor_methods.rb +22 -0
  130. data/lib/farce/engine/ruby/4.1/ractor_selector.rb +25 -0
  131. data/lib/farce/engine/ruby/4.1/vault.rb +5 -0
  132. data/lib/farce/engine/ruby/fiber_scheduler.rb +32 -0
  133. data/lib/farce/engine/ruby/key_lock_map.rb +28 -0
  134. data/lib/farce/engine/ruby/shared/lease.rb +26 -0
  135. data/lib/farce/engine/ruby/shared/lease_pool.rb +24 -0
  136. data/lib/farce/engine/ruby/shared/main_scheduler.rb +9 -0
  137. data/lib/farce/engine/ruby/shared/parallel_scheduler.rb +9 -0
  138. data/lib/farce/engine/ruby/shared/proxy_owner.rb +31 -0
  139. data/lib/farce/engine/ruby/shared/ractor_methods.rb +34 -0
  140. data/lib/farce/engine/ruby/shared/ractor_selector.rb +328 -0
  141. data/lib/farce/engine/ruby/shared/strict_map.rb +13 -0
  142. data/lib/farce/engine/ruby/shared/unshared_vector.rb +14 -0
  143. data/lib/farce/engine/ruby/shared/vault.rb +144 -0
  144. data/lib/farce/engine/ruby/shared/vault_weak_map.rb +336 -0
  145. data/lib/farce/engine/ruby/shared/weak_atom.rb +54 -0
  146. data/lib/farce/engine/ruby/shared/weak_map.rb +413 -0
  147. data/lib/farce/engine/ruby.rb +130 -0
  148. data/lib/farce/engine/shared/atom.rb +10 -0
  149. data/lib/farce/engine/shared/exchanger.rb +130 -0
  150. data/lib/farce/engine/shared/identity_key.rb +22 -0
  151. data/lib/farce/engine/shared/lease.rb +10 -0
  152. data/lib/farce/engine/shared/lease_pool.rb +10 -0
  153. data/lib/farce/engine/shared/main_scheduler.rb +20 -0
  154. data/lib/farce/engine/shared/map_key_coordination.rb +226 -0
  155. data/lib/farce/engine/shared/parallel_scheduler.rb +9 -0
  156. data/lib/farce/engine/shared/port.rb +44 -0
  157. data/lib/farce/engine/shared/portable_bounded_map.rb +619 -0
  158. data/lib/farce/engine/shared/proxy_owner.rb +43 -0
  159. data/lib/farce/engine/shared/queue.rb +233 -0
  160. data/lib/farce/engine/shared/ractor_methods.rb +73 -0
  161. data/lib/farce/engine/shared/rebindable.rb +15 -0
  162. data/lib/farce/engine/shared/strict_atom.rb +73 -0
  163. data/lib/farce/engine/shared/strict_map.rb +117 -0
  164. data/lib/farce/engine/shared/strict_queue_values.rb +27 -0
  165. data/lib/farce/engine/shared/strict_tree_map.rb +56 -0
  166. data/lib/farce/engine/shared/transaction_map_backend.rb +20 -0
  167. data/lib/farce/engine/shared/trie.rb +317 -0
  168. data/lib/farce/engine/shared/trie_builder.rb +199 -0
  169. data/lib/farce/engine/shared/unshareable.rb +14 -0
  170. data/lib/farce/engine/shared/unshared_atom.rb +256 -0
  171. data/lib/farce/engine/shared/unshared_priority_queue.rb +9 -0
  172. data/lib/farce/engine/shared/unshared_queue.rb +18 -0
  173. data/lib/farce/engine/shared/unshared_signal.rb +21 -0
  174. data/lib/farce/engine/shared/unshared_vector.rb +377 -0
  175. data/lib/farce/engine/shared/unshared_weak_atom.rb +30 -0
  176. data/lib/farce/engine/shared/unshared_weak_map.rb +445 -0
  177. data/lib/farce/engine/shared/vault.rb +31 -0
  178. data/lib/farce/engine/shared/vector.rb +83 -0
  179. data/lib/farce/engine/shared/weak_atom/base.rb +189 -0
  180. data/lib/farce/engine/shared/weak_atom.rb +20 -0
  181. data/lib/farce/engine/shared/weak_map/cell.rb +99 -0
  182. data/lib/farce/engine/shared/weak_map/index.rb +249 -0
  183. data/lib/farce/engine/shared/weak_map/lock.rb +80 -0
  184. data/lib/farce/engine/shared/weak_map/reference.rb +33 -0
  185. data/lib/farce/engine/shared.rb +63 -0
  186. data/lib/farce/engine/truffleruby/fiber_scheduler.rb +13 -0
  187. data/lib/farce/engine/truffleruby/lock.rb +121 -0
  188. data/lib/farce/engine/truffleruby/map.rb +656 -0
  189. data/lib/farce/engine/truffleruby/native/counter.rb +105 -0
  190. data/lib/farce/engine/truffleruby/native/flag.rb +77 -0
  191. data/lib/farce/engine/truffleruby/native/ordered_array_support.rb +67 -0
  192. data/lib/farce/engine/truffleruby/native/priority_queue.rb +388 -0
  193. data/lib/farce/engine/truffleruby/native/tree_map.rb +51 -0
  194. data/lib/farce/engine/truffleruby/native/unsafe_tree_map.rb +350 -0
  195. data/lib/farce/engine/truffleruby/signal.rb +77 -0
  196. data/lib/farce/engine/truffleruby.rb +148 -0
  197. data/lib/farce/envelope.rb +335 -0
  198. data/lib/farce/error.rb +35 -0
  199. data/lib/farce/exchanger.rb +41 -0
  200. data/lib/farce/flag.rb +27 -0
  201. data/lib/farce/integrations/active_support/blank.rb +68 -0
  202. data/lib/farce/integrations/active_support/clock.rb +17 -0
  203. data/lib/farce/integrations/active_support/duplicable.rb +78 -0
  204. data/lib/farce/integrations/active_support/map.rb +175 -0
  205. data/lib/farce/integrations/active_support/set.rb +60 -0
  206. data/lib/farce/integrations/active_support/value_serialization.rb +17 -0
  207. data/lib/farce/integrations/active_support/vector.rb +231 -0
  208. data/lib/farce/integrations/active_support.rb +9 -0
  209. data/lib/farce/integrations/activesupport.rb +5 -0
  210. data/lib/farce/integrations/bson.rb +108 -0
  211. data/lib/farce/integrations/cbor.rb +51 -0
  212. data/lib/farce/integrations/concurrent.rb +112 -0
  213. data/lib/farce/integrations/dry-types.rb +5 -0
  214. data/lib/farce/integrations/dry_types.rb +694 -0
  215. data/lib/farce/integrations/json.rb +7 -0
  216. data/lib/farce/integrations/msgpack.rb +112 -0
  217. data/lib/farce/integrations/oj.rb +69 -0
  218. data/lib/farce/integrations/psych.rb +191 -0
  219. data/lib/farce/integrations/ractor-sharing.rb +5 -0
  220. data/lib/farce/integrations/ractor-tmvar.rb +5 -0
  221. data/lib/farce/integrations/ractor_sharing.rb +172 -0
  222. data/lib/farce/integrations/ractor_tmvar.rb +64 -0
  223. data/lib/farce/integrations/shared/to_json.rb +42 -0
  224. data/lib/farce/integrations/sorted_set.rb +11 -0
  225. data/lib/farce/integrations/weakref.rb +38 -0
  226. data/lib/farce/integrations/yajl.rb +10 -0
  227. data/lib/farce/integrations.rb +156 -0
  228. data/lib/farce/internal/_frozen_config.rb +11 -0
  229. data/lib/farce/internal/autoloads.rb +47 -0
  230. data/lib/farce/internal/blocking_priority_queue.rb +122 -0
  231. data/lib/farce/internal/converter.rb +106 -0
  232. data/lib/farce/internal/copyable.rb +31 -0
  233. data/lib/farce/internal/delegation.rb +20 -0
  234. data/lib/farce/internal/external_transaction.rb +59 -0
  235. data/lib/farce/internal/fake_ractor.rb +179 -0
  236. data/lib/farce/internal/freeze.rb +118 -0
  237. data/lib/farce/internal/inspect.rb +157 -0
  238. data/lib/farce/internal/key_lock_map.rb +29 -0
  239. data/lib/farce/internal/key_normalizer.rb +289 -0
  240. data/lib/farce/internal/lease_initialization.rb +115 -0
  241. data/lib/farce/internal/lease_map.rb +441 -0
  242. data/lib/farce/internal/lease_pool_state.rb +228 -0
  243. data/lib/farce/internal/lease_state.rb +342 -0
  244. data/lib/farce/internal/lease_waiting.rb +13 -0
  245. data/lib/farce/internal/managed_queue.rb +26 -0
  246. data/lib/farce/internal/map_value_modes.rb +227 -0
  247. data/lib/farce/internal/marshal_support.rb +227 -0
  248. data/lib/farce/internal/mixin.rb +20 -0
  249. data/lib/farce/internal/mutable_ordered_key_lock_map.rb +63 -0
  250. data/lib/farce/internal/noncopyable.rb +17 -0
  251. data/lib/farce/internal/ordered_key_lock_map.rb +69 -0
  252. data/lib/farce/internal/pool_supervisor.rb +41 -0
  253. data/lib/farce/internal/pool_worker.rb +61 -0
  254. data/lib/farce/internal/portable_transaction/reservation_entry.rb +29 -0
  255. data/lib/farce/internal/portable_transaction/strong_map_entry.rb +137 -0
  256. data/lib/farce/internal/portable_transaction/strong_map_size_entry.rb +44 -0
  257. data/lib/farce/internal/portable_transaction/tree_entry.rb +64 -0
  258. data/lib/farce/internal/portable_transaction.rb +164 -0
  259. data/lib/farce/internal/proxy_owner_notifications.rb +29 -0
  260. data/lib/farce/internal/reservation_waiting.rb +24 -0
  261. data/lib/farce/internal/scheduled_task.rb +48 -0
  262. data/lib/farce/internal/scheduler_io.rb +171 -0
  263. data/lib/farce/internal/scheduler_lifecycle.rb +314 -0
  264. data/lib/farce/internal/select_scheduler.rb +235 -0
  265. data/lib/farce/internal/storage.rb +162 -0
  266. data/lib/farce/internal/strict_lease.rb +30 -0
  267. data/lib/farce/internal/strict_lease_map.rb +20 -0
  268. data/lib/farce/internal/strict_lease_pool.rb +29 -0
  269. data/lib/farce/internal/thread_pool.rb +166 -0
  270. data/lib/farce/internal/transaction_conflict.rb +9 -0
  271. data/lib/farce/internal/transaction_freeze_guard.rb +30 -0
  272. data/lib/farce/internal/transaction_map_snapshot.rb +123 -0
  273. data/lib/farce/internal/undefined.rb +22 -0
  274. data/lib/farce/internal/unshared_lease.rb +29 -0
  275. data/lib/farce/internal/unshared_lease_pool.rb +34 -0
  276. data/lib/farce/internal/unshared_queue_waiting.rb +28 -0
  277. data/lib/farce/internal/value_serialization.rb +13 -0
  278. data/lib/farce/internal/weak_map_value_modes.rb +58 -0
  279. data/lib/farce/internal/weak_mode_manager.rb +26 -0
  280. data/lib/farce/internal.rb +129 -0
  281. data/lib/farce/lazy.rb +100 -0
  282. data/lib/farce/lazy_ref.rb +40 -0
  283. data/lib/farce/lease.rb +28 -0
  284. data/lib/farce/lease_map.rb +34 -0
  285. data/lib/farce/lease_pool.rb +29 -0
  286. data/lib/farce/lfu_map.rb +53 -0
  287. data/lib/farce/local/atom.rb +23 -0
  288. data/lib/farce/local/counter.rb +88 -0
  289. data/lib/farce/local/flag.rb +65 -0
  290. data/lib/farce/local/lazy.rb +38 -0
  291. data/lib/farce/local/lazy_ref.rb +36 -0
  292. data/lib/farce/local/lease.rb +77 -0
  293. data/lib/farce/local/lease_map.rb +80 -0
  294. data/lib/farce/local/lease_pool.rb +38 -0
  295. data/lib/farce/local/lfu_map.rb +55 -0
  296. data/lib/farce/local/lru_map.rb +62 -0
  297. data/lib/farce/local/map.rb +47 -0
  298. data/lib/farce/local/molecule.rb +45 -0
  299. data/lib/farce/local/priority_queue.rb +53 -0
  300. data/lib/farce/local/queue.rb +32 -0
  301. data/lib/farce/local/scoped.rb +166 -0
  302. data/lib/farce/local/set.rb +18 -0
  303. data/lib/farce/local/sorted_set.rb +50 -0
  304. data/lib/farce/local/timer_queue.rb +41 -0
  305. data/lib/farce/local/tree_map.rb +47 -0
  306. data/lib/farce/local/vector.rb +30 -0
  307. data/lib/farce/local/weak_atom.rb +23 -0
  308. data/lib/farce/local/weak_key_map.rb +39 -0
  309. data/lib/farce/local/weak_map.rb +39 -0
  310. data/lib/farce/local/weak_set.rb +18 -0
  311. data/lib/farce/local/weak_value_map.rb +39 -0
  312. data/lib/farce/local.rb +35 -0
  313. data/lib/farce/lock.rb +54 -0
  314. data/lib/farce/lru_map.rb +63 -0
  315. data/lib/farce/map.rb +58 -0
  316. data/lib/farce/mode_manager.rb +142 -0
  317. data/lib/farce/molecule.rb +60 -0
  318. data/lib/farce/mutable.rb +171 -0
  319. data/lib/farce/pool.rb +332 -0
  320. data/lib/farce/port.rb +134 -0
  321. data/lib/farce/priority_queue.rb +70 -0
  322. data/lib/farce/proxy/register.rb +101 -0
  323. data/lib/farce/proxy/supervisor.rb +137 -0
  324. data/lib/farce/proxy/wrapper.rb +49 -0
  325. data/lib/farce/proxy.rb +291 -0
  326. data/lib/farce/queue.rb +60 -0
  327. data/lib/farce/ractor.rb +269 -0
  328. data/lib/farce/read_write_lock.rb +256 -0
  329. data/lib/farce/reference.rb +158 -0
  330. data/lib/farce/resolv/dns.rb +42 -0
  331. data/lib/farce/resolv.rb +85 -0
  332. data/lib/farce/scheduler.rb +536 -0
  333. data/lib/farce/set.rb +39 -0
  334. data/lib/farce/shareable.rb +150 -0
  335. data/lib/farce/signal.rb +97 -0
  336. data/lib/farce/sorted_set.rb +36 -0
  337. data/lib/farce/strict/atom.rb +34 -0
  338. data/lib/farce/strict/counter.rb +10 -0
  339. data/lib/farce/strict/exchanger.rb +25 -0
  340. data/lib/farce/strict/flag.rb +10 -0
  341. data/lib/farce/strict/lazy.rb +26 -0
  342. data/lib/farce/strict/lazy_ref.rb +26 -0
  343. data/lib/farce/strict/lease.rb +27 -0
  344. data/lib/farce/strict/lease_map.rb +33 -0
  345. data/lib/farce/strict/lease_pool.rb +28 -0
  346. data/lib/farce/strict/lfu_map.rb +27 -0
  347. data/lib/farce/strict/lru_map.rb +28 -0
  348. data/lib/farce/strict/map.rb +54 -0
  349. data/lib/farce/strict/molecule.rb +16 -0
  350. data/lib/farce/strict/port.rb +40 -0
  351. data/lib/farce/strict/priority_queue.rb +20 -0
  352. data/lib/farce/strict/queue.rb +17 -0
  353. data/lib/farce/strict/set.rb +14 -0
  354. data/lib/farce/strict/sorted_set.rb +19 -0
  355. data/lib/farce/strict/timer_queue.rb +13 -0
  356. data/lib/farce/strict/tree_map.rb +27 -0
  357. data/lib/farce/strict/vector.rb +24 -0
  358. data/lib/farce/strict/weak_atom.rb +31 -0
  359. data/lib/farce/strict/weak_key_map.rb +49 -0
  360. data/lib/farce/strict/weak_map.rb +49 -0
  361. data/lib/farce/strict/weak_set.rb +14 -0
  362. data/lib/farce/strict/weak_value_map.rb +48 -0
  363. data/lib/farce/strict.rb +28 -0
  364. data/lib/farce/system.rb +40 -0
  365. data/lib/farce/thread_scheduler.rb +70 -0
  366. data/lib/farce/timer_queue.rb +66 -0
  367. data/lib/farce/transaction/atom.rb +73 -0
  368. data/lib/farce/transaction/map.rb +25 -0
  369. data/lib/farce/transaction/map_operations.rb +143 -0
  370. data/lib/farce/transaction/molecule.rb +90 -0
  371. data/lib/farce/transaction/mutable.rb +61 -0
  372. data/lib/farce/transaction/set.rb +17 -0
  373. data/lib/farce/transaction/set_operations.rb +48 -0
  374. data/lib/farce/transaction/sorted_set.rb +18 -0
  375. data/lib/farce/transaction/tree_map.rb +78 -0
  376. data/lib/farce/transaction/vector.rb +139 -0
  377. data/lib/farce/transaction/wrapper.rb +202 -0
  378. data/lib/farce/transaction.rb +343 -0
  379. data/lib/farce/tree_map.rb +56 -0
  380. data/lib/farce/unsafe/lfu_map.rb +36 -0
  381. data/lib/farce/unsafe/lru_map.rb +36 -0
  382. data/lib/farce/unsafe/tree_map.rb +21 -0
  383. data/lib/farce/unsafe.rb +29 -0
  384. data/lib/farce/unshareable.rb +67 -0
  385. data/lib/farce/unshared/atom.rb +24 -0
  386. data/lib/farce/unshared/counter.rb +10 -0
  387. data/lib/farce/unshared/flag.rb +10 -0
  388. data/lib/farce/unshared/lazy.rb +38 -0
  389. data/lib/farce/unshared/lazy_ref.rb +26 -0
  390. data/lib/farce/unshared/lease.rb +27 -0
  391. data/lib/farce/unshared/lease_map.rb +26 -0
  392. data/lib/farce/unshared/lease_pool.rb +25 -0
  393. data/lib/farce/unshared/lfu_map.rb +20 -0
  394. data/lib/farce/unshared/lru_map.rb +20 -0
  395. data/lib/farce/unshared/map.rb +49 -0
  396. data/lib/farce/unshared/molecule.rb +16 -0
  397. data/lib/farce/unshared/priority_queue.rb +16 -0
  398. data/lib/farce/unshared/queue.rb +27 -0
  399. data/lib/farce/unshared/set.rb +14 -0
  400. data/lib/farce/unshared/sorted_set.rb +28 -0
  401. data/lib/farce/unshared/timer_queue.rb +16 -0
  402. data/lib/farce/unshared/tree_map.rb +21 -0
  403. data/lib/farce/unshared/vector.rb +19 -0
  404. data/lib/farce/unshared/weak_atom.rb +31 -0
  405. data/lib/farce/unshared/weak_key_map.rb +44 -0
  406. data/lib/farce/unshared/weak_map.rb +44 -0
  407. data/lib/farce/unshared/weak_set.rb +14 -0
  408. data/lib/farce/unshared/weak_value_map.rb +43 -0
  409. data/lib/farce/unshared.rb +28 -0
  410. data/lib/farce/vector.rb +228 -0
  411. data/lib/farce/version.rb +8 -0
  412. data/lib/farce/walker/definitions.rb +186 -0
  413. data/lib/farce/walker/modification.rb +355 -0
  414. data/lib/farce/walker.rb +319 -0
  415. data/lib/farce/weak_atom.rb +121 -0
  416. data/lib/farce/weak_key_map.rb +31 -0
  417. data/lib/farce/weak_map.rb +33 -0
  418. data/lib/farce/weak_ref.rb +67 -0
  419. data/lib/farce/weak_set.rb +82 -0
  420. data/lib/farce/weak_value.rb +195 -0
  421. data/lib/farce/weak_value_map.rb +32 -0
  422. data/lib/farce.rb +519 -0
  423. metadata +468 -0
@@ -0,0 +1,656 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ require "farce/engine/shared/map_key_coordination"
6
+
7
+ module Farce
8
+ # @!visibility private
9
+ module Internal # :nodoc: all
10
+ class Map < TruffleRuby::ConcurrentMap
11
+ include MapKeyCoordination
12
+ include TransactionMapBackend
13
+
14
+ BASIC_OBJECT_EQUAL_METHOD = BasicObject.instance_method(:equal?)
15
+ private_constant :BASIC_OBJECT_EQUAL_METHOD
16
+
17
+ class Key
18
+ attr_accessor :mutation_owner
19
+ attr_reader :value
20
+
21
+ def initialize(value) = @value = value
22
+
23
+ def hash
24
+ result = value.hash
25
+ owner = mutation_owner
26
+ Internal::Freeze.check(owner) if owner
27
+ result
28
+ end
29
+
30
+ def eql?(other)
31
+ result = other.is_a?(Key) && value.eql?(other.value)
32
+ owner = mutation_owner || (other.mutation_owner if other.is_a?(Key))
33
+ Internal::Freeze.check(owner) if owner
34
+ result
35
+ end
36
+
37
+ alias == eql?
38
+ end
39
+ private_constant :Key
40
+
41
+ def initialize(
42
+ initial_mapping = nil,
43
+ compare_by_identity: false,
44
+ compare_keys_by_identity: compare_by_identity,
45
+ compare_values_by_identity: compare_by_identity
46
+ )
47
+ validate_boolean(compare_by_identity, "compare_by_identity")
48
+ validate_boolean(compare_keys_by_identity, "compare_keys_by_identity")
49
+ validate_boolean(compare_values_by_identity, "compare_values_by_identity")
50
+ raise TypeError, "initial mapping must be a Hash" unless initial_mapping.nil? || initial_mapping.is_a?(Hash)
51
+
52
+ super()
53
+ # Preserve the native superclass interface while keeping replaceable storage.
54
+ # Transactions can prepare a replacement without editing live entries.
55
+ @map = TruffleRuby::ConcurrentMap.new
56
+ @compare_keys_by_identity = compare_keys_by_identity
57
+ @compare_values_by_identity = compare_values_by_identity
58
+ @freeze_state = Flag.new(false)
59
+ # Native operations may overlap. Block updates reserve one logical key.
60
+ @state_mutex = Mutex.new
61
+ @change_signal = Signal.new
62
+ @active_owner_fiber = nil
63
+ @active_owner_thread = nil
64
+ @active_owners = nil
65
+ initialize_key_coordination
66
+ initial_mapping&.each do |key, value|
67
+ check_frozen!
68
+ wrapped = wrap_key(key)
69
+ with_mutation_callback_guard(wrapped) { concurrent_store(wrapped, value) }
70
+ end
71
+ end
72
+
73
+ def freeze
74
+ state = @freeze_state
75
+ return super unless state
76
+
77
+ state.set
78
+ self
79
+ end
80
+
81
+ def frozen?
82
+ state = @freeze_state
83
+ state ? state.value : super
84
+ end
85
+
86
+ def check_mutation = check_frozen!
87
+
88
+ def prepare_mutation_key(key)
89
+ check_frozen!
90
+ normalize_external_key(key)
91
+ end
92
+
93
+ def [](key) = concurrent_get(wrap_key(key))
94
+
95
+ def fetch(*arguments)
96
+ unless arguments.length.between?(1, 2)
97
+ raise ArgumentError, "wrong number of arguments (given #{arguments.length}, expected 1..2)"
98
+ end
99
+
100
+ key, default = arguments
101
+ default_given = arguments.length == 2
102
+ warn "block supersedes default value argument", uplevel: 1 if block_given? && default_given
103
+ missing = Object.new
104
+ value = concurrent_get_or_default(wrap_key(key), missing)
105
+ return value unless missing.equal?(value)
106
+ return yield(key) if block_given?
107
+ return default if default_given
108
+
109
+ raise KeyError.new("key not found: #{key.inspect}", receiver: self, key: key)
110
+ end
111
+
112
+ def []=(key, value)
113
+ check_frozen!
114
+ wrapped = wrap_key(key)
115
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
116
+ commit_mutation(reservation) do
117
+ native_operation { concurrent_store(wrapped, value) }
118
+ changed!
119
+ end
120
+ value
121
+ end
122
+ result
123
+ end
124
+
125
+ def get(key, timeout: nil, &fallback)
126
+ wrapped = wrap_key(key)
127
+ completed, result = with_key_operation(wrapped, timeout_deadline(timeout)) do
128
+ native_operation { concurrent_get(wrapped) }
129
+ end
130
+ completed ? result : fallback&.call
131
+ end
132
+
133
+ def store(key, value, timeout: nil, &fallback)
134
+ check_frozen!
135
+ wrapped = wrap_key(key)
136
+ completed, result = with_mutating_key_operation(wrapped, timeout_deadline(timeout)) do |reservation|
137
+ commit_mutation(reservation) do
138
+ native_operation { concurrent_store(wrapped, value) }
139
+ changed!
140
+ end
141
+ value
142
+ end
143
+ completed ? result : fallback&.call
144
+ end
145
+
146
+ def swap(key, replacement, timeout: nil, &fallback)
147
+ check_frozen!
148
+ wrapped = wrap_key(key)
149
+ completed, result = with_mutating_key_operation(wrapped, timeout_deadline(timeout)) do |reservation|
150
+ previous = nil
151
+ commit_mutation(reservation) do
152
+ previous = native_operation { concurrent_get_and_set(wrapped, replacement) }
153
+ changed!
154
+ end
155
+ previous
156
+ end
157
+ completed ? result : fallback&.call
158
+ end
159
+
160
+ def store_if_absent(key, timeout: nil)
161
+ raise LocalJumpError, "no block given" unless block_given?
162
+ check_frozen!
163
+
164
+ wrapped = wrap_key(key)
165
+ completed, result = with_mutating_key_operation(wrapped, timeout_deadline(timeout)) do |reservation|
166
+ if native_operation { concurrent_key?(wrapped) }
167
+ native_operation { concurrent_get(wrapped) }
168
+ else
169
+ value = yield
170
+ stored = commit_mutation(reservation) do
171
+ native_operation { concurrent_store(wrapped, value) }
172
+ changed!
173
+ end
174
+ value if stored
175
+ end
176
+ end
177
+ completed ? result : nil
178
+ end
179
+
180
+ def compare_and_set(key, expected, replacement, timeout: nil)
181
+ check_frozen!
182
+ wrapped = wrap_key(key)
183
+ completed, result = with_mutating_key_operation(wrapped, timeout_deadline(timeout)) do |reservation|
184
+ next false unless native_operation { concurrent_key?(wrapped) }
185
+
186
+ current = native_operation { concurrent_get(wrapped) }
187
+ next false unless values_equal?(current, expected)
188
+
189
+ replaced = commit_mutation(reservation) do
190
+ native_operation { concurrent_store(wrapped, replacement) }
191
+ changed!
192
+ end
193
+ replaced
194
+ end
195
+ completed && result
196
+ end
197
+
198
+ def update(key, timeout: nil)
199
+ raise LocalJumpError, "no block given" unless block_given?
200
+ check_frozen!
201
+
202
+ wrapped = wrap_key(key)
203
+ completed, result = with_mutating_key_operation(wrapped, timeout_deadline(timeout)) do |reservation|
204
+ value = yield(native_operation { concurrent_get(wrapped) })
205
+ stored = commit_mutation(reservation) do
206
+ native_operation { concurrent_store(wrapped, value) }
207
+ changed!
208
+ end
209
+ value if stored
210
+ end
211
+ completed ? result : nil
212
+ end
213
+
214
+ # Yield presence and value under the key reservation.
215
+ # MAP_KEEP and MAP_DELETE are control results. Other results replace the value.
216
+ # Return whether a change committed.
217
+ def modify(key) # rubocop:disable Naming/PredicateMethod
218
+ raise LocalJumpError, "no block given" unless block_given?
219
+ check_frozen!
220
+ wrapped = wrap_key(key)
221
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
222
+ present, current = native_operation { [concurrent_key?(wrapped), concurrent_get(wrapped)] }
223
+ value = yield(present, current)
224
+ next false if MAP_KEEP.equal?(value)
225
+ remove = MAP_DELETE.equal?(value)
226
+ next false if remove && !present
227
+ commit_mutation(reservation) do
228
+ native_operation do
229
+ remove ? concurrent_delete(wrapped) : concurrent_store(wrapped, value)
230
+ end
231
+ changed!
232
+ end
233
+ end
234
+ !!result
235
+ end
236
+
237
+ def upsert(key, initial_value, timeout: nil)
238
+ raise LocalJumpError, "no block given" unless block_given?
239
+ check_frozen!
240
+
241
+ wrapped = wrap_key(key)
242
+ completed, result = with_mutating_key_operation(wrapped, timeout_deadline(timeout)) do |reservation|
243
+ present = native_operation { concurrent_key?(wrapped) }
244
+ value = present ? yield(native_operation { concurrent_get(wrapped) }) : initial_value
245
+ stored = commit_mutation(reservation) do
246
+ native_operation { concurrent_store(wrapped, value) }
247
+ changed!
248
+ end
249
+ value if stored
250
+ end
251
+ completed ? result : nil
252
+ end
253
+
254
+ def wait_until_changed(key, expected, timeout: nil, &fallback)
255
+ wait_for_value(key, expected, timeout_deadline(timeout), fallback, non_nil: false)
256
+ end
257
+
258
+ def wait_until_non_nil(key, timeout: nil, &fallback)
259
+ wait_for_value(key, nil, timeout_deadline(timeout), fallback, non_nil: true)
260
+ end
261
+
262
+ def key?(key) = concurrent_key?(wrap_key(key))
263
+ def size = concurrent_size
264
+ def compare_keys_by_identity? = @compare_keys_by_identity
265
+ def compare_values_by_identity? = @compare_values_by_identity
266
+
267
+ def keys = entries_snapshot.map(&:first)
268
+
269
+ def each(&block)
270
+ return enum_for(__callee__) { size } unless block
271
+
272
+ entries_snapshot.each { |pair| block.call(pair) }
273
+ self
274
+ end
275
+ alias each_pair each
276
+
277
+ def each_live
278
+ return enum_for(__method__) { size } unless block_given?
279
+ concurrent_each_pair { |key, value| yield [unwrap_key(key), value] }
280
+ self
281
+ end
282
+
283
+ def each_key(&block)
284
+ return enum_for(__callee__) { size } unless block
285
+
286
+ entries_snapshot.each { |pair| block.call(pair.first) }
287
+ self
288
+ end
289
+
290
+ def each_value(&block)
291
+ return enum_for(__callee__) { size } unless block
292
+
293
+ entries_snapshot.each { |pair| block.call(pair.last) }
294
+ self
295
+ end
296
+
297
+ def delete(key)
298
+ check_frozen!
299
+ wrapped = wrap_key(key)
300
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
301
+ value = nil
302
+ commit_mutation(reservation) do
303
+ value = native_operation { concurrent_delete(wrapped) }
304
+ changed!
305
+ end
306
+ value
307
+ end
308
+ result
309
+ end
310
+
311
+ def getkey(key)
312
+ wrapped = wrap_key(key)
313
+ return unless concurrent_key?(wrapped)
314
+
315
+ concurrent_each_pair do |stored, _value|
316
+ return unwrap_key(stored) if keys_equal?(stored, wrapped)
317
+ end
318
+ nil
319
+ end
320
+
321
+ def clear
322
+ check_frozen!
323
+ clear_key_operations do
324
+ native_operation { concurrent_clear }
325
+ changed!
326
+ end
327
+ self
328
+ end
329
+
330
+ def compute(key)
331
+ check_frozen!
332
+ wrapped = wrap_key(key)
333
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
334
+ value = yield(native_operation { concurrent_get(wrapped) })
335
+ stored = commit_mutation(reservation) do
336
+ native_operation { concurrent_store(wrapped, value) }
337
+ changed!
338
+ end
339
+ value if stored
340
+ end
341
+ result
342
+ end
343
+
344
+ def compute_if_absent(key)
345
+ check_frozen!
346
+ wrapped = wrap_key(key)
347
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
348
+ next native_operation { concurrent_get(wrapped) } if
349
+ native_operation { concurrent_key?(wrapped) }
350
+
351
+ value = yield
352
+ stored = commit_mutation(reservation) do
353
+ native_operation { concurrent_store(wrapped, value) }
354
+ changed!
355
+ end
356
+ value if stored
357
+ end
358
+ result
359
+ end
360
+
361
+ def compute_if_present(key)
362
+ check_frozen!
363
+ wrapped = wrap_key(key)
364
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
365
+ next unless native_operation { concurrent_key?(wrapped) }
366
+
367
+ value = yield(native_operation { concurrent_get(wrapped) })
368
+ stored = commit_mutation(reservation) do
369
+ native_operation { concurrent_store(wrapped, value) }
370
+ changed!
371
+ end
372
+ value if stored
373
+ end
374
+ result
375
+ end
376
+
377
+ def delete_pair(key, value)
378
+ check_frozen!
379
+ return delete_pair_by_identity(key, value) if compare_values_by_identity?
380
+
381
+ wrapped = wrap_key(key)
382
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
383
+ deleted = false
384
+ commit_mutation(reservation) do
385
+ deleted = native_operation { concurrent_delete_pair(wrapped, value) }
386
+ changed! if deleted
387
+ end
388
+ deleted
389
+ end
390
+ result
391
+ end
392
+
393
+ def get_and_set(key, value)
394
+ check_frozen!
395
+ wrapped = wrap_key(key)
396
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
397
+ previous = nil
398
+ commit_mutation(reservation) do
399
+ previous = native_operation { concurrent_get_and_set(wrapped, value) }
400
+ changed!
401
+ end
402
+ previous
403
+ end
404
+ result
405
+ end
406
+
407
+ def get_or_default(key, default) = concurrent_get_or_default(wrap_key(key), default)
408
+
409
+ def merge_pair(key, value)
410
+ check_frozen!
411
+ wrapped = wrap_key(key)
412
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
413
+ present = native_operation { concurrent_key?(wrapped) }
414
+ merged = present ? yield(native_operation { concurrent_get(wrapped) }) : value
415
+ stored = commit_mutation(reservation) do
416
+ native_operation { concurrent_store(wrapped, merged) }
417
+ changed!
418
+ end
419
+ merged if stored
420
+ end
421
+ result
422
+ end
423
+
424
+ def replace_if_exists(key, value)
425
+ check_frozen!
426
+ wrapped = wrap_key(key)
427
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
428
+ previous = nil
429
+ commit_mutation(reservation) do
430
+ previous = native_operation { concurrent_replace_if_exists(wrapped, value) }
431
+ changed!
432
+ end
433
+ previous
434
+ end
435
+ result
436
+ end
437
+
438
+ def replace_pair(key, expected, replacement)
439
+ check_frozen!
440
+ return replace_pair_by_identity(key, expected, replacement) if compare_values_by_identity?
441
+
442
+ wrapped = wrap_key(key)
443
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
444
+ replaced = false
445
+ commit_mutation(reservation) do
446
+ replaced = native_operation { concurrent_replace_pair(wrapped, expected, replacement) }
447
+ changed! if replaced
448
+ end
449
+ replaced
450
+ end
451
+ result
452
+ end
453
+
454
+ private
455
+
456
+ def check_frozen! = Internal::Freeze.check(self)
457
+
458
+ def commit_mutation(reservation, &)
459
+ check_frozen!
460
+ reservation.commit(&)
461
+ end
462
+
463
+ def with_mutating_key_operation(key, deadline, &)
464
+ with_key_operation(key, deadline) do |reservation|
465
+ with_mutation_callback_guard(key) do
466
+ check_frozen!
467
+ yield reservation
468
+ end
469
+ end
470
+ end
471
+
472
+ def with_mutation_callback_guard(key)
473
+ return yield unless key.is_a?(Key)
474
+
475
+ key.mutation_owner = self
476
+ yield
477
+ ensure
478
+ key.mutation_owner = nil if key.is_a?(Key)
479
+ end
480
+
481
+ def wrap_key(key)
482
+ return IdentityKey.new(key) if compare_keys_by_identity?
483
+ key = String.instance_method(:-@).bind_call(key) if String === key && !key.frozen?
484
+ Key.new(key)
485
+ end
486
+
487
+ def unwrap_key(key) = key.is_a?(IdentityKey) || key.is_a?(Key) ? key.value : key
488
+
489
+ def entries_snapshot
490
+ entries = []
491
+ concurrent_each_pair { |key, value| entries << [unwrap_key(key), value] }
492
+ entries
493
+ end
494
+
495
+ def keys_equal?(left, right)
496
+ compare_keys_by_identity? ? left.eql?(right) : left.hash == right.hash && left.eql?(right)
497
+ end
498
+
499
+ def delete_pair_by_identity(key, expected)
500
+ wrapped = wrap_key(key)
501
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
502
+ next false unless native_operation { concurrent_key?(wrapped) } &&
503
+ identical?(native_operation { concurrent_get(wrapped) }, expected)
504
+
505
+ commit_mutation(reservation) do
506
+ native_operation { concurrent_delete(wrapped) }
507
+ changed!
508
+ end
509
+ end
510
+ result
511
+ end
512
+
513
+ def replace_pair_by_identity(key, expected, replacement)
514
+ wrapped = wrap_key(key)
515
+ _, result = with_mutating_key_operation(wrapped, nil) do |reservation|
516
+ next false unless native_operation { concurrent_key?(wrapped) } &&
517
+ identical?(native_operation { concurrent_get(wrapped) }, expected)
518
+
519
+ commit_mutation(reservation) do
520
+ native_operation { concurrent_store(wrapped, replacement) }
521
+ changed!
522
+ end
523
+ end
524
+ result
525
+ end
526
+
527
+ def validate_boolean(value, name)
528
+ return if identical?(value, true) || identical?(value, false)
529
+ raise ArgumentError, "#{name} must be true or false"
530
+ end
531
+
532
+ def native_operation(&)
533
+ entered = false
534
+ @state_mutex.synchronize do
535
+ reject_active_operation_reentry!
536
+ Thread.handle_interrupt(INTERRUPT_MASK) do
537
+ register_active_operation
538
+ entered = true
539
+ end
540
+ end
541
+ yield
542
+ ensure
543
+ Thread.handle_interrupt(INTERRUPT_MASK) { leave_operation } if entered
544
+ end
545
+
546
+ def leave_operation
547
+ @state_mutex.synchronize { unregister_active_operation }
548
+ end
549
+
550
+ def changed! = @change_signal.broadcast
551
+
552
+ def wait_for_value(key, expected, deadline, fallback, non_nil:)
553
+ wrapped = wrap_key(key)
554
+ while true
555
+ generation = @change_signal.generation
556
+ completed, current = with_key_operation(wrapped, deadline) do
557
+ native_operation { concurrent_get(wrapped) }
558
+ end
559
+ return fallback&.call unless completed
560
+ ready = non_nil ? !current.nil? : !values_equal?(current, expected)
561
+ return current if ready
562
+ return fallback&.call unless wait_for_signal(@change_signal, generation, deadline)
563
+ end
564
+ end
565
+
566
+ def wait_for_signal(signal, generation, deadline)
567
+ return signal.wait(generation) unless deadline
568
+
569
+ remaining = deadline - Clock.now
570
+ return false unless remaining.positive?
571
+ !signal.wait(generation, timeout: remaining).nil?
572
+ end
573
+
574
+ def timeout_deadline(timeout)
575
+ return if timeout.nil?
576
+
577
+ timeout = Float(timeout)
578
+ if !timeout.finite? || timeout.negative?
579
+ raise ArgumentError, "timeout must be a finite, non-negative number or nil"
580
+ end
581
+ Clock.now + timeout
582
+ end
583
+
584
+ def reject_active_operation_reentry!
585
+ return unless active_operation_owned_by?(Fiber.current)
586
+
587
+ raise ThreadError, "deadlock; recursive map access during an operation"
588
+ end
589
+
590
+ def register_active_operation
591
+ fiber = Fiber.current
592
+ thread = Thread.current
593
+ if @active_owners
594
+ @active_owners[fiber] = thread
595
+ elsif @active_owner_fiber
596
+ owners = {}.compare_by_identity
597
+ owners[@active_owner_fiber] = @active_owner_thread
598
+ owners[fiber] = thread
599
+ @active_owners = owners
600
+ @active_owner_fiber = @active_owner_thread = nil
601
+ else
602
+ @active_owner_thread = thread
603
+ @active_owner_fiber = fiber
604
+ end
605
+ end
606
+
607
+ def unregister_active_operation
608
+ if @active_owners
609
+ removed = @active_owners.delete(Fiber.current)
610
+ if @active_owners.one?
611
+ @active_owner_fiber, @active_owner_thread = @active_owners.first
612
+ @active_owners = nil
613
+ end
614
+ removed
615
+ elsif identical?(@active_owner_fiber, Fiber.current)
616
+ removed = @active_owner_thread
617
+ @active_owner_fiber = @active_owner_thread = nil
618
+ removed
619
+ end
620
+ end
621
+
622
+ def active_operation_owned_by?(fiber)
623
+ @active_owners ? @active_owners.key?(fiber) : identical?(@active_owner_fiber, fiber)
624
+ end
625
+
626
+ def values_equal?(left, right)
627
+ compare_values_by_identity? ? identical?(left, right) : left == right
628
+ end
629
+
630
+ def identical?(left, right) = BASIC_OBJECT_EQUAL_METHOD.bind_call(left, right)
631
+
632
+ def concurrent_get(...) = @map.[](...)
633
+ def concurrent_store(...) = @map.[]=(...)
634
+ def concurrent_clear(...) = @map.clear(...)
635
+ def concurrent_compute(...) = @map.compute(...)
636
+ def concurrent_compute_if_absent(...) = @map.compute_if_absent(...)
637
+ def concurrent_compute_if_present(...) = @map.compute_if_present(...)
638
+ def concurrent_delete(...) = @map.delete(...)
639
+ def concurrent_delete_pair(...) = @map.delete_pair(...)
640
+ def concurrent_each_pair(...) = @map.each_pair(...)
641
+ def concurrent_get_and_set(...) = @map.get_and_set(...)
642
+ def concurrent_get_or_default(...) = @map.get_or_default(...)
643
+ def concurrent_key?(...) = @map.key?(...)
644
+ def concurrent_merge_pair(...) = @map.merge_pair(...)
645
+ def concurrent_replace_if_exists(...) = @map.replace_if_exists(...)
646
+ def concurrent_replace_pair(...) = @map.replace_pair(...)
647
+ def concurrent_size(...) = @map.size(...)
648
+
649
+ private :concurrent_get, :concurrent_store, :concurrent_clear, :concurrent_compute,
650
+ :concurrent_compute_if_absent, :concurrent_compute_if_present, :concurrent_delete,
651
+ :concurrent_delete_pair, :concurrent_each_pair, :concurrent_get_and_set,
652
+ :concurrent_get_or_default, :concurrent_key?, :concurrent_merge_pair,
653
+ :concurrent_replace_if_exists, :concurrent_replace_pair, :concurrent_size
654
+ end
655
+ end
656
+ end