farce 0.0.1.alpha2-x86_64-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,103 @@
1
+ #ifndef FARCE_FIBER_REACTOR_H
2
+ #define FARCE_FIBER_REACTOR_H
3
+ #include <ruby.h>
4
+ #include <ruby/io.h>
5
+ #include <ruby/io/buffer.h>
6
+ #include <ruby/thread.h>
7
+ #include <ruby/st.h>
8
+ #include <pthread.h>
9
+ #include <stdint.h>
10
+ #include <time.h>
11
+ #include <sys/stat.h>
12
+ #if defined(FARCE_HAVE_LIBURING)
13
+ #include <liburing.h>
14
+ #define FARCE_URING 1
15
+ #endif
16
+ #ifdef HAVE_SYS_EVENT_H
17
+ #include <sys/event.h>
18
+ #endif
19
+ #define FS_READ 1
20
+ #define FS_PRI 2
21
+ #define FS_WRITE 4
22
+ #define FS_EVENTS 1024
23
+ #define FS_RECEIVE (UINT64_C(1) << 63)
24
+ #define FS_SLOT_BITS 20
25
+ #define FS_SLOT_MASK ((1U << FS_SLOT_BITS) - 1)
26
+
27
+ typedef struct fs_admission fs_admission;
28
+ struct fs_admission { VALUE parent, child; fs_admission *previous; };
29
+ typedef struct fs_wait fs_wait;
30
+ typedef struct { fs_wait *wait; uint64_t generation; uint32_t next_free; } fs_slot;
31
+ typedef struct fs_reg fs_reg;
32
+ typedef struct fs_watch fs_watch;
33
+ struct fs_watch {
34
+ fs_wait *wait;
35
+ fs_reg *reg;
36
+ fs_watch *next_reg, *next_wait;
37
+ int events, group;
38
+ long index;
39
+ };
40
+ struct fs_reg {
41
+ int fd, events, poll_events;
42
+ uint64_t generation;
43
+ fs_watch *watches;
44
+ };
45
+ struct fs_wait {
46
+ VALUE token, fiber, value, error, groups, ios;
47
+ uint32_t slot;
48
+ int status, events, selected, queued, native_error, receive_pending;
49
+ fs_wait *ready_next, *ready_prev;
50
+ fs_watch *watches;
51
+ fs_watch first_watch;
52
+ };
53
+ typedef struct { uint64_t generation; int events, error; } fs_event;
54
+ typedef struct {
55
+ VALUE owner, root, active, backend, fallback;
56
+ fs_wait *ready_head, *ready_tail;
57
+ fs_admission *admission;
58
+ int dispatch_left, stopping, closing, policy_pending, allow_poll;
59
+ st_table *fibers, *regs, *generations, *retired_regs;
60
+ fs_slot *slots;
61
+ uint32_t slot_count, slot_capacity, first_free;
62
+ size_t pending;
63
+ uint64_t serial, generation, suspensions;
64
+ unsigned immediate;
65
+ int selected_pending, receive_disabled;
66
+ int driver, descriptor, wake[2], closed;
67
+ pthread_mutex_t wake_mutex;
68
+ #ifdef FARCE_URING
69
+ struct io_uring ring;
70
+ int ring_live;
71
+ #endif
72
+ #ifdef HAVE_SYS_EVENT_H
73
+ struct kevent *changes;
74
+ int change_count, change_capacity;
75
+ #endif
76
+ fs_event events[FS_EVENTS];
77
+ double timeout, close_check_at;
78
+ int event_count, poll_error, polling_regs, ready_batches;
79
+ } fs_state;
80
+ enum { FS_EPOLL = 1, FS_KQUEUE, FS_URING_DRIVER };
81
+ extern const rb_data_type_t fs_type;
82
+ static inline fs_state *fs_get(VALUE self) {
83
+ fs_state *s; TypedData_Get_Struct(self, fs_state, &fs_type, s); return s;
84
+ }
85
+ int fs_driver_init(fs_state *s, int driver);
86
+ int fs_driver_update(fs_state *s, fs_reg *reg, int events);
87
+ int fs_driver_receive(fs_state *s, fs_wait *w, int fd, void *buffer, size_t size);
88
+ void fs_cancel_receive(VALUE self, fs_wait *w);
89
+ void fs_driver_close(fs_state *s);
90
+ void *fs_driver_poll(void *data);
91
+ void fs_check_fiber(VALUE self);
92
+ VALUE fs_checkpoint(VALUE self, VALUE value);
93
+ VALUE fs_arm(VALUE self);
94
+ VALUE fs_arm_checked(VALUE self);
95
+ VALUE fs_suspend(VALUE self, VALUE token);
96
+ VALUE fs_park(VALUE self, VALUE token);
97
+ VALUE fs_retire(VALUE self, VALUE token);
98
+ VALUE fs_resume(VALUE self, VALUE token, VALUE value, VALUE error);
99
+ void fs_watch_io(fs_state *s, fs_wait *wait, int fd, int events, int group, long index);
100
+ fs_wait *fs_lookup(fs_state *s, VALUE token);
101
+ VALUE fs_io_wait(int argc, VALUE *argv, VALUE self);
102
+ void fs_init_io(VALUE klass);
103
+ #endif
@@ -0,0 +1,31 @@
1
+ #ifndef FARCE_SHAREABLE_H
2
+ #define FARCE_SHAREABLE_H
3
+
4
+ #include "ruby.h"
5
+ #include "ruby/ractor.h"
6
+ #include "ruby/version.h"
7
+
8
+ /* CRuby 4.0 declares rb_obj_set_shareable in its public header, but some
9
+ * installations do not export the symbol. The raw fallback is limited to the
10
+ * audited 3.4/4.0 object layout. CRuby 4.1 must use the exported function so
11
+ * global-GC and shared-reference bookkeeping run. */
12
+ static inline VALUE
13
+ farce_ruby_mark_shareable(VALUE object)
14
+ {
15
+ #if defined(FARCE_HAVE_EXPORTED_SHAREABLE_MARKER)
16
+ # if RUBY_API_VERSION_CODE < 40100
17
+ # error "The exported shareable marker is enabled only for CRuby 4.1 or newer"
18
+ # endif
19
+ return RB_OBJ_SET_SHAREABLE(object);
20
+ #elif defined(FARCE_USE_LEGACY_SHAREABLE_FLAG)
21
+ # if RUBY_API_VERSION_CODE < 30400 || RUBY_API_VERSION_CODE >= 40100
22
+ # error "The legacy shareable flag is supported only on CRuby 3.4 and 4.0"
23
+ # endif
24
+ RB_FL_SET_RAW(object, RUBY_FL_SHAREABLE);
25
+ return object;
26
+ #else
27
+ # error "No supported CRuby shareable marker was configured"
28
+ #endif
29
+ }
30
+
31
+ #endif
@@ -0,0 +1,350 @@
1
+ #include "containers.h"
2
+ #include "ruby/io.h"
3
+
4
+ #include <errno.h>
5
+ #include <fcntl.h>
6
+ #include <math.h>
7
+ #include <stdint.h>
8
+ #include <time.h>
9
+ #include <unistd.h>
10
+
11
+ static VALUE cSignal;
12
+
13
+ typedef struct containers_signal_waiter containers_signal_waiter_t;
14
+
15
+ struct containers_signal_waiter {
16
+ int read_fd;
17
+ int write_fd;
18
+ bool notified;
19
+ containers_signal_waiter_t *next;
20
+ };
21
+
22
+ typedef struct {
23
+ pthread_mutex_t lock;
24
+ containers_signal_waiter_t *waiters;
25
+ uint64_t generation;
26
+ bool initialized;
27
+ } containers_signal_t;
28
+
29
+ typedef struct {
30
+ bool finite;
31
+ double deadline;
32
+ } containers_signal_timeout_t;
33
+
34
+ typedef struct {
35
+ containers_signal_t *signal;
36
+ containers_signal_waiter_t waiter;
37
+ containers_signal_timeout_t *timeout;
38
+ } containers_signal_wait_context_t;
39
+
40
+ static double
41
+ containers_signal_monotonic_now(void)
42
+ {
43
+ struct timespec now;
44
+ #ifdef CLOCK_MONOTONIC
45
+ if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
46
+ return (double)now.tv_sec + (double)now.tv_nsec / 1000000000.0;
47
+ }
48
+ #endif
49
+ struct timeval fallback;
50
+ gettimeofday(&fallback, NULL);
51
+ return (double)fallback.tv_sec + (double)fallback.tv_usec / 1000000.0;
52
+ }
53
+
54
+ static containers_signal_timeout_t
55
+ containers_signal_parse_timeout(VALUE value)
56
+ {
57
+ containers_signal_timeout_t timeout = {.finite = false, .deadline = 0};
58
+ if (NIL_P(value)) return timeout;
59
+
60
+ double seconds = NUM2DBL(value);
61
+ if (!isfinite(seconds) || seconds < 0) {
62
+ rb_raise(rb_eArgError, "timeout must be a finite, non-negative number or nil");
63
+ }
64
+ timeout.finite = true;
65
+ timeout.deadline = containers_signal_monotonic_now() + seconds;
66
+ return timeout;
67
+ }
68
+
69
+ static void
70
+ containers_signal_set_fd_flags(int fd)
71
+ {
72
+ #ifdef _WIN32
73
+ (void)fd;
74
+ #else
75
+ int flags = fcntl(fd, F_GETFL, 0);
76
+ if (flags >= 0) (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK);
77
+ flags = fcntl(fd, F_GETFD, 0);
78
+ if (flags >= 0) (void)fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
79
+ #endif
80
+ }
81
+
82
+ /* Called with signal->lock held. Each waiter has a separate descriptor, so a
83
+ * single broadcast makes every scheduled Fiber or native thread runnable. */
84
+ static void
85
+ containers_signal_notify_waiters_locked(containers_signal_t *signal)
86
+ {
87
+ unsigned char byte = 1;
88
+ for (containers_signal_waiter_t *waiter = signal->waiters; waiter; waiter = waiter->next) {
89
+ if (waiter->notified) continue;
90
+ ssize_t result;
91
+ do {
92
+ result = write(waiter->write_fd, &byte, 1);
93
+ } while (result < 0 && errno == EINTR);
94
+ if (result == 1 || (result < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))) {
95
+ waiter->notified = true;
96
+ }
97
+ }
98
+ }
99
+
100
+ static void
101
+ containers_signal_free(void *pointer)
102
+ {
103
+ containers_signal_t *signal = pointer;
104
+ pthread_mutex_destroy(&signal->lock);
105
+ ruby_xfree(signal);
106
+ }
107
+
108
+ static size_t
109
+ containers_signal_memsize(const void *pointer)
110
+ {
111
+ return pointer ? sizeof(containers_signal_t) : 0;
112
+ }
113
+
114
+ static const rb_data_type_t containers_signal_type = {
115
+ .wrap_struct_name = "Ractor::Containers::Signal",
116
+ .function = {
117
+ .dmark = NULL,
118
+ .dfree = containers_signal_free,
119
+ .dsize = containers_signal_memsize,
120
+ .dcompact = NULL,
121
+ },
122
+ .flags = RUBY_TYPED_FROZEN_SHAREABLE,
123
+ };
124
+
125
+ static VALUE
126
+ containers_signal_allocate(VALUE klass)
127
+ {
128
+ containers_signal_t *signal;
129
+ VALUE object = TypedData_Make_Struct(
130
+ klass,
131
+ containers_signal_t,
132
+ &containers_signal_type,
133
+ signal
134
+ );
135
+ pthread_mutex_init(&signal->lock, NULL);
136
+ signal->waiters = NULL;
137
+ signal->generation = 0;
138
+ signal->initialized = false;
139
+ return object;
140
+ }
141
+
142
+ static containers_signal_t *
143
+ containers_signal_get(VALUE self)
144
+ {
145
+ containers_signal_t *signal;
146
+ TypedData_Get_Struct(self, containers_signal_t, &containers_signal_type, signal);
147
+ if (!signal->initialized) rb_raise(rb_eRuntimeError, "uninitialized Signal");
148
+ return signal;
149
+ }
150
+
151
+ static VALUE
152
+ containers_signal_frozen_p(VALUE self)
153
+ {
154
+ (void)self;
155
+ return Qfalse;
156
+ }
157
+
158
+ static VALUE
159
+ containers_signal_freeze(VALUE self)
160
+ {
161
+ containers_raise_unfreezable(self);
162
+ return Qnil;
163
+ }
164
+
165
+ static VALUE
166
+ containers_signal_initialize(VALUE self)
167
+ {
168
+ containers_signal_t *signal;
169
+ TypedData_Get_Struct(self, containers_signal_t, &containers_signal_type, signal);
170
+ if (signal->initialized) rb_raise(rb_eRuntimeError, "Signal is already initialized");
171
+ signal->initialized = true;
172
+ containers_publish_native_reference_free(self);
173
+ return self;
174
+ }
175
+
176
+ VALUE
177
+ containers_signal_new(void)
178
+ {
179
+ VALUE signal = containers_signal_allocate(cSignal);
180
+ return containers_signal_initialize(signal);
181
+ }
182
+
183
+ static bool
184
+ containers_signal_wait_for_descriptor(int fd, containers_signal_timeout_t *timeout)
185
+ {
186
+ VALUE wait_timeout = Qnil;
187
+ if (timeout->finite) {
188
+ double remaining = timeout->deadline - containers_signal_monotonic_now();
189
+ if (remaining <= 0) return false;
190
+ wait_timeout = DBL2NUM(remaining);
191
+ }
192
+
193
+ return containers_wait_for_readable(fd, wait_timeout);
194
+ }
195
+
196
+ static VALUE
197
+ containers_signal_wait_body(VALUE opaque)
198
+ {
199
+ containers_signal_wait_context_t *context = (containers_signal_wait_context_t *)opaque;
200
+ return containers_signal_wait_for_descriptor(context->waiter.read_fd, context->timeout)
201
+ ? Qtrue
202
+ : Qfalse;
203
+ }
204
+
205
+ static VALUE
206
+ containers_signal_wait_cleanup(VALUE opaque)
207
+ {
208
+ containers_signal_wait_context_t *context = (containers_signal_wait_context_t *)opaque;
209
+ containers_signal_waiter_t **link;
210
+
211
+ pthread_mutex_lock(&context->signal->lock);
212
+ for (link = &context->signal->waiters; *link; link = &(*link)->next) {
213
+ if (*link == &context->waiter) {
214
+ *link = context->waiter.next;
215
+ break;
216
+ }
217
+ }
218
+ pthread_mutex_unlock(&context->signal->lock);
219
+ close(context->waiter.read_fd);
220
+ close(context->waiter.write_fd);
221
+ return Qnil;
222
+ }
223
+
224
+ /* Called with signal->lock held and always returns with it released. */
225
+ static bool
226
+ containers_signal_wait_once(
227
+ containers_signal_t *signal,
228
+ containers_signal_timeout_t *timeout
229
+ )
230
+ {
231
+ int descriptors[2];
232
+ if (pipe(descriptors) != 0) {
233
+ pthread_mutex_unlock(&signal->lock);
234
+ rb_sys_fail("pipe");
235
+ }
236
+ containers_signal_set_fd_flags(descriptors[0]);
237
+ containers_signal_set_fd_flags(descriptors[1]);
238
+
239
+ containers_signal_wait_context_t context = {
240
+ .signal = signal,
241
+ .waiter = {
242
+ .read_fd = descriptors[0],
243
+ .write_fd = descriptors[1],
244
+ .notified = false,
245
+ .next = signal->waiters,
246
+ },
247
+ .timeout = timeout,
248
+ };
249
+ signal->waiters = &context.waiter;
250
+ pthread_mutex_unlock(&signal->lock);
251
+ return RTEST(rb_ensure(
252
+ containers_signal_wait_body,
253
+ (VALUE)&context,
254
+ containers_signal_wait_cleanup,
255
+ (VALUE)&context
256
+ ));
257
+ }
258
+
259
+ static VALUE
260
+ containers_signal_timeout_result(void)
261
+ {
262
+ return rb_block_given_p() ? rb_yield_values(0) : Qnil;
263
+ }
264
+
265
+ static VALUE
266
+ containers_signal_generation(VALUE self)
267
+ {
268
+ containers_signal_t *signal = containers_signal_get(self);
269
+ uint64_t generation;
270
+ pthread_mutex_lock(&signal->lock);
271
+ generation = signal->generation;
272
+ pthread_mutex_unlock(&signal->lock);
273
+ return ULL2NUM(generation);
274
+ }
275
+
276
+ static VALUE
277
+ containers_signal_num_waiting(VALUE self)
278
+ {
279
+ containers_signal_t *signal = containers_signal_get(self);
280
+ size_t count = 0;
281
+
282
+ /* Count on demand so wait and broadcast have no additional bookkeeping. */
283
+ pthread_mutex_lock(&signal->lock);
284
+ for (containers_signal_waiter_t *waiter = signal->waiters; waiter; waiter = waiter->next) {
285
+ count++;
286
+ }
287
+ pthread_mutex_unlock(&signal->lock);
288
+ return SIZET2NUM(count);
289
+ }
290
+
291
+ VALUE
292
+ containers_signal_broadcast(VALUE self)
293
+ {
294
+ containers_signal_t *signal = containers_signal_get(self);
295
+ uint64_t generation;
296
+ pthread_mutex_lock(&signal->lock);
297
+ signal->generation++;
298
+ generation = signal->generation;
299
+ containers_signal_notify_waiters_locked(signal);
300
+ pthread_mutex_unlock(&signal->lock);
301
+ return ULL2NUM(generation);
302
+ }
303
+
304
+ static VALUE
305
+ containers_signal_wait(int argc, VALUE *argv, VALUE self)
306
+ {
307
+ VALUE observed_value = Qnil;
308
+ VALUE keywords = Qnil;
309
+ VALUE keyword_values[1] = {Qundef};
310
+ ID keyword_ids[] = {rb_intern("timeout")};
311
+ rb_scan_args(argc, argv, "01:", &observed_value, &keywords);
312
+ if (!NIL_P(keywords)) rb_get_kwargs(keywords, keyword_ids, 0, 1, keyword_values);
313
+
314
+ bool snapshot_at_entry = NIL_P(observed_value);
315
+ uint64_t observed = snapshot_at_entry ? 0 : NUM2ULL(observed_value);
316
+ containers_signal_timeout_t timeout = containers_signal_parse_timeout(
317
+ keyword_values[0] == Qundef ? Qnil : keyword_values[0]
318
+ );
319
+ containers_signal_t *signal = containers_signal_get(self);
320
+
321
+ pthread_mutex_lock(&signal->lock);
322
+ if (snapshot_at_entry) observed = signal->generation;
323
+ for (;;) {
324
+ if (signal->generation != observed) {
325
+ uint64_t generation = signal->generation;
326
+ pthread_mutex_unlock(&signal->lock);
327
+ return ULL2NUM(generation);
328
+ }
329
+ bool awakened = containers_signal_wait_once(signal, &timeout);
330
+ pthread_mutex_lock(&signal->lock);
331
+ if (!awakened && signal->generation == observed) {
332
+ pthread_mutex_unlock(&signal->lock);
333
+ return containers_signal_timeout_result();
334
+ }
335
+ }
336
+ }
337
+
338
+ void
339
+ containers_init_signal(VALUE namespace)
340
+ {
341
+ cSignal = rb_define_class_under(namespace, "Signal", rb_cObject);
342
+ rb_define_alloc_func(cSignal, containers_signal_allocate);
343
+ rb_define_method(cSignal, "initialize", containers_signal_initialize, 0);
344
+ rb_define_method(cSignal, "generation", containers_signal_generation, 0);
345
+ rb_define_method(cSignal, "num_waiting", containers_signal_num_waiting, 0);
346
+ rb_define_method(cSignal, "broadcast", containers_signal_broadcast, 0);
347
+ rb_define_method(cSignal, "wait", containers_signal_wait, -1);
348
+ rb_define_method(cSignal, "freeze", containers_signal_freeze, 0);
349
+ rb_define_method(cSignal, "frozen?", containers_signal_frozen_p, 0);
350
+ }