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,229 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # Map operations that return independent maps of the same kind.
8
+ # Include this in subclasses of {Map} that support copying.
9
+ # Operations work on an independent copy, not an atomic snapshot of the source.
10
+ # Local copies transform the current scope and retain constructor defaults for other scopes.
11
+ module DuplicableMap
12
+ # Return an independent map containing only the requested keys that exist.
13
+ # @param keys [Array<BasicObject>] keys to retain, using the map's lookup rules
14
+ # @return [Map] A map of the same class with the same settings.
15
+ def slice(*keys)
16
+ with_map_copy do |_, map|
17
+ retained = {}.compare_by_identity
18
+ keys.each do |key|
19
+ key = normalize_copied_key(key)
20
+ retained[map.getkey(key)] = true if map.key?(key)
21
+ end
22
+ # Tree backends expose each, but not each_key.
23
+ map.each { |key, _| map.delete(key) unless retained.key?(key) } # rubocop:disable Style/HashEachMethods
24
+ end
25
+ end
26
+
27
+ # Return an independent map without the requested keys.
28
+ # @param keys [Array<BasicObject>] keys to omit, using the map's lookup rules
29
+ # @return [Map] A map of the same class with the same settings.
30
+ def except(*keys)
31
+ with_map_copy do |_, map|
32
+ keys.each { map.delete(normalize_copied_key(it)) }
33
+ end
34
+ end
35
+
36
+ # Return an independent map without entries whose value is nil. False values are retained.
37
+ # @return [Map] A map of the same class with the same settings.
38
+ def compact
39
+ with_map_copy do |copy, map|
40
+ nil_value = copy.wrap_value(nil)
41
+ map.each { |key, value| map.delete(key) if nil_value.equal?(value) }
42
+ end
43
+ end
44
+
45
+ # Return an independent map containing entries accepted by the block.
46
+ # The block receives public values from the copy. Stored values and map settings are preserved.
47
+ # @yieldparam key [BasicObject] an existing key
48
+ # @yieldparam value [BasicObject] the public value
49
+ # @return [Map, Enumerator] A map of the same class, or an Enumerator without a block.
50
+ def select
51
+ return enum_for(__method__) { size } unless block_given?
52
+ with_map_copy do |copy, map|
53
+ map.each { |key, value| map.delete(key) unless yield(key, copy.unwrap_value(value)) }
54
+ end
55
+ end
56
+ alias filter select
57
+
58
+ # Return an independent map excluding entries accepted by the block.
59
+ # The block receives public values from the copy. Stored values and map settings are preserved.
60
+ # @yieldparam key [BasicObject] an existing key
61
+ # @yieldparam value [BasicObject] the public value
62
+ # @return [Map, Enumerator] A map of the same class, or an Enumerator without a block.
63
+ def reject
64
+ return enum_for(__method__) { size } unless block_given?
65
+ with_map_copy do |copy, map|
66
+ map.each { |key, value| map.delete(key) if yield(key, copy.unwrap_value(value)) }
67
+ end
68
+ end
69
+
70
+ # Return an independent map with transformed keys and unchanged stored values.
71
+ # Mapping entries take precedence over the block. Unmapped keys are retained when no block is given.
72
+ # Transformed keys pass through this map's normalizer. On collisions, the last visited entry wins.
73
+ # Bounded copies rebuild eviction history as transformed entries are inserted.
74
+ # @param mapping [Hash, #to_hash] optional replacements for existing keys
75
+ # @yieldparam key [BasicObject] an existing key
76
+ # @yieldreturn [BasicObject] the replacement key
77
+ # @return [Map, Enumerator] A map of the same class, or an Enumerator without a mapping or block.
78
+ def transform_keys(mapping = UNDEFINED)
79
+ if UNDEFINED.equal?(mapping)
80
+ return enum_for(__method__, mapping) { size } unless block_given?
81
+ mapping = nil
82
+ else
83
+ mapping = Hash.try_convert(mapping) || raise(TypeError, "mapping must be a Hash or respond to #to_hash")
84
+ end
85
+
86
+ with_map_copy(empty: true) do |_, map|
87
+ internal_map.each do |key, value|
88
+ if mapping&.key?(key)
89
+ key = normalize_copied_key(mapping.fetch(key))
90
+ elsif block_given?
91
+ key = normalize_copied_key(yield(key))
92
+ end
93
+ map[key] = value
94
+ end
95
+ end
96
+ end
97
+
98
+ # Return an independent map with transformed values and unchanged keys.
99
+ # Results follow the map's transfer mode. Move-mode results are copied before transfer to preserve the source.
100
+ # Bounded copies count replacements as writes. The source's eviction history is unchanged.
101
+ # @yieldparam value [BasicObject] the current value
102
+ # @yieldreturn [BasicObject] the replacement value
103
+ # @return [Map, Enumerator] A map of the same class, or an Enumerator without a block.
104
+ def transform_values
105
+ return enum_for(__method__) { size } unless block_given?
106
+ copier = ModeManager.new(mode: :copy) if respond_to?(:mode) && mode == :move
107
+ with_map_copy do |copy, map|
108
+ map.each do |key, value|
109
+ value = yield copy.unwrap_value(value)
110
+ value = copier.unwrap(copier.wrap(value)) if copier
111
+ map[key] = copy.wrap_value(value)
112
+ end
113
+ end
114
+ end
115
+
116
+ # Return an independent map with keys and values exchanged.
117
+ # New keys follow the map's normal key normalization and shareability rules.
118
+ # On collisions, the last visited entry wins. Bounded copies rebuild eviction history.
119
+ # @return [Map] A map of the same class with the same settings.
120
+ # @raise [Ractor::IsolationError] if a new key violates the map's shareability rules
121
+ def invert
122
+ copier = ModeManager.new(mode: :copy) if respond_to?(:mode) && mode == :move
123
+ empty_copy.tap do |copy|
124
+ each_pair do |key, value|
125
+ key = copier.unwrap(copier.wrap(key)) if copier
126
+ copy[value] = key
127
+ end
128
+ end
129
+ end
130
+
131
+ # Return an independent map with entries from each input applied in order.
132
+ # Incoming keys pass through the normalizer. A block resolves collisions using the canonical key.
133
+ # Move-mode values are copied before transfer to preserve the source and inputs.
134
+ # Bounded copies retain eviction history and apply their usual capacity limits to new writes.
135
+ # @param others [Array<Map, Hash, #to_hash>] maps to merge, with later entries taking precedence
136
+ # @yieldparam key [BasicObject] the canonical key shared by both maps
137
+ # @yieldparam old_value [BasicObject] the current value in the result
138
+ # @yieldparam new_value [BasicObject] the incoming value
139
+ # @yieldreturn [BasicObject] the replacement value
140
+ # @return [Map] A map of the same class with the same settings.
141
+ def merge(*others)
142
+ copier = ModeManager.new(mode: :copy) if respond_to?(:mode) && mode == :move
143
+ with_map_copy do |copy, map|
144
+ others.each do |other|
145
+ unless Map === other
146
+ other = Hash.try_convert(other) || raise(TypeError, "input must be a Map, Hash, or respond to #to_hash")
147
+ end
148
+ other.each_pair do |key, value|
149
+ key = normalize_copied_key(key)
150
+ value = yield(key, copy.unwrap_value(map[key]), value) if block_given? && map.key?(key)
151
+ value = copier.unwrap(copier.wrap(value)) if copier
152
+ map[key] = copy.wrap_value(value)
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ # Return a lambda that looks up a key using this map's current contents and lookup rules.
159
+ # The lambda is Ractor-shareable when this map is Ractor-shareable.
160
+ # @return [Proc] A one-argument lookup lambda.
161
+ def to_proc
162
+ lookup = ->(key) { self[key] }
163
+ Ractor.shareable?(self) ? Ractor.shareable_lambda(self: self, &lookup) : lookup
164
+ end
165
+
166
+ # Return keys and values in a flattened Array.
167
+ # The default depth flattens entry pairs. Zero preserves pairs, and negative depths flatten all levels.
168
+ # @param level [Integer, #to_int] the number of Array levels to flatten
169
+ # @return [Array] The flattened entries.
170
+ def flatten(level = 1)
171
+ level = Integer.try_convert(level) || raise(TypeError, "level must be an Integer or respond to #to_int")
172
+ to_a.flatten(level)
173
+ end
174
+
175
+ protected
176
+
177
+ # The backing map used by copying and transformation operations.
178
+ # Scoped maps override this to resolve storage for the current scope.
179
+ # @api private
180
+ def internal_map = @map
181
+
182
+ private
183
+
184
+ def initialize_dup(other)
185
+ super
186
+ publish_shareable_copy(other, operation: :dup) if is_a?(Shareable)
187
+ end
188
+
189
+ def initialize_clone(other, freeze: nil)
190
+ super
191
+ publish_shareable_copy(other, operation: :clone, freeze:) if is_a?(Shareable)
192
+ end
193
+
194
+ def initialize_copy(other, empty: false)
195
+ super(other)
196
+ normalizer = other.instance_variable_get(:@key_normalizer)
197
+ if normalizer && !is_a?(ConcurrentMap)
198
+ operations = Internal::KeyNormalizer.operations_for(self)
199
+ Internal::KeyNormalizer.install(self, normalizer, operations) unless is_a?(operations)
200
+ end
201
+ install_copied_map(copy_map_backend(other.internal_map, empty:))
202
+ end
203
+
204
+ def install_copied_map(map) = @map = map
205
+
206
+ def empty_copy
207
+ # Preserve wrapper settings without copying entries or rerunning the public constructor.
208
+ copy = self.class.allocate
209
+ instance_variables.each { |name| copy.instance_variable_set(name, instance_variable_get(name)) }
210
+ copy.__send__(:initialize_copy, self, empty: true)
211
+ copy.__send__(:publish_shareable) if is_a?(Shareable)
212
+ copy
213
+ end
214
+
215
+ def with_map_copy(empty: false)
216
+ copy = empty ? empty_copy : dup
217
+ map = copy.internal_map
218
+ map = map.instance_variable_get(:@map) if map.is_a?(Internal::KeyNormalizer::ConcurrentMap)
219
+ yield copy, map
220
+ copy
221
+ end
222
+
223
+ def normalize_copied_key(key)
224
+ normalizer = instance_variable_get(:@key_normalizer)
225
+ normalizer ? normalizer.call(key) : key
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # A rendezvous where callers pair up and receive each other's offered value.
8
+ # Each call participates in one exchange. The exchanger can be reused by any number of callers.
9
+ class Exchanger
10
+ include Internal::Noncopyable
11
+ include Internal::Inspect
12
+
13
+ # Wait for a partner and return the partner's value.
14
+ # Offering nil allows a caller to receive a value without sending a payload.
15
+ # A timeout of zero only exchanges with a partner that is already waiting.
16
+ # A successful exchange of nil does not invoke the fallback.
17
+ #
18
+ # @param offered [BasicObject, nil] the value to give to the partner
19
+ # @param timeout [Numeric, nil] the maximum seconds to wait, or nil to wait indefinitely
20
+ # @yield called without arguments when the timeout expires
21
+ # @return [BasicObject, nil] the partner's value, or the fallback result or nil on timeout
22
+ # @raise [ArgumentError] if the timeout is negative or not finite
23
+ def exchange(offered, timeout: nil, &) = @exchanger.exchange(offered, timeout:, &)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # @abstract Common boolean interface and serialization for atomic flags.
8
+ # @note This is a module rather than a class so {Farce::Flag} can inherit
9
+ # directly from the native flag and avoid delegation overhead.
10
+ #
11
+ # @!method value
12
+ # @return [Boolean] the current value
13
+ #
14
+ # @!method set
15
+ # Set the flag to true.
16
+ # @return [true]
17
+ #
18
+ # @!method unset
19
+ # Set the flag to false.
20
+ # @return [false]
21
+ #
22
+ # @!method store(value)
23
+ # Set the flag to the given value.
24
+ # @param value [Boolean] the new value
25
+ # @return [Boolean] the new value
26
+ # @raise [ArgumentError] if the value is not true or false
27
+ #
28
+ # @!method value=(value)
29
+ # Alias for {#store}
30
+ #
31
+ # @!method swap(value)
32
+ # Replace the value and return its previous state.
33
+ # @param value [Boolean] the new value
34
+ # @return [Boolean] the previous value
35
+ # @raise [ArgumentError] if the value is not true or false
36
+ #
37
+ # @!method compare_and_set(expected_value, replacement_value)
38
+ # Replace the value only if it matches the expected value.
39
+ # @param expected_value [Boolean] the expected current value
40
+ # @param replacement_value [Boolean] the new value
41
+ # @return [Boolean] whether the replacement succeeded
42
+ # @raise [ArgumentError] if either argument is not true or false
43
+ #
44
+ # @!method toggle
45
+ # Atomically invert the value.
46
+ # @return [Boolean] the new value
47
+ module Flag
48
+ include Internal::MarshalSupport::Flag
49
+ include Internal::Copyable
50
+ include Value
51
+ include Internal::ValueSerialization
52
+ include Internal::Inspect
53
+
54
+ # @api private
55
+ def inspect_with(inspector)
56
+ begin
57
+ current = value
58
+ rescue StandardError
59
+ # FrozenError may inspect an allocated flag before it is initialized.
60
+ return inspector.object_with_address(self)
61
+ end
62
+
63
+ super do
64
+ yield if block_given?
65
+ inspector.breakable
66
+ inspector.object(current)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # @abstract Shared factory, caching, and delegation behavior for lazy values.
8
+ class Lazy
9
+ include Internal::MarshalSupport::Initialize
10
+ include Internal::Copyable
11
+ include Internal::Inspect
12
+ include Value
13
+
14
+ # @overload initialize(factory)
15
+ # @param [Class, Proc, #call] factory The factory to use for creating the value. Must be ractor-shareable.
16
+ #
17
+ # @overload initialize(self: nil)
18
+ # @yield The block to use for creating the value. Must be ractor-shareable.
19
+ # @yieldreceiver [BasicObject] The `self` parameter provided, or `nil` if not provided.
20
+ # @yieldreturn [BasicObject] The value to be returned by the lazy instance.
21
+ # @param [BasicObject] self The `self` parameter to be provided to the block. Must be ractor-shareable.
22
+ def initialize(factory = nil, **, &)
23
+ @factory = prepare_factory(factory, **, &)
24
+ @atom = new_internal_atom
25
+ super()
26
+ end
27
+
28
+ # The first time this method is called, the value will be computed based on the factory provided.
29
+ # Subsequent calls will return the same value.
30
+ #
31
+ # Concurrent access computes the value once.
32
+ # Shareable variants support calls from any Ractor.
33
+ # @return [BasicObject] The value computed by the factory.
34
+ def value
35
+ atom = internal_atom
36
+ value = atom.value
37
+ if value.nil?
38
+ value = atom.store_if_absent do
39
+ value = compute_value
40
+ value.nil? ? UNDEFINED : value
41
+ end
42
+ end
43
+ value unless UNDEFINED.equal?(value)
44
+ end
45
+
46
+ # @api private
47
+ def marshal_dump
48
+ current = marshal_current_value
49
+ resolved = !current.nil?
50
+ stored = UNDEFINED.equal?(current) ? nil : current
51
+ manager = @manager if defined?(@manager)
52
+ options = {}
53
+ options[:mode] = manager.mode if manager
54
+ options[:manager] = manager if manager
55
+ options[:scope] = scope if is_a?(Local::Lazy)
56
+
57
+ # Other scopes still need their factory even when this scope is resolved.
58
+ factory = @factory if !resolved || is_a?(Local::Lazy)
59
+
60
+ [1, resolved, factory, Internal::MarshalSupport.value(stored), options, frozen?]
61
+ end
62
+
63
+ # @api private
64
+ def marshal_load(data)
65
+ resolved, factory, stored, options, frozen = Internal::MarshalSupport.payload(data, 5)
66
+ @manager = options.delete(:manager) if options.key?(:manager)
67
+ initialize(factory, **options)
68
+ if resolved
69
+ value = Internal::MarshalSupport.restore_value(stored)
70
+ internal_atom.store(value.nil? ? UNDEFINED : value)
71
+ end
72
+ Internal::MarshalSupport.freeze(self, frozen)
73
+ end
74
+
75
+ # @api private
76
+ def inspect_with(inspector)
77
+ super do
78
+ inspector.breakable
79
+ display_value(inspector)
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ # @api private
86
+ def marshal_current_value = internal_atom.value
87
+
88
+ def internal_atom = @atom
89
+ def new_internal_atom = Internal::StrictAtom.new
90
+ def compute_value = @factory.is_a?(Class) ? @factory.new : @factory.call
91
+ def prepare_proc(factory, **) = Ractor.shareable_proc(**, &factory)
92
+
93
+ def prepare_factory(factory, **options, &block)
94
+ Internal.self_option(options.dup)
95
+ if block
96
+ raise ArgumentError, "factory and block cannot be both given" unless factory.nil?
97
+ factory = block
98
+ end
99
+ factory.is_a?(Proc) ? prepare_proc(factory, **options) : factory
100
+ end
101
+
102
+ def display_value(inspector, ...)
103
+ case value = internal_atom.value
104
+ when nil then inspector.object(@factory, ...)
105
+ when UNDEFINED then inspector.object(nil)
106
+ else inspector.object(value, ...)
107
+ end
108
+ end
109
+
110
+ # Delegates all method calls to {#value}.
111
+ def method_missing(...) = value.public_send(...)
112
+ def respond_to_missing?(...) = value.respond_to?(...)
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # @abstract Shared checkout, return, ownership, and retirement behavior for leases.
8
+ class Lease
9
+ include Internal::Noncopyable
10
+ include Internal::Inspect
11
+
12
+ # Construct a lease from one resource-building block.
13
+ # @yield builds the resource managed by the lease
14
+ # @yieldreturn [BasicObject] the initial resource
15
+ # @raise [ArgumentError] if no block is given or the resource is nil or boolean
16
+ def initialize
17
+ raise ArgumentError, "a resource constructor block is required" unless block_given?
18
+
19
+ @lease = new_internal_lease(yield)
20
+ super
21
+ end
22
+
23
+ # Acquire the resource, waiting until it is available.
24
+ # @param timeout [Numeric, nil] maximum seconds to wait
25
+ # @yieldparam resource [BasicObject] the acquired resource
26
+ # @return [BasicObject] the resource without a block, or the block result
27
+ # @raise [Farce::TimeoutError] if the timeout expires
28
+ # @raise [Farce::RetiredLeaseError] if the lease is retired
29
+ def checkout(timeout: nil, &block)
30
+ lease = internal_lease
31
+ block ? lease.checkout(timeout:, &block) : lease.checkout(timeout:)
32
+ end
33
+
34
+ # Acquire the resource immediately if it is available.
35
+ # @yieldparam resource [BasicObject] the acquired resource
36
+ # @return [BasicObject, nil] the resource or block result, or nil when unavailable
37
+ # @raise [Farce::RetiredLeaseError] if the lease is retired
38
+ def try_checkout(&block)
39
+ lease = internal_lease
40
+ block ? lease.try_checkout(&block) : lease.try_checkout
41
+ end
42
+
43
+ # Return an explicitly checked-out resource or a replacement.
44
+ # @param resource [BasicObject] the resource to store
45
+ # @return [self]
46
+ # @raise [Farce::OwnershipError] unless the current Fiber owns an explicit checkout
47
+ # @raise [Farce::RetiredLeaseError] if the lease is retired
48
+ # @raise [ArgumentError] if the resource is nil or boolean
49
+ def checkin(resource)
50
+ internal_lease.checkin(resource)
51
+ self
52
+ end
53
+
54
+ # Permanently retire this lease and wake its waiters.
55
+ #
56
+ # The current Fiber must own the checkout. Retirement ends that checkout,
57
+ # so automatic block cleanup does not return the resource. The resource is
58
+ # not closed or otherwise disposed. Calling this again after retirement is safe.
59
+ # @return [self]
60
+ # @raise [Farce::OwnershipError] unless the current Fiber owns the checkout
61
+ def retire
62
+ internal_lease.retire
63
+ self
64
+ end
65
+
66
+ # @return [Boolean] whether the resource is available for checkout
67
+ def available? = internal_lease.available?
68
+
69
+ # @return [Boolean] whether the resource is checked out
70
+ def checked_out? = internal_lease.checked_out?
71
+
72
+ # @return [Boolean] whether the current Fiber owns the checkout
73
+ def owned? = internal_lease.owned?
74
+
75
+ # @return [Boolean] whether the lease has been permanently retired
76
+ def retired? = internal_lease.retired?
77
+
78
+ # @api private
79
+ def inspect_with(inspector)
80
+ super do
81
+ yield if block_given?
82
+ inspector.breakable
83
+ next inspector.text("checked_out") if checked_out?
84
+ next inspector.text("available") if available?
85
+ next inspector.text("retired") if retired?
86
+ inspector.text("unknown")
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ def checkout_with_handoff(...) = internal_lease.checkout_with_handoff(...)
93
+ def try_checkout_with_handoff(...) = internal_lease.try_checkout_with_handoff(...)
94
+ def checkin_scope(resource) = internal_lease.checkin_scope(resource)
95
+ def explicitly_owned? = internal_lease.explicitly_owned?
96
+ def mark_scope_managed = internal_lease.mark_scope_managed
97
+ def scope_managed? = internal_lease.scope_managed?
98
+ def owned_resource = internal_lease.owned_resource
99
+ def replace_owned_resource(resource) = internal_lease.replace_owned_resource(resource)
100
+ def internal_lease = @lease
101
+ def new_internal_lease(_) = raise(NoMethodError, "abstract lease storage")
102
+ end
103
+ end
104
+ end