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,256 @@
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 UnsharedAtom
9
+ TIMED_OUT = Object.new.freeze
10
+ private_constant :TIMED_OUT
11
+
12
+ def initialize(value = nil, compare_by_identity: false)
13
+ if compare_by_identity != true && compare_by_identity != false
14
+ raise ArgumentError, "compare_by_identity must be a boolean"
15
+ end
16
+
17
+ @value = value
18
+ @compare_by_identity = compare_by_identity
19
+ @mutex = Mutex.new
20
+ @signal = ConditionVariable.new
21
+ @updating = false
22
+ @updating_fiber = nil
23
+ @updating_thread = nil
24
+ @version = 0
25
+ @farce_frozen = false
26
+ end
27
+
28
+ # @api private
29
+ def transaction_snapshot
30
+ PortableTransaction.snapshot(self, :atom)
31
+ end
32
+
33
+ def value = @mutex.synchronize { @value }
34
+
35
+ def freeze
36
+ @mutex.synchronize { @farce_frozen = true }
37
+ self
38
+ end
39
+
40
+ def frozen? = @mutex.synchronize { @farce_frozen }
41
+
42
+ def get(timeout: nil, &fallback)
43
+ result = with_available_value(timeout) { @value }
44
+ timed_out(result, fallback)
45
+ end
46
+
47
+ def store(new_value, timeout: nil, &fallback)
48
+ check_frozen!
49
+ result = with_available_value(timeout) do
50
+ check_frozen_locked!
51
+ @value = new_value
52
+ changed!
53
+ new_value
54
+ end
55
+ timed_out(result, fallback)
56
+ end
57
+
58
+ def swap(new_value, timeout: nil, &fallback)
59
+ check_frozen!
60
+ result = with_available_value(timeout) do
61
+ check_frozen_locked!
62
+ old_value = @value
63
+ @value = new_value
64
+ changed!
65
+ old_value
66
+ end
67
+ timed_out(result, fallback)
68
+ end
69
+
70
+ def store_if_absent(timeout: nil, &update)
71
+ raise LocalJumpError, "no block given" unless update
72
+ check_frozen!
73
+ deadline = timeout_deadline(timeout)
74
+
75
+ current = reserve(deadline) do
76
+ return @value unless @value.nil?
77
+ end
78
+ return if TIMED_OUT.equal?(current)
79
+
80
+ update_reserved(&update)
81
+ end
82
+
83
+ def compare_and_set(expected, new_value, timeout: nil)
84
+ check_frozen!
85
+ current = reserve(timeout_deadline(timeout))
86
+ return false if TIMED_OUT.equal?(current)
87
+
88
+ matched = false
89
+ begin
90
+ matches = values_equal?(current, expected)
91
+ check_frozen!
92
+ matched = matches
93
+ ensure
94
+ finish_update(new_value, changed: matched)
95
+ end
96
+ matched
97
+ end
98
+
99
+ def update(timeout: nil)
100
+ raise LocalJumpError, "no block given" unless block_given?
101
+ check_frozen!
102
+ deadline = timeout_deadline(timeout)
103
+
104
+ current = reserve(deadline)
105
+ return if TIMED_OUT.equal?(current)
106
+
107
+ update_reserved { yield(current) }
108
+ end
109
+
110
+ def upsert(initial_value, timeout: nil)
111
+ raise LocalJumpError, "no block given" unless block_given?
112
+ check_frozen!
113
+ deadline = timeout_deadline(timeout)
114
+
115
+ current = reserve(deadline) do
116
+ next unless @value.nil?
117
+
118
+ @value = initial_value
119
+ changed!
120
+ return initial_value
121
+ end
122
+ return if TIMED_OUT.equal?(current)
123
+
124
+ update_reserved { yield(current) }
125
+ end
126
+
127
+ def wait_until_changed(expected, timeout: nil, &fallback)
128
+ deadline = timeout_deadline(timeout)
129
+
130
+ loop do
131
+ current, version = @mutex.synchronize { [@value, @version] }
132
+ return current unless values_equal?(current, expected)
133
+
134
+ result = @mutex.synchronize do
135
+ next unless @version == version
136
+ reject_update_wait! if @updating
137
+ TIMED_OUT unless wait_for_signal(deadline)
138
+ end
139
+ return timed_out(result, fallback) if TIMED_OUT.equal?(result)
140
+ end
141
+ end
142
+
143
+ def wait_until_non_nil(timeout: nil, &) = wait_until_changed(nil, timeout:, &)
144
+ def compare_by_identity? = @compare_by_identity
145
+
146
+ alias value= store
147
+
148
+ private
149
+
150
+ def with_available_value(timeout)
151
+ deadline = timeout_deadline(timeout)
152
+
153
+ @mutex.synchronize do
154
+ while @updating
155
+ reject_update_wait!
156
+ return TIMED_OUT unless wait_for_signal(deadline)
157
+ end
158
+ yield
159
+ end
160
+ end
161
+
162
+ def reserve(deadline)
163
+ @mutex.synchronize do
164
+ while @updating
165
+ reject_update_wait!
166
+ return TIMED_OUT unless wait_for_signal(deadline)
167
+ end
168
+ check_frozen_locked!
169
+ yield if block_given?
170
+ @updating = true
171
+ @updating_fiber = Fiber.current
172
+ @updating_thread = Thread.current
173
+ @value
174
+ end
175
+ end
176
+
177
+ def update_reserved
178
+ changed = false
179
+ begin
180
+ result = yield
181
+ check_frozen!
182
+ changed = true
183
+ result
184
+ ensure
185
+ finish_update(result, changed:)
186
+ end
187
+ end
188
+
189
+ def finish_update(value, changed:)
190
+ @mutex.synchronize do
191
+ @value = value if changed
192
+ @version += 1 if changed
193
+ @updating = false
194
+ @updating_fiber = nil
195
+ @updating_thread = nil
196
+ @signal.broadcast
197
+ end
198
+ end
199
+
200
+ def changed!
201
+ @version += 1
202
+ @signal.broadcast
203
+ end
204
+
205
+ def check_frozen!
206
+ @mutex.synchronize { check_frozen_locked! }
207
+ end
208
+
209
+ def check_frozen_locked!
210
+ return unless @farce_frozen
211
+
212
+ raise FrozenError.new("can't modify frozen #{self.class}", receiver: self)
213
+ end
214
+
215
+ def timeout_deadline(timeout)
216
+ return unless timeout
217
+
218
+ timeout = Float(timeout)
219
+ raise ArgumentError, "timeout must be non-negative" if timeout.negative?
220
+ raise ArgumentError, "timeout must be finite" if timeout.infinite?
221
+ raise ArgumentError, "timeout must be a number" if timeout.nan?
222
+
223
+ Clock.now + timeout
224
+ end
225
+
226
+ def wait_for_signal(deadline)
227
+ return @signal.wait(@mutex) unless deadline
228
+
229
+ remaining = deadline - Clock.now
230
+ return false unless remaining.positive?
231
+
232
+ @signal.wait(@mutex, remaining)
233
+ true
234
+ end
235
+
236
+ def reject_update_wait!
237
+ raise ThreadError, "deadlock; recursive atom access during an update" if @updating_fiber.equal?(Fiber.current)
238
+
239
+ scheduler = Fiber.scheduler if Fiber.respond_to?(:scheduler)
240
+ return unless @updating_thread.equal?(Thread.current) && !scheduler
241
+
242
+ raise ThreadError, "deadlock; atom update is owned by another unscheduled fiber"
243
+ end
244
+
245
+ def timed_out(result, fallback)
246
+ return result unless TIMED_OUT.equal?(result)
247
+ fallback&.call
248
+ end
249
+
250
+ def values_equal?(left, right)
251
+ return left == right unless compare_by_identity?
252
+ left.equal?(right)
253
+ end
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal # :nodoc: all
7
+ UnsharedPriorityQueue = PriorityQueue
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal # :nodoc: all
7
+ class UnsharedQueue < Queue
8
+ def initialize(capacity: 1024, fiber_wait: :auto, track_age: false)
9
+ raise ArgumentError, "fiber_wait must be :auto, :io, or :block" unless %i[auto io block].include?(fiber_wait)
10
+ super(capacity:, track_age:)
11
+ end
12
+
13
+ def fiber_wait = :auto
14
+
15
+ private def check_value(_item); end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Internal
7
+ class UnsharedSignal < Signal
8
+ def self.for(mode)
9
+ raise ArgumentError, "fiber_wait must be :auto, :io, or :block" unless %i[auto io block].include?(mode)
10
+ new
11
+ end
12
+
13
+ # Alternative engines keep their existing scheduler coordination.
14
+ # @api private
15
+ def fiber_wait = :auto
16
+ end
17
+
18
+ UnsharedIOSignal = UnsharedSignal
19
+ UnsharedBlockSignal = UnsharedSignal
20
+ end
21
+ end
@@ -0,0 +1,377 @@
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 UnsharedVector
9
+ def initialize(source = nil, compare_by_identity: false)
10
+ validate_boolean(compare_by_identity, "compare_by_identity")
11
+ raise TypeError, "source must be an Array" unless source.nil? || source.is_a?(Array)
12
+
13
+ @values = source ? Array.new(source) : []
14
+ @compare_by_identity = compare_by_identity
15
+ @mutex = Mutex.new
16
+ @signal = Signal.new
17
+ @updating = false
18
+ @farce_frozen = false
19
+ end
20
+
21
+ # @api private
22
+ def transaction_snapshot
23
+ PortableTransaction.snapshot(self, :vector)
24
+ end
25
+
26
+ def freeze
27
+ @mutex.synchronize { @farce_frozen = true }
28
+ self
29
+ end
30
+
31
+ def frozen? = @mutex.synchronize { @farce_frozen }
32
+
33
+ def size = @mutex.synchronize { @values.size }
34
+
35
+ def snapshot = @mutex.synchronize { @values.dup }
36
+
37
+ def each
38
+ return enum_for(__method__) { size } unless block_given?
39
+
40
+ limit = size
41
+ index = 0
42
+ while index < limit
43
+ value = @mutex.synchronize do
44
+ return self if index >= @values.size
45
+ @values[index]
46
+ end
47
+ yield value
48
+ index += 1
49
+ end
50
+ self
51
+ end
52
+
53
+ def reverse_each
54
+ return enum_for(__method__) { size } unless block_given?
55
+
56
+ index = size
57
+ while index.positive?
58
+ value = @mutex.synchronize do
59
+ index = @values.size if index > @values.size
60
+ index -= 1
61
+ return self if index.negative?
62
+ @values[index]
63
+ end
64
+ yield value
65
+ end
66
+ self
67
+ end
68
+
69
+ def fetch(index)
70
+ index = convert_index(index)
71
+ found = true
72
+ value = @mutex.synchronize { @values.fetch(index) { found = false } }
73
+ return value if found
74
+ return yield(index) if block_given?
75
+
76
+ raise IndexError, "index #{index} outside of vector bounds"
77
+ end
78
+
79
+ def [](index)
80
+ index = convert_index(index)
81
+ @mutex.synchronize { @values[index] }
82
+ end
83
+
84
+ def []=(index, value)
85
+ check_frozen!
86
+ index = convert_index(index)
87
+ _, result = with_available(nil) do
88
+ check_frozen_locked!
89
+ store_value(index, value)
90
+ end
91
+ result
92
+ end
93
+
94
+ def get(index, timeout: nil)
95
+ index = convert_index(index)
96
+ completed, result = with_available(timeout_deadline(timeout)) { @values[index] }
97
+ result if completed
98
+ end
99
+
100
+ def store(index, value, timeout: nil)
101
+ check_frozen!
102
+ index = convert_index(index)
103
+ completed, result = with_available(timeout_deadline(timeout)) do
104
+ check_frozen_locked!
105
+ store_value(index, value)
106
+ end
107
+ completed ? result : false
108
+ end
109
+
110
+ def clear
111
+ check_frozen!
112
+ with_available(nil) do
113
+ check_frozen_locked!
114
+ @values.clear
115
+ changed!
116
+ end
117
+ self
118
+ end
119
+
120
+ def push(value, timeout: nil)
121
+ check_frozen!
122
+ completed, = with_available(timeout_deadline(timeout)) do
123
+ check_frozen_locked!
124
+ @values.push(value)
125
+ changed!
126
+ end
127
+ completed ? self : false
128
+ end
129
+
130
+ def pop(timeout: nil)
131
+ check_frozen!
132
+ completed, result = with_available(timeout_deadline(timeout)) do
133
+ check_frozen_locked!
134
+ next if @values.empty?
135
+
136
+ value = @values.pop
137
+ changed!
138
+ value
139
+ end
140
+ result if completed
141
+ end
142
+
143
+ def swap(index, replacement, timeout: nil)
144
+ check_frozen!
145
+ index = convert_index(index)
146
+ completed, result = with_available(timeout_deadline(timeout)) do
147
+ check_frozen_locked!
148
+ index = assignment_index(index)
149
+ previous = @values[index]
150
+ @values[index] = replacement
151
+ changed!
152
+ previous
153
+ end
154
+ result if completed
155
+ end
156
+
157
+ def store_if_absent(index, timeout: nil)
158
+ raise LocalJumpError, "no block given" unless block_given?
159
+ check_frozen!
160
+
161
+ index = convert_index(index)
162
+ completed, reservation = reserve(timeout_deadline(timeout)) do
163
+ normalized = assignment_index(index)
164
+ current = @values[normalized]
165
+ if current.nil?
166
+ @updating = true
167
+ [:store, normalized]
168
+ else
169
+ [:existing, current]
170
+ end
171
+ end
172
+ return unless completed
173
+ return reservation.last if reservation.first == :existing
174
+
175
+ _, normalized = reservation
176
+ result = yield
177
+ check_frozen!
178
+ @mutex.synchronize { @values[normalized] = result }
179
+ result
180
+ ensure
181
+ finish_update if reservation&.first == :store
182
+ end
183
+
184
+ def compare_and_set(index, expected, replacement, timeout: nil)
185
+ check_frozen!
186
+ index = convert_index(index)
187
+ completed, reservation = reserve(timeout_deadline(timeout)) do
188
+ normalized = lookup_index(index)
189
+ next unless normalized
190
+
191
+ @updating = true
192
+ [normalized, @values[normalized]]
193
+ end
194
+ return false unless completed && reservation
195
+
196
+ normalized, current = reservation
197
+ matches = values_equal?(current, expected)
198
+ check_frozen!
199
+ @mutex.synchronize { @values[normalized] = replacement if matches }
200
+ matches
201
+ ensure
202
+ finish_update if reservation
203
+ end
204
+
205
+ def upsert(index, initial, timeout: nil)
206
+ raise LocalJumpError, "no block given" unless block_given?
207
+ check_frozen!
208
+
209
+ index = convert_index(index)
210
+ completed, reservation = reserve(timeout_deadline(timeout)) do
211
+ normalized = assignment_index(index)
212
+ current = @values[normalized]
213
+ if current.nil?
214
+ @values[normalized] = initial
215
+ changed!
216
+ [:stored, initial]
217
+ else
218
+ @updating = true
219
+ [:update, normalized, current]
220
+ end
221
+ end
222
+ return unless completed
223
+ return reservation.last if reservation.first == :stored
224
+
225
+ _, normalized, current = reservation
226
+ result = yield(current)
227
+ check_frozen!
228
+ @mutex.synchronize { @values[normalized] = result }
229
+ result
230
+ ensure
231
+ finish_update if reservation&.first == :update
232
+ end
233
+
234
+ def update(index, timeout: nil)
235
+ raise LocalJumpError, "no block given" unless block_given?
236
+ check_frozen!
237
+
238
+ index = convert_index(index)
239
+ completed, reservation = reserve(timeout_deadline(timeout)) do
240
+ normalized = assignment_index(index)
241
+ @updating = true
242
+ [normalized, @values[normalized]]
243
+ end
244
+ return unless completed
245
+
246
+ normalized, current = reservation
247
+ result = yield(current)
248
+ check_frozen!
249
+ @mutex.synchronize { @values[normalized] = result }
250
+ result
251
+ ensure
252
+ finish_update if reservation
253
+ end
254
+
255
+ def wait_until_changed(index, expected, timeout: nil)
256
+ wait_for_value(convert_index(index), expected, timeout_deadline(timeout), non_nil: false)
257
+ end
258
+
259
+ def wait_until_non_nil(index, timeout: nil)
260
+ wait_for_value(convert_index(index), nil, timeout_deadline(timeout), non_nil: true)
261
+ end
262
+
263
+ def compare_by_identity? = @compare_by_identity
264
+
265
+ private
266
+
267
+ def store_value(index, value)
268
+ @values[assignment_index(index)] = value
269
+ changed!
270
+ value
271
+ end
272
+
273
+ def with_available(deadline)
274
+ while true
275
+ generation = @signal.generation
276
+ completed, result = @mutex.synchronize do
277
+ @updating ? [false, nil] : [true, yield]
278
+ end
279
+ return [true, result] if completed
280
+ return [false, nil] unless wait_for_signal(generation, deadline)
281
+ end
282
+ end
283
+
284
+ def reserve(deadline)
285
+ while true
286
+ generation = @signal.generation
287
+ completed, result = @mutex.synchronize do
288
+ if @updating
289
+ [false, nil]
290
+ else
291
+ check_frozen_locked!
292
+ [true, yield]
293
+ end
294
+ end
295
+ return [true, result] if completed
296
+ return [false, nil] unless wait_for_signal(generation, deadline)
297
+ end
298
+ end
299
+
300
+ def finish_update
301
+ @mutex.synchronize { @updating = false }
302
+ changed!
303
+ end
304
+
305
+ def changed! = @signal.broadcast
306
+
307
+ def check_frozen!
308
+ @mutex.synchronize { check_frozen_locked! }
309
+ end
310
+
311
+ def check_frozen_locked!
312
+ return unless @farce_frozen
313
+
314
+ raise FrozenError.new("can't modify frozen #{self.class}", receiver: self)
315
+ end
316
+
317
+ def wait_for_value(index, expected, deadline, non_nil:)
318
+ while true
319
+ generation = @signal.generation
320
+ current = @mutex.synchronize { @values[index] }
321
+ ready = non_nil ? !current.nil? : !values_equal?(current, expected)
322
+ return current if ready
323
+ return unless wait_for_signal(generation, deadline)
324
+ end
325
+ end
326
+
327
+ def wait_for_signal(generation, deadline)
328
+ return @signal.wait(generation) unless deadline
329
+
330
+ remaining = deadline - Clock.now
331
+ return false unless remaining.positive?
332
+ !@signal.wait(generation, timeout: remaining).nil?
333
+ end
334
+
335
+ def timeout_deadline(timeout)
336
+ return if timeout.nil?
337
+
338
+ timeout = Float(timeout)
339
+ if !timeout.finite? || timeout.negative?
340
+ raise ArgumentError, "timeout must be a finite, non-negative number or nil"
341
+ end
342
+ Clock.now + timeout
343
+ end
344
+
345
+ def lookup_index(index)
346
+ index += @values.size if index.negative?
347
+ index if index >= 0 && index < @values.size
348
+ end
349
+
350
+ def assignment_index(index)
351
+ return index unless index.negative?
352
+
353
+ normalized = @values.size + index
354
+ return normalized unless normalized.negative?
355
+ raise IndexError, "index #{index} too small for vector; minimum: -#{@values.size}"
356
+ end
357
+
358
+ def convert_index(index)
359
+ return index if index.is_a?(Integer)
360
+
361
+ raise TypeError, "no implicit conversion of #{index.class} into Integer" unless index.respond_to?(:to_int)
362
+ converted = index.to_int
363
+ return converted if converted.is_a?(Integer)
364
+ raise TypeError, "can't convert #{index.class} to Integer"
365
+ end
366
+
367
+ def validate_boolean(value, name)
368
+ return if value.equal?(true) || value.equal?(false)
369
+ raise ArgumentError, "#{name} must be true or false"
370
+ end
371
+
372
+ def values_equal?(left, right)
373
+ compare_by_identity? ? left.equal?(right) : left == right
374
+ end
375
+ end
376
+ end
377
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ require "farce/engine/shared/weak_atom/base"
6
+ require "farce/engine/shared/weak_map/reference"
7
+
8
+ module Farce
9
+ # @!visibility private
10
+ module Internal # :nodoc: all
11
+ class UnsharedWeakAtom < WeakAtomBase
12
+ private
13
+
14
+ def initialize_storage(value)
15
+ @mutex = Mutex.new
16
+ @reference = UnsharedWeakMapWeakReference.for(value)
17
+ end
18
+
19
+ def read_value = @mutex.synchronize { @reference.read.last }
20
+
21
+ def write_value(value)
22
+ @mutex.synchronize do
23
+ @reference = UnsharedWeakMapWeakReference.for(value)
24
+ @changes.update { |generation| generation + 1 }
25
+ end
26
+ nil
27
+ end
28
+ end
29
+ end
30
+ end