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,441 @@
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
+ # Portable per-key ownership and lifecycle implementation for LeaseMap.
9
+ class LeaseMap
10
+ include Freeze::Unfreezable
11
+
12
+ AUTO_LEASE_CONTEXTS = Object.new.freeze
13
+ private_constant :AUTO_LEASE_CONTEXTS
14
+
15
+ def initialize(initial_mapping, lease_class:, registry_class:)
16
+ raise TypeError, "lease map initializer must return a Hash" unless initial_mapping.is_a?(Hash)
17
+
18
+ @lease_class = lease_class
19
+ @registry_lock = Lock.new
20
+ @creation_locks = KeyLockMap.new(registry_class:)
21
+
22
+ initial_mapping.each_key { validate_key!(it) }
23
+ initial_mapping.each_value { validate_resource!(it) }
24
+
25
+ entries = initial_mapping.to_h { |key, resource| [key, new_lease(resource)] }
26
+ @registry = registry_class.new(entries, compare_values_by_identity: true)
27
+
28
+ return unless @registry.ractor_shareable?
29
+
30
+ Freeze.publish(self)
31
+ end
32
+
33
+ def checkout(key, receiver:, missing_key: key, timeout: nil, &block)
34
+ lease = fetch_lease(key, receiver:, missing_key:)
35
+ if block
36
+ entered = false
37
+ lease.checkout(timeout:) do |resource|
38
+ entered = true
39
+ block.call(resource)
40
+ end
41
+ else
42
+ context = auto_context
43
+ context ? acquire_for_context(lease, context, timeout:) : lease.checkout(timeout:)
44
+ end
45
+ rescue RetiredLeaseError
46
+ raise if entered
47
+ prune_binding(key, lease)
48
+ raise_missing_key(missing_key, receiver)
49
+ end
50
+
51
+ def try_checkout(key, receiver:, missing_key: key, &block)
52
+ lease = fetch_lease(key, receiver:, missing_key:)
53
+ if block
54
+ entered = false
55
+ lease.try_checkout do |resource|
56
+ entered = true
57
+ block.call(resource)
58
+ end
59
+ else
60
+ context = auto_context
61
+ context ? acquire_for_context(lease, context, try: true) : lease.try_checkout
62
+ end
63
+ rescue RetiredLeaseError
64
+ raise if entered
65
+ prune_binding(key, lease)
66
+ raise_missing_key(missing_key, receiver)
67
+ end
68
+
69
+ def checkin(key, resource, receiver:, missing_key: key)
70
+ lease = fetch_lease(key, receiver:, missing_key:)
71
+
72
+ if nil.equal?(resource)
73
+ unless explicitly_owned?(lease) && !scope_managed?(lease)
74
+ raise OwnershipError, "the current Fiber does not own an explicit checkout"
75
+ end
76
+
77
+ delete_entry(key, lease)
78
+ return self
79
+ end
80
+
81
+ lease.checkin(resource)
82
+ self
83
+ end
84
+
85
+ def read_entry(key)
86
+ lease = current_lease(key)
87
+ return [false, nil] unless lease
88
+
89
+ resource = if lease.owned?
90
+ owned_resource(lease)
91
+ elsif (context = auto_context)
92
+ acquire_for_context(lease, context)
93
+ else
94
+ raise RetiredLeaseError, "lease has been retired" if lease.retired?
95
+ raise OwnershipError, "the current Fiber does not own the key checkout"
96
+ end
97
+
98
+ [true, resource]
99
+ rescue RetiredLeaseError
100
+ prune_binding(key, lease)
101
+ [false, nil]
102
+ end
103
+
104
+ def lease_for(key, receiver:, missing_key: key) = fetch_lease(key, receiver:, missing_key:)
105
+
106
+ def store(key, resource)
107
+ key = validate_key!(key)
108
+ return delete(key) if nil.equal?(resource)
109
+ validate_resource!(resource)
110
+
111
+ lease = nil
112
+ inserted = false
113
+ context = auto_context
114
+ @creation_locks.synchronize(key) do
115
+ Thread.handle_interrupt(INTERRUPT_MASK) do
116
+ @registry_lock.synchronize do
117
+ lease = @registry[key]
118
+ if lease&.retired?
119
+ @registry.delete(key)
120
+ lease = nil
121
+ end
122
+ unless lease
123
+ lease = new_lease(resource)
124
+ @registry[key] = lease
125
+ acquire_for_context(lease, context) if context
126
+ inserted = true
127
+ end
128
+ end
129
+ end
130
+ end
131
+ return resource if inserted
132
+
133
+ replace(key, lease, resource)
134
+ rescue RetiredLeaseError
135
+ prune_binding(key, lease)
136
+ retry
137
+ end
138
+
139
+ def store_if_absent(key, &)
140
+ raise LocalJumpError, "no block given" unless block_given?
141
+ key = validate_key!(key)
142
+
143
+ while true
144
+ present, resource = read_entry(key)
145
+ return resource if present
146
+
147
+ context = auto_context
148
+ raise OwnershipError, "resource construction requires an automatic lease scope" unless context
149
+
150
+ inserted = false
151
+ @creation_locks.synchronize(key) do
152
+ next if current_lease(key)
153
+
154
+ Thread.handle_interrupt(INTERRUPT_MASK) do
155
+ resource = Thread.handle_interrupt(Exception => :immediate, &)
156
+ validate_resource!(resource)
157
+ @registry_lock.synchronize do
158
+ lease = new_lease(resource)
159
+ @registry[key] = lease
160
+ resource = acquire_for_context(lease, context)
161
+ inserted = true
162
+ end
163
+ end
164
+ end
165
+ return resource if inserted
166
+ end
167
+ end
168
+
169
+ def delete(key)
170
+ lease = current_lease(key)
171
+ return unless lease
172
+
173
+ delete_entry(key, lease)
174
+ rescue RetiredLeaseError
175
+ prune_binding(key, lease)
176
+ nil
177
+ end
178
+
179
+ def clear
180
+ entries_snapshot.each do |key, lease|
181
+ delete_entry(key, lease)
182
+ rescue RetiredLeaseError
183
+ prune_binding(key, lease)
184
+ end
185
+ self
186
+ end
187
+
188
+ def auto_lease
189
+ raise LocalJumpError, "no block given" unless block_given?
190
+
191
+ contexts = context = nil
192
+ pushed = false
193
+ Thread.handle_interrupt(INTERRUPT_MASK) do
194
+ contexts = auto_contexts
195
+ context = {}.compare_by_identity
196
+ (contexts[self] ||= []) << context
197
+ pushed = true
198
+ end
199
+ yield
200
+ ensure
201
+ if pushed
202
+ Thread.handle_interrupt(INTERRUPT_MASK) do
203
+ cleanup_context(context)
204
+ ensure
205
+ stack = contexts[self]
206
+ stack.pop
207
+ contexts.delete(self) if stack.empty?
208
+ end
209
+ end
210
+ end
211
+
212
+ def available?(key) = current_lease(key)&.available? || false
213
+ def checked_out?(key) = current_lease(key)&.checked_out? || false
214
+ def owned?(key) = current_lease(key)&.owned? || false
215
+ def key?(key) = !current_lease(key).nil?
216
+ def size = entries_snapshot.size
217
+ def keys = entries_snapshot.map(&:first)
218
+ def compare_keys_by_identity? = @registry.compare_keys_by_identity?
219
+ def compare_values_by_identity? = true
220
+ def getkey(key) = current_lease(key) && @registry.getkey(key)
221
+
222
+ def each
223
+ return enum_for(__method__) { size } unless block_given?
224
+
225
+ entries_snapshot.each do |key, lease|
226
+ next unless current_binding?(key, lease)
227
+
228
+ if lease.owned?
229
+ yield key, owned_resource(lease)
230
+ else
231
+ entered = false
232
+ begin
233
+ lease.checkout do |resource|
234
+ entered = true
235
+ yield key, resource
236
+ end
237
+ rescue RetiredLeaseError
238
+ raise if entered
239
+
240
+ prune_binding(key, lease)
241
+ end
242
+ end
243
+ end
244
+ self
245
+ end
246
+
247
+ def each_key
248
+ return enum_for(__method__) { size } unless block_given?
249
+
250
+ keys.each { yield it }
251
+ self
252
+ end
253
+
254
+ def each_value
255
+ return enum_for(__method__) { size } unless block_given?
256
+
257
+ each { |_key, value| yield value }
258
+ self
259
+ end
260
+
261
+ def handles = entries_snapshot
262
+
263
+ private
264
+
265
+ def new_lease(resource) = @lease_class.new { resource }
266
+
267
+ def current_lease(key)
268
+ @registry_lock.synchronize do
269
+ lease = @registry[key]
270
+ if lease&.retired?
271
+ @registry.delete(key) if @registry[key].equal?(lease)
272
+ lease = nil
273
+ end
274
+ lease
275
+ end
276
+ end
277
+
278
+ def fetch_lease(key, receiver:, missing_key: key)
279
+ current_lease(key) || raise_missing_key(missing_key, receiver)
280
+ end
281
+
282
+ def raise_missing_key(key, receiver)
283
+ raise KeyError.new("key not found: #{key.inspect}", receiver:, key:)
284
+ end
285
+
286
+ def replace(key, lease, resource)
287
+ if lease.owned?
288
+ replace_owned_resource(lease, resource)
289
+ return resource
290
+ end
291
+
292
+ original = nil
293
+ completed = false
294
+ begin
295
+ if (context = auto_context)
296
+ original = acquire_for_context(lease, context)
297
+ replace_owned_resource(lease, resource)
298
+ else
299
+ lease.__send__(:checkout_with_handoff) { |value| original = value }
300
+ lease.checkin(resource)
301
+ end
302
+ completed = true
303
+ ensure
304
+ if !completed && original && lease.owned? && !lease.retired?
305
+ if scope_managed?(lease)
306
+ lease.__send__(:checkin_scope, owned_resource(lease))
307
+ else
308
+ lease.checkin(original)
309
+ end
310
+ end
311
+ end
312
+ resource
313
+ rescue RetiredLeaseError
314
+ prune_binding(key, lease)
315
+ raise
316
+ end
317
+
318
+ def delete_entry(key, lease)
319
+ return unless current_binding?(key, lease)
320
+
321
+ acquired = false
322
+ resource = nil
323
+ begin
324
+ if lease.owned?
325
+ resource = owned_resource(lease)
326
+ else
327
+ lease.__send__(:checkout_with_handoff) do |value|
328
+ resource = value
329
+ acquired = true
330
+ end
331
+ end
332
+
333
+ removed = Thread.handle_interrupt(INTERRUPT_MASK) do
334
+ @registry_lock.synchronize do
335
+ next false unless @registry[key].equal?(lease)
336
+
337
+ @registry.delete(key)
338
+ remove_auto_resource(lease)
339
+ lease.retire
340
+ true
341
+ end
342
+ end
343
+ return resource if removed
344
+ ensure
345
+ lease.checkin(resource) if acquired && lease.owned? && !lease.retired?
346
+ end
347
+ nil
348
+ end
349
+
350
+ def entries_snapshot
351
+ @registry_lock.synchronize do
352
+ entries = @registry.each_pair.to_a
353
+ entries.reject! do |key, lease|
354
+ next false unless lease.retired?
355
+
356
+ @registry.delete(key) if @registry[key].equal?(lease)
357
+ true
358
+ end
359
+ entries
360
+ end
361
+ end
362
+
363
+ def current_binding?(key, lease)
364
+ @registry_lock.synchronize { @registry[key].equal?(lease) && !lease.retired? }
365
+ end
366
+
367
+ def prune_binding(key, lease)
368
+ return unless lease
369
+
370
+ @registry_lock.synchronize { @registry.delete(key) if @registry[key].equal?(lease) && lease.retired? }
371
+ end
372
+
373
+ def owned_resource(lease) = lease.__send__(:owned_resource)
374
+
375
+ def replace_owned_resource(lease, resource)
376
+ lease.__send__(:replace_owned_resource, resource)
377
+ end
378
+
379
+ def auto_contexts
380
+ Storage.fiber.store_if_absent(AUTO_LEASE_CONTEXTS, mode: :strong) { {}.compare_by_identity }
381
+ end
382
+
383
+ def auto_context
384
+ auto_contexts[self]&.last
385
+ end
386
+
387
+ def acquire_for_context(lease, context, timeout: nil, try: false)
388
+ method = try ? :try_checkout_with_handoff : :checkout_with_handoff
389
+ options = try ? {} : { timeout: }
390
+ already_registered = context.key?(lease)
391
+ lease.__send__(method, **options) do
392
+ lease.__send__(:mark_scope_managed)
393
+ register_context_resource(context, lease)
394
+ end
395
+ rescue Exception # rubocop:disable Lint/RescueException
396
+ context.delete(lease) if !already_registered && context.key?(lease)
397
+ raise
398
+ end
399
+
400
+ def register_context_resource(context, lease)
401
+ context[lease] = true
402
+ end
403
+
404
+ def remove_auto_resource(lease)
405
+ auto_contexts[self]&.each { it.delete(lease) }
406
+ end
407
+
408
+ def cleanup_context(context)
409
+ Thread.handle_interrupt(INTERRUPT_MASK) do
410
+ failure = nil
411
+ context.each_key.to_a.reverse_each do |lease|
412
+ next if lease.retired? || !lease.owned? || !scope_managed?(lease)
413
+
414
+ begin
415
+ lease.__send__(:checkin_scope, owned_resource(lease))
416
+ rescue Exception => e # rubocop:disable Lint/RescueException
417
+ failure ||= e
418
+ end
419
+ end
420
+ raise failure if failure
421
+ end
422
+ end
423
+
424
+ def validate_resource!(resource)
425
+ return unless nil.equal?(resource) || true.equal?(resource) || false.equal?(resource)
426
+
427
+ raise ArgumentError, "lease resource cannot be nil or boolean"
428
+ end
429
+
430
+ def validate_key!(key)
431
+ key = String.instance_method(:-@).bind_call(key) if String === key && !key.frozen?
432
+ return key if Ractor.shareable?(key)
433
+
434
+ raise Ractor::IsolationError, "key must be Ractor-shareable"
435
+ end
436
+
437
+ def explicitly_owned?(lease) = lease.__send__(:explicitly_owned?)
438
+ def scope_managed?(lease) = lease.__send__(:scope_managed?)
439
+ end
440
+ end
441
+ end
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ # @!visibility private
7
+ module Internal # :nodoc: all
8
+ # Coordinates capacity, ownership, waiting, and cleanup for a resource pool.
9
+ class LeasePoolState
10
+ OWNERSHIP = Object.new.freeze
11
+ private_constant :OWNERSHIP
12
+
13
+ attr_reader :max_size
14
+
15
+ def initialize(max_size)
16
+ @max_size = max_size
17
+ @slots = ::Farce::Counter.new
18
+ @managed = Counter.new
19
+ @creating = Counter.new
20
+ @checked_out = Counter.new
21
+ @available = Queue.new(capacity: max_size)
22
+ @signal = Signal.new
23
+ initialize_storage
24
+ finalize_initialization
25
+ end
26
+
27
+ def size = @managed.value
28
+ def available_count = @available.size
29
+ def checked_out_count = @checked_out.value
30
+ def creating_count = @creating.value
31
+
32
+ def checkout(factory, timeout: nil, &block)
33
+ return checkout_block(factory, timeout, block) if block
34
+
35
+ checkout_explicit(factory, timeout:, wait: true)
36
+ end
37
+
38
+ def try_checkout(factory, &block)
39
+ return checkout_block(factory, nil, block, wait: false) if block
40
+
41
+ checkout_explicit(factory, wait: false)
42
+ end
43
+
44
+ def checkin(resource)
45
+ tokens = explicit_tokens(create: false)
46
+ raise OwnershipError, "the current Fiber does not own an explicit pool checkout" unless tokens&.any?
47
+ validate_resource!(resource) unless nil.equal?(resource)
48
+
49
+ Thread.handle_interrupt(INTERRUPT_MASK) do
50
+ token = tokens.last
51
+ if nil.equal?(resource)
52
+ @checked_out.decrement
53
+ @managed.decrement
54
+ @slots.decrement
55
+ else
56
+ return_resource(token, resource)
57
+ @available.push(token)
58
+ @checked_out.decrement
59
+ end
60
+ tokens.pop
61
+ clear_explicit_tokens if tokens.empty?
62
+ @signal.broadcast
63
+ end
64
+ self
65
+ end
66
+
67
+ private
68
+
69
+ def checkout_explicit(factory, wait:, timeout: nil)
70
+ acquisition = nil
71
+ owned = false
72
+ begin
73
+ Thread.handle_interrupt(INTERRUPT_MASK) do
74
+ acquisition = acquire(factory, timeout:, wait:)
75
+ return unless acquisition
76
+
77
+ explicit_tokens << acquisition.first
78
+ owned = true
79
+ end
80
+ acquisition.last
81
+ rescue Exception # rubocop:disable Lint/RescueException
82
+ rollback_explicit(acquisition) if owned
83
+ raise
84
+ end
85
+ end
86
+
87
+ def checkout_block(factory, timeout, block, wait: true)
88
+ acquisition = nil
89
+ Thread.handle_interrupt(INTERRUPT_MASK) do
90
+ acquisition = acquire(factory, timeout:, wait:)
91
+ return unless acquisition
92
+
93
+ begin
94
+ Thread.handle_interrupt(Exception => :immediate) { return block.call(acquisition.last) }
95
+ ensure
96
+ checkin_block(acquisition)
97
+ end
98
+ end
99
+ end
100
+
101
+ def acquire(factory, timeout:, wait:)
102
+ deadline = timeout_deadline(timeout)
103
+
104
+ loop do
105
+ observed = @signal.generation
106
+ token = @available.try_pop
107
+ return take_available(token) if token
108
+ return create_resource(factory) if reserve_creation
109
+ return unless wait
110
+
111
+ remaining = deadline - Clock.now if deadline
112
+ raise TimeoutError, "lease pool checkout timed out" if remaining && !remaining.positive?
113
+ interval = LeaseWaiting.wait_interval(remaining)
114
+ changed = Thread.handle_interrupt(Exception => :immediate) do
115
+ @signal.wait(observed, timeout: interval)
116
+ end
117
+ next if changed || interval != remaining
118
+
119
+ raise TimeoutError, "lease pool checkout timed out"
120
+ end
121
+ end
122
+
123
+ def take_available(token)
124
+ resource = take_resource(token)
125
+ @checked_out.increment
126
+ [token, resource]
127
+ rescue Exception # rubocop:disable Lint/RescueException
128
+ @available.push(token)
129
+ @signal.broadcast
130
+ raise
131
+ end
132
+
133
+ def reserve_creation # rubocop:disable Naming/PredicateMethod
134
+ return false unless @slots.increment_if_below(max_size)
135
+
136
+ @creating.increment
137
+ true
138
+ end
139
+
140
+ def create_resource(factory)
141
+ committed = false
142
+ stored = false
143
+ token = nil
144
+ begin
145
+ resource = Thread.handle_interrupt(Exception => :immediate) { factory.call }
146
+ validate_resource!(resource)
147
+ token = next_token
148
+ store_resource(token, resource)
149
+ stored = true
150
+ resource = take_resource(token)
151
+ stored = false
152
+ @managed.increment
153
+ @creating.decrement
154
+ @checked_out.increment
155
+ committed = true
156
+ [token, resource]
157
+ ensure
158
+ unless committed
159
+ discard_resource(token) if stored
160
+ @creating.decrement
161
+ @slots.decrement
162
+ @signal.broadcast
163
+ end
164
+ end
165
+ end
166
+
167
+ def checkin_block(acquisition)
168
+ token, resource = acquisition
169
+ return_resource(token, resource)
170
+ @available.push(token)
171
+ @checked_out.decrement
172
+ @signal.broadcast
173
+ end
174
+
175
+ def rollback_explicit(acquisition)
176
+ Thread.handle_interrupt(INTERRUPT_MASK) do
177
+ token, resource = acquisition
178
+ return_resource(token, resource)
179
+ @available.push(token)
180
+ @checked_out.decrement
181
+ tokens = explicit_tokens
182
+ tokens.pop
183
+ clear_explicit_tokens if tokens.empty?
184
+ @signal.broadcast
185
+ end
186
+ end
187
+
188
+ def explicit_tokens(create: true)
189
+ ownership = Storage.fiber[OWNERSHIP, :strong]
190
+ if create
191
+ ownership ||= Storage.fiber.store_if_absent(OWNERSHIP, mode: :strong) { {}.compare_by_identity }
192
+ ownership[self] ||= []
193
+ else
194
+ ownership&.[](self)
195
+ end
196
+ end
197
+
198
+ def clear_explicit_tokens
199
+ Storage.fiber[OWNERSHIP, :strong]&.delete(self)
200
+ end
201
+
202
+ def timeout_deadline(timeout)
203
+ return if timeout.nil?
204
+
205
+ timeout = Float(timeout)
206
+ unless timeout.finite? && !timeout.negative?
207
+ raise ArgumentError, "timeout must be a finite, non-negative number or nil"
208
+ end
209
+ Clock.now + timeout
210
+ end
211
+
212
+ def next_token = Object.new.freeze
213
+
214
+ def validate_resource!(resource)
215
+ return unless nil.equal?(resource) || true.equal?(resource) || false.equal?(resource)
216
+
217
+ raise ArgumentError, "lease pool resource cannot be nil or boolean"
218
+ end
219
+
220
+ def initialize_storage = nil
221
+ def finalize_initialization = nil
222
+ def store_resource(*) = raise(NoMethodError, "abstract lease pool storage")
223
+ def take_resource(*) = raise(NoMethodError, "abstract lease pool storage")
224
+ def return_resource(*) = raise(NoMethodError, "abstract lease pool storage")
225
+ def discard_resource(*) = raise(NoMethodError, "abstract lease pool storage")
226
+ end
227
+ end
228
+ end