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,117 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # @abstract Shared priority ordering and blocking behavior.
8
+ class PriorityQueue < Queue
9
+ include Internal::BlockingPriorityQueue
10
+
11
+ # @return [BasicObject] the priority used when none is passed to push
12
+ attr_reader :default_priority
13
+
14
+ # @return [:ascending, :descending] the priority order
15
+ attr_reader :order
16
+
17
+ # @param capacity [Integer, nil] the maximum number of values, or nil for
18
+ # an unbounded queue
19
+ # @param default_priority [BasicObject] the priority used when push or
20
+ # try_push is called without an explicit priority
21
+ # @param order [:ascending, :descending] the priority order
22
+ def initialize(capacity: nil, default_priority: 0, order: :ascending, track_age: false)
23
+ @order = normalize_order(order)
24
+ @default_priority = default_priority
25
+ super(capacity:, reverse_order: @order == :descending, track_age:)
26
+ end
27
+
28
+ # Return the next value without removing it.
29
+ # @yield called when the queue is empty
30
+ # @return [BasicObject, nil] the next value or the fallback result
31
+ def peek(&) = internal_reverse_order? ? internal_queue.peek_last(&) : internal_queue.peek(&)
32
+
33
+ # Remove the oldest value at the lowest or highest priority, depending on {#order}, waiting when empty.
34
+ def pop(non_block = false, timeout: nil) # rubocop:disable Style/OptionalBooleanParameter
35
+ return try_pop { raise ThreadError, "queue empty" } if non_block
36
+ deadline = timeout_at(timeout) unless timeout.nil?
37
+
38
+ while true
39
+ empty = false
40
+ result = if internal_reverse_order?
41
+ internal_queue.pop_last { empty = true }
42
+ else
43
+ internal_queue.pop { empty = true }
44
+ end
45
+
46
+ return result unless empty
47
+ remaining = remaining_timeout(deadline)
48
+ return block_given? ? yield : nil unless wait_pop(timeout: remaining)
49
+ end
50
+ end
51
+
52
+ # Add a value, waiting for capacity when the queue is bounded and full.
53
+ # @param value [BasicObject] the value to add
54
+ # @param non_block [Boolean] whether to raise an exception when the queue is at capacity
55
+ # @param priority [BasicObject] the value used to order the entry
56
+ # @param timeout [Numeric, nil] maximum number of seconds to wait
57
+ # @raise [ThreadError] when the queue is at capacity and non_block is true
58
+ # @return [Boolean] whether the value was added
59
+ def push(value, non_block = false, priority: default_priority, timeout: nil) # rubocop:disable Style/OptionalBooleanParameter
60
+ push_to_storage(priority, non_block, value, timeout:)
61
+ end
62
+
63
+ # Try to remove the oldest value at the lowest priority without waiting.
64
+ # @yield called when the queue is empty
65
+ # @return [BasicObject, nil] the next value or the fallback result
66
+ def try_pop(&) = internal_reverse_order? ? internal_queue.pop_last(&) : internal_queue.pop(&)
67
+
68
+ # Try to add a value without waiting.
69
+ # @param value [BasicObject] the value to add
70
+ # @param priority [BasicObject] the value used to order the entry
71
+ # @yield called when the queue is at capacity
72
+ # @return [Boolean, BasicObject] true, or the fallback result when full
73
+ def try_push(value, priority: default_priority)
74
+ return true if internal_queue.push(priority, value)
75
+
76
+ block_given? ? yield : false
77
+ end
78
+
79
+ # Return the next priority without removing it.
80
+ # @yield called when the queue is empty
81
+ # @return [BasicObject, nil] the priority or the fallback result
82
+ def first_priority(&)
83
+ internal_reverse_order? ? internal_queue.peek_last_priority(&) : internal_queue.peek_priority(&)
84
+ end
85
+
86
+ # Return the last priority without removing it.
87
+ # @yield called when the queue is empty
88
+ # @return [BasicObject, nil] the priority or the fallback result
89
+ def last_priority(&)
90
+ internal_reverse_order? ? internal_queue.peek_priority(&) : internal_queue.peek_last_priority(&)
91
+ end
92
+
93
+ # Delete the oldest matching value at the exact priority.
94
+ # @param value [BasicObject] the value to delete
95
+ # @param priority [BasicObject] the exact priority to search
96
+ # @param compare_by_identity [Boolean] compare values by identity instead of equality
97
+ # @return [Boolean] whether a value was deleted
98
+ def delete(value, priority:, compare_by_identity: false)
99
+ delete_from_storage(priority, value, compare_by_identity:)
100
+ end
101
+
102
+ # Wait until a value is available without removing it.
103
+ def wait_pop(timeout: nil) = wait(timeout) { size.positive? }
104
+
105
+ private
106
+
107
+ def internal_reverse_order? = @reverse_order
108
+
109
+ def normalize_order(order)
110
+ return :ascending if :ascending.equal?(order)
111
+ return :descending if :descending.equal?(order)
112
+
113
+ raise ArgumentError, "order must be :ascending or :descending"
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,269 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # @abstract A shared super class for all queues defined by Farce.
8
+ #
9
+ # A queue is a collection of items that can be added to and removed from in a thread-safe manner.
10
+ # The order is typically FIFO (first-in, first-out), but other orderings may be applied on top.
11
+ #
12
+ # Queues have a blocking and non-blocking interface.
13
+ #
14
+ # @!attribute [r] capacity
15
+ # @abstract
16
+ # @return [Integer, nil] The maximum number of items the queue can hold.
17
+ #
18
+ # @!attribute [r] num_waiting
19
+ # @abstract
20
+ # The number of threads/fibers currently waiting on the queue. This is a momentary snapshot and may be an
21
+ # approximation. The number may also include threads waiting for a push to succeed, as well as threads waiting
22
+ # without modifying the queue.
23
+ # @return [Integer] Number of threads/fibers waiting on the queue.
24
+ #
25
+ # @!attribute [r] mode
26
+ # @return [Symbol] The default mode used to transfer values between Ractors.
27
+ #
28
+ # @!attribute [r] size
29
+ # @abstract
30
+ # @return [Integer] The current number of items in the queue.
31
+ #
32
+ # @!method initialize(capacity: 1024, track_age: false)
33
+ # @abstract Subclasses may add additional parameters to this method.
34
+ # @param capacity [Integer, nil]
35
+ # The maximum number of items the queue can hold.
36
+ # If `nil`, the queue is unbounded.
37
+ #
38
+ # The default may vary for subclasses.
39
+ # Most notably, priority and timer queues default to `nil`.
40
+ # @param track_age [Boolean] Whether to track enqueue age and queue generations.
41
+ #
42
+ # @!method clear
43
+ # @abstract
44
+ # Removes all items from the queue.
45
+ # @return [self]
46
+ #
47
+ # @!method close
48
+ # @abstract
49
+ # Closes the queue, preventing any further items from being added.
50
+ # @return [self]
51
+ #
52
+ # @!method closed?
53
+ # @abstract
54
+ # Checks whether the queue is closed.
55
+ # @return [Boolean] `true` if the queue is closed, `false` otherwise.
56
+ #
57
+ # @!method seal
58
+ # Stops new pushes while allowing queued items to be removed.
59
+ # The queue closes automatically when it becomes empty.
60
+ # @return [self]
61
+ #
62
+ # @!method sealed?
63
+ # @return [Boolean] Whether the queue rejects new pushes.
64
+ #
65
+ # @!method empty?
66
+ # @abstract
67
+ # Checks whether the queue is empty.
68
+ # @return [Boolean] `true` if the queue is empty, `false` otherwise.
69
+ #
70
+ # @!method pop(non_block = false, timeout: nil)
71
+ # @abstract Subclasses may add additional parameters to this method.
72
+ # Takes an item from the queue, blocking until one is available or the timeout expires.
73
+ # @yield Block called if the timeout expires before an item is available.
74
+ # @param non_block [Boolean] whether to raise an exception when the queue is empty
75
+ # @param timeout [Numeric, nil]
76
+ # The maximum time to wait for an item to be available.
77
+ # If `nil`, the method will wait indefinitely.
78
+ # If `0`, the method will not wait at all.
79
+ # @raise [Farce::ClosedQueueError] when the queue is closed
80
+ # @raise [ThreadError] when the queue is empty and non_block is true
81
+ # @return [BasicObject, nil]
82
+ # The item taken from the queue, or the return value of the block or `nil` if the timeout expired.
83
+ #
84
+ # @!method push(value, non_block = false, timeout: nil)
85
+ # @abstract
86
+ # Subclasses may add additional parameters to this method.
87
+ # They may also restrict what types of values can be pushed onto the queue.
88
+ # In particular, some queues may only accept Ractor-shareable values.
89
+ # Pushes an item onto the queue. May block if the queue is at capacity.
90
+ # If the queue is unbounded, this method will never block.
91
+ # If a timeout is specified, the method will block until the item is added or the timeout expires.
92
+ # @param value [BasicObject] The item to add to the queue.
93
+ # @param non_block [Boolean] whether to raise an exception when the queue is full
94
+ # @param timeout [Numeric, nil]
95
+ # The maximum time to wait for the item to be added.
96
+ # If `nil`, the method will wait indefinitely.
97
+ # If `0`, the method will not wait at all.
98
+ # @raise [Farce::ClosedQueueError] when the queue is closed
99
+ # @raise [Farce::SealedQueueError] when the queue is sealed but not yet closed
100
+ # @raise [ThreadError] when the queue is full and non_block is true
101
+ # @return [Boolean] `true` if the item was added to the queue
102
+ #
103
+ # @!method try_pop
104
+ # @abstract Subclasses may add additional parameters to this method.
105
+ # Tries to take an item from the queue without blocking.
106
+ # If no item is available, the method will call the block if given, or return `nil` if no block is given.
107
+ # @yield Block called if no item is available.
108
+ # @return [BasicObject, nil]
109
+ # The item taken from the queue, or the return value of the block or `nil` if no item was available.
110
+ #
111
+ # @!method try_push(value)
112
+ # @abstract Subclasses may add additional parameters to this method.
113
+ # Tries to push an item onto the queue without blocking.
114
+ # If the queue is at capacity, the method will call the block if given, or return `false` if no block is given.
115
+ # @param value [BasicObject] The item to add to the queue.
116
+ # @yield Block called if the queue is at capacity.
117
+ # @raise [Farce::ClosedQueueError] when the queue is closed
118
+ # @raise [Farce::SealedQueueError] when the queue is sealed but not yet closed
119
+ # @return [Boolean]
120
+ # `true` if the item was added to the queue, `false` if the queue was at capacity and no block was given.
121
+ #
122
+ # @!method wait_pop(timeout: nil)
123
+ # @abstract Subclasses may add additional parameters to this method.
124
+ # Waits until an item is available to pop from the queue, or the timeout expires.
125
+ # Does not remove the item from the queue.
126
+ # Note that this method does not guarantee a subsequent call to {#pop} or {#try_pop} will succeed,
127
+ # as another thread may remove the item first.
128
+ # @param timeout [Numeric, nil]
129
+ # The maximum time to wait for an item to be available.
130
+ # If `nil`, the method will wait indefinitely.
131
+ # If `0`, the method will not wait at all.
132
+ # @raise [Farce::ClosedQueueError] when the queue is closed
133
+ # @return [Boolean] `true` if an item is available, `false` if the timeout expired.
134
+ #
135
+ # @!method wait_push(timeout: nil)
136
+ # @abstract Subclasses may add additional parameters to this method.
137
+ # Waits until there is space to push an item onto the queue, or the timeout expires.
138
+ # Note that this method does not guarantee a subsequent call to {#push} or {#try_push} will succeed,
139
+ # as another thread may add an item first.
140
+ # @param timeout [Numeric, nil]
141
+ # The maximum time to wait for space to be available.
142
+ # If `nil`, the method will wait indefinitely.
143
+ # If `0`, the method will not wait at all.
144
+ # @raise [Farce::ClosedQueueError] when the queue is closed
145
+ # @raise [Farce::SealedQueueError] when the queue is sealed but not yet closed
146
+ # @return [Boolean] `true` if space is available, `false` if the timeout expired.
147
+ class Queue
148
+ include Internal::MarshalSupport::Reject
149
+ include Internal::Inspect
150
+
151
+ # The default mode used to transfer values between Ractors.
152
+ # @return [Symbol]
153
+ def mode = :raise
154
+
155
+ # Alias for {#pop} to match the interface of Ruby's Queue class.
156
+ # @return (see #pop)
157
+ def deq(...) = pop(...)
158
+ alias shift deq
159
+
160
+ # Alias for {#push} to match the interface of Ruby's Queue class.
161
+ # @return (see #push)
162
+ def enq(...) = push(...)
163
+ alias << enq
164
+
165
+ # Alias for {#size} to match the interface of Ruby's Queue class.
166
+ # @return (see #size)
167
+ def length = size
168
+
169
+ # The maximum number of items the queue can hold.
170
+ # @return [Integer, Float] the maximum number of items, or `Float::INFINITY` if the queue is unbounded.
171
+ def max = capacity || Float::INFINITY
172
+
173
+ # Whether the queue is at capacity.
174
+ # @return [Boolean] `true` if the queue is at capacity, `false` otherwise.
175
+ def full? = capacity && size >= capacity
176
+
177
+ def capacity = internal_queue.capacity
178
+
179
+ def clear
180
+ internal_queue.clear
181
+ self
182
+ end
183
+
184
+ def close
185
+ internal_queue.close
186
+ self
187
+ end
188
+
189
+ # Stop new pushes and close after the final queued item is removed.
190
+ # @return [self]
191
+ def seal
192
+ internal_queue.seal
193
+ self
194
+ end
195
+
196
+ def closed? = internal_queue.closed?
197
+ def sealed? = internal_queue.sealed?
198
+
199
+ # @return [Boolean] Whether enqueue-age tracking is enabled.
200
+ def age_tracking? = internal_queue.age_tracking?
201
+
202
+ # @return [Integer, nil] The mutation generation, or `nil` when tracking is disabled.
203
+ def generation = internal_queue.generation
204
+
205
+ # The timestamp is monotonic. Its origin is runtime-specific.
206
+ # @return [Float, nil] The monotonic enqueue time of the oldest item.
207
+ def oldest_enqueued_at = internal_queue.oldest_enqueued_at
208
+
209
+ # @return [Float, nil] Seconds since the oldest item was enqueued.
210
+ def oldest_age = internal_queue.oldest_age
211
+
212
+ def empty? = size.zero?
213
+
214
+ def num_waiting = internal_queue.num_waiting
215
+
216
+ def pop(non_block = false, timeout: nil, &) # rubocop:disable Style/OptionalBooleanParameter
217
+ return internal_queue.try_pop { raise ThreadError, "queue empty" } if non_block
218
+ timeout.nil? ? internal_queue.pop(&) : internal_queue.pop(timeout:, &)
219
+ end
220
+
221
+ def push(value, non_block = false, timeout: nil) # rubocop:disable Style/OptionalBooleanParameter
222
+ if non_block
223
+ return true if internal_queue.try_push(value)
224
+ raise ThreadError, "queue full"
225
+ end
226
+ timeout.nil? ? internal_queue.push(value) : internal_queue.push(value, timeout:)
227
+ end
228
+
229
+ def try_pop(&) = internal_queue.try_pop(&)
230
+
231
+ def try_push(value)
232
+ return true if internal_queue.try_push(value)
233
+ block_given? ? yield : false
234
+ end
235
+
236
+ def size = internal_queue.size
237
+
238
+ def wait_pop(timeout: nil) = internal_queue.wait_pop(timeout:)
239
+
240
+ def wait_push(timeout: nil) = internal_queue.wait_push(timeout:)
241
+
242
+ # @api private
243
+ def inspect_with(inspector)
244
+ super do
245
+ if closed?
246
+ inspector.breakable " "
247
+ inspector.text "closed"
248
+ else
249
+ inspector.attributes(inspect_info)
250
+ end
251
+ end
252
+ end
253
+
254
+ private
255
+
256
+ def initialize_copy(_other)
257
+ raise TypeError, "queues cannot be copied"
258
+ end
259
+
260
+ def inspect_info
261
+ info = { size:, capacity: }.compact
262
+ info[:num_waiting] = num_waiting if num_waiting.positive?
263
+ info
264
+ end
265
+
266
+ private def internal_queue = @queue
267
+ end
268
+ end
269
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+ # shareable_constant_value: literal
3
+ # warn_indent: true
4
+
5
+ module Farce
6
+ module Abstract
7
+ # @abstract A shared super class for all scheduler implementations.
8
+ #
9
+ # @!method schedule(*args, mode: :copy, auto_local: true)
10
+ # @abstract This method must be implemented by concrete scheduler subclasses.
11
+ #
12
+ # Schedules a block for execution.
13
+ # What actually happens depends on the concrete scheduler implementation.
14
+ # Some schedulers may ignore the `auto_local` option. Some might treat every mode as `:local`.
15
+ #
16
+ # The scheduler may choose to block until the task has been executed, but most will add it to a queue of pending
17
+ # tasks, only blocking when that queue's capacity has been reached.
18
+ #
19
+ # @!macro modes
20
+ #
21
+ # @param args [Array]
22
+ # Arguments to pass to the scheduled block.
23
+ # May be handled according to `mode`.
24
+ #
25
+ # @param mode [Symbol]
26
+ # The mode in which to schedule the task. Defaults to `:copy`.
27
+ # May be ignored by some schedulers.
28
+ #
29
+ # @param auto_local [Boolean]
30
+ # Whether to automatically use a local mode when possible. Defaults to `true`.
31
+ # May be ignored by some schedulers.
32
+ #
33
+ # @yield [*args] The block to be executed by the scheduler.
34
+ # @yieldparam args [Array] The arguments passed to the block.
35
+ # @yieldreceiver [BasicObject, nil]
36
+ # Local mode will not touch the block's binding (self stays the same), but other modes may change it to `nil`.
37
+ #
38
+ # @return [self]
39
+ #
40
+ # @!method close
41
+ # @abstract This method must be implemented by concrete scheduler subclasses.
42
+ # Closes the scheduler, releasing any resources it holds.
43
+ # Once closed, the scheduler cannot be used to schedule new tasks.
44
+ # Will drain any pending tasks before fully closing. If tasks are running indefinitely, it may block.
45
+ # @return [self]
46
+ #
47
+ # @!method closed?
48
+ # @abstract This method must be implemented by concrete scheduler subclasses.
49
+ # @return [Boolean] Whether the scheduler is closed.
50
+ #
51
+ # @!method state
52
+ # @abstract This method must be implemented by concrete scheduler subclasses.
53
+ # @return [Symbol]
54
+ # The current state of the scheduler.
55
+ #
56
+ # Common states include:
57
+ # * `:initialized`, `:launching` and `:setup` for the setup phase.
58
+ # * `:running` for the execution phase.
59
+ # * `:closing`, `:closed`, and `:error` for the termination phase.
60
+ #
61
+ # Not all schedulers will implement every state.
62
+ #
63
+ # @!method ractor_safe?
64
+ # @abstract Schedulers should include {Shareable} or {Unshareable}, which implement this method.
65
+ # @return [Boolean] Whether the scheduler is safe to use across Ractors.
66
+ class Scheduler
67
+ include Internal::Noncopyable
68
+
69
+ # An error that occurred during the scheduler's operation, if any.
70
+ # This is primarily for scheduling errors, not execution errors.
71
+ # You can check this if the {#state} is `:error`.
72
+ def error = nil
73
+
74
+ # @param wait [Boolean] Whether to wait for the owner to be non-nil before checking if the scheduler is local.
75
+ # @return [Boolean] Whether the scheduler is local for the current Ractor.
76
+ def local?(wait: true) = false # rubocop:disable Lint/UnusedMethodArgument
77
+
78
+ # Like {#schedule}, with two differences:
79
+ # 1. If {#local?} returns true, and it would run in local mode (either due to `auto_local` or explicitly set
80
+ # `mode: :local`), it executes the block directly without enqueuing it.
81
+ # 2. It blocks until the block has been executed, either immediately in local mode or after being scheduled.
82
+ #
83
+ # @param (see #schedule)
84
+ # @return [self]
85
+ def execute(*, mode: :copy, auto_local: true, &callback)
86
+ raise LocalJumpError, "Cannot yield without a block" unless block_given?
87
+ raise SchedulerClosedError, "cannot execute task on a closed scheduler" if closed?
88
+
89
+ if (auto_local || mode == :local) && local?
90
+ raise SchedulerClosedError, "cannot execute task on a closed scheduler" if closed?
91
+ yield(*)
92
+ return self
93
+ end
94
+
95
+ ran = Farce::Flag.new(false)
96
+ signal = Signal.new
97
+ callback = Ractor.shareable_proc(&callback) unless Ractor.shareable?(callback)
98
+
99
+ schedule(callback, ran, signal, *, mode:, auto_local:) do |callback, ran, signal, *args|
100
+ callback.call(*args)
101
+ ensure
102
+ ran.set
103
+ signal.broadcast
104
+ end
105
+
106
+ signal.wait_until { ran.value }
107
+ self
108
+ end
109
+ end
110
+ end
111
+ end