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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/CODE_OF_CONDUCT.md +26 -0
- data/CONTRIBUTING.md +71 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1525 -0
- data/SECURITY.md +10 -0
- data/docs/benchmarks.md +185 -0
- data/docs/gems/dry-types.md +290 -0
- data/docs/gems/msgpack.md +70 -0
- data/docs/gems/ractor-shim.md +63 -0
- data/docs/modes.md +628 -0
- data/docs/scopes.md +649 -0
- data/docs/variants.md +346 -0
- data/ext/ext_helper.rb +20 -0
- data/ext/farce/README.md +21 -0
- data/ext/farce/atom.c +1023 -0
- data/ext/farce/bounded_map.c +1683 -0
- data/ext/farce/containers.h +77 -0
- data/ext/farce/counter.c +399 -0
- data/ext/farce/darwin.c +100 -0
- data/ext/farce/depend +12 -0
- data/ext/farce/dict.c +1523 -0
- data/ext/farce/dict.h +152 -0
- data/ext/farce/drivers.c +237 -0
- data/ext/farce/exchanger.c +299 -0
- data/ext/farce/extconf.rb +99 -0
- data/ext/farce/farce.c +359 -0
- data/ext/farce/flag.c +288 -0
- data/ext/farce/io.c +338 -0
- data/ext/farce/lock.c +510 -0
- data/ext/farce/map.c +2240 -0
- data/ext/farce/priority_queue.c +2056 -0
- data/ext/farce/queue.c +1059 -0
- data/ext/farce/reactor.c +820 -0
- data/ext/farce/reactor.h +103 -0
- data/ext/farce/shareable.h +31 -0
- data/ext/farce/signal.c +350 -0
- data/ext/farce/transaction.c +354 -0
- data/ext/farce/transaction.h +40 -0
- data/ext/farce/tree_map.c +1953 -0
- data/ext/farce/trie.c +2020 -0
- data/ext/farce/unshareable.c +155 -0
- data/ext/farce/unshared_io_pool.h +234 -0
- data/ext/farce/unshared_signal.c +263 -0
- data/ext/farce/unshared_wait.h +193 -0
- data/ext/farce/unsupported.c +6 -0
- data/ext/farce/vector.c +1195 -0
- data/ext/farce/weak_map.c +1714 -0
- data/ext/java/org/farce/BoundedMap.java +394 -0
- data/ext/java/org/farce/FiberScheduler.java +141 -0
- data/ext/java/org/farce/PriorityKey.java +45 -0
- data/ext/java/org/farce/PriorityQueue.java +373 -0
- data/ext/java/org/farce/QueueSignal.java +28 -0
- data/ext/rebind/README.md +14 -0
- data/ext/rebind/extconf.rb +10 -0
- data/ext/rebind/rebind.c +186 -0
- data/lib/farce/_yard/internal.rb +13 -0
- data/lib/farce/_yard/macros.rb +61 -0
- data/lib/farce/_yard/ractor.rb +46 -0
- data/lib/farce/abstract/atom.rb +186 -0
- data/lib/farce/abstract/bounded_map.rb +232 -0
- data/lib/farce/abstract/collection.rb +151 -0
- data/lib/farce/abstract/concurrent_map.rb +381 -0
- data/lib/farce/abstract/counter.rb +193 -0
- data/lib/farce/abstract/duplicable_map.rb +229 -0
- data/lib/farce/abstract/exchanger.rb +26 -0
- data/lib/farce/abstract/flag.rb +71 -0
- data/lib/farce/abstract/lazy.rb +115 -0
- data/lib/farce/abstract/lease.rb +104 -0
- data/lib/farce/abstract/lease_map.rb +261 -0
- data/lib/farce/abstract/lease_pool.rb +91 -0
- data/lib/farce/abstract/lfu_map.rb +20 -0
- data/lib/farce/abstract/lru_map.rb +25 -0
- data/lib/farce/abstract/map.rb +345 -0
- data/lib/farce/abstract/molecule.rb +245 -0
- data/lib/farce/abstract/port.rb +74 -0
- data/lib/farce/abstract/priority_queue.rb +117 -0
- data/lib/farce/abstract/queue.rb +269 -0
- data/lib/farce/abstract/scheduler.rb +111 -0
- data/lib/farce/abstract/set.rb +910 -0
- data/lib/farce/abstract/sorted_set.rb +172 -0
- data/lib/farce/abstract/timer_queue.rb +136 -0
- data/lib/farce/abstract/tree_map.rb +269 -0
- data/lib/farce/abstract/value.rb +68 -0
- data/lib/farce/abstract/vector.rb +1126 -0
- data/lib/farce/abstract/weak_atom.rb +32 -0
- data/lib/farce/abstract/weak_key_map.rb +12 -0
- data/lib/farce/abstract/weak_map.rb +13 -0
- data/lib/farce/abstract/weak_set.rb +12 -0
- data/lib/farce/abstract/weak_value_map.rb +12 -0
- data/lib/farce/abstract.rb +17 -0
- data/lib/farce/atom.rb +293 -0
- data/lib/farce/class_mirror.rb +87 -0
- data/lib/farce/clock.rb +121 -0
- data/lib/farce/config.rb +229 -0
- data/lib/farce/counter.rb +71 -0
- data/lib/farce/deduper.rb +122 -0
- data/lib/farce/engine/jruby/bounded_map.rb +314 -0
- data/lib/farce/engine/jruby/fiber_scheduler.jar +0 -0
- data/lib/farce/engine/jruby/fiber_scheduler.rb +119 -0
- data/lib/farce/engine/jruby/lease_waiting.rb +19 -0
- data/lib/farce/engine/jruby/map.rb +505 -0
- data/lib/farce/engine/jruby/mutable_numeric_copy.rb +42 -0
- data/lib/farce/engine/jruby/signal.rb +147 -0
- data/lib/farce/engine/jruby.rb +63 -0
- data/lib/farce/engine/jvm/concurrent_weak_registry.rb +55 -0
- data/lib/farce/engine/jvm/counter.rb +102 -0
- data/lib/farce/engine/jvm/extension.rb +32 -0
- data/lib/farce/engine/jvm/farce.jar +0 -0
- data/lib/farce/engine/jvm/flag.rb +79 -0
- data/lib/farce/engine/jvm/priority_queue.rb +217 -0
- data/lib/farce/engine/jvm/tree_map.rb +350 -0
- data/lib/farce/engine/jvm/types.rb +180 -0
- data/lib/farce/engine/jvm.rb +19 -0
- data/lib/farce/engine/ruby/3.4/fiber_scheduler.rb +20 -0
- data/lib/farce/engine/ruby/3.4/port.rb +186 -0
- data/lib/farce/engine/ruby/3.4/ractor_methods.rb +26 -0
- data/lib/farce/engine/ruby/3.4/ractor_selector.rb +92 -0
- data/lib/farce/engine/ruby/3.4/vault.rb +56 -0
- data/lib/farce/engine/ruby/4.0/port.rb +19 -0
- data/lib/farce/engine/ruby/4.0/ractor_methods.rb +20 -0
- data/lib/farce/engine/ruby/4.0/ractor_selector.rb +108 -0
- data/lib/farce/engine/ruby/4.0/vault.rb +74 -0
- data/lib/farce/engine/ruby/4.1/port.rb +21 -0
- data/lib/farce/engine/ruby/4.1/ractor_methods.rb +22 -0
- data/lib/farce/engine/ruby/4.1/ractor_selector.rb +25 -0
- data/lib/farce/engine/ruby/4.1/vault.rb +5 -0
- data/lib/farce/engine/ruby/fiber_scheduler.rb +32 -0
- data/lib/farce/engine/ruby/key_lock_map.rb +28 -0
- data/lib/farce/engine/ruby/shared/lease.rb +26 -0
- data/lib/farce/engine/ruby/shared/lease_pool.rb +24 -0
- data/lib/farce/engine/ruby/shared/main_scheduler.rb +9 -0
- data/lib/farce/engine/ruby/shared/parallel_scheduler.rb +9 -0
- data/lib/farce/engine/ruby/shared/proxy_owner.rb +31 -0
- data/lib/farce/engine/ruby/shared/ractor_methods.rb +34 -0
- data/lib/farce/engine/ruby/shared/ractor_selector.rb +328 -0
- data/lib/farce/engine/ruby/shared/strict_map.rb +13 -0
- data/lib/farce/engine/ruby/shared/unshared_vector.rb +14 -0
- data/lib/farce/engine/ruby/shared/vault.rb +144 -0
- data/lib/farce/engine/ruby/shared/vault_weak_map.rb +336 -0
- data/lib/farce/engine/ruby/shared/weak_atom.rb +54 -0
- data/lib/farce/engine/ruby/shared/weak_map.rb +413 -0
- data/lib/farce/engine/ruby.rb +130 -0
- data/lib/farce/engine/shared/atom.rb +10 -0
- data/lib/farce/engine/shared/exchanger.rb +130 -0
- data/lib/farce/engine/shared/identity_key.rb +22 -0
- data/lib/farce/engine/shared/lease.rb +10 -0
- data/lib/farce/engine/shared/lease_pool.rb +10 -0
- data/lib/farce/engine/shared/main_scheduler.rb +20 -0
- data/lib/farce/engine/shared/map_key_coordination.rb +226 -0
- data/lib/farce/engine/shared/parallel_scheduler.rb +9 -0
- data/lib/farce/engine/shared/port.rb +44 -0
- data/lib/farce/engine/shared/portable_bounded_map.rb +619 -0
- data/lib/farce/engine/shared/proxy_owner.rb +43 -0
- data/lib/farce/engine/shared/queue.rb +233 -0
- data/lib/farce/engine/shared/ractor_methods.rb +73 -0
- data/lib/farce/engine/shared/rebindable.rb +15 -0
- data/lib/farce/engine/shared/strict_atom.rb +73 -0
- data/lib/farce/engine/shared/strict_map.rb +117 -0
- data/lib/farce/engine/shared/strict_queue_values.rb +27 -0
- data/lib/farce/engine/shared/strict_tree_map.rb +56 -0
- data/lib/farce/engine/shared/transaction_map_backend.rb +20 -0
- data/lib/farce/engine/shared/trie.rb +317 -0
- data/lib/farce/engine/shared/trie_builder.rb +199 -0
- data/lib/farce/engine/shared/unshareable.rb +14 -0
- data/lib/farce/engine/shared/unshared_atom.rb +256 -0
- data/lib/farce/engine/shared/unshared_priority_queue.rb +9 -0
- data/lib/farce/engine/shared/unshared_queue.rb +18 -0
- data/lib/farce/engine/shared/unshared_signal.rb +21 -0
- data/lib/farce/engine/shared/unshared_vector.rb +377 -0
- data/lib/farce/engine/shared/unshared_weak_atom.rb +30 -0
- data/lib/farce/engine/shared/unshared_weak_map.rb +445 -0
- data/lib/farce/engine/shared/vault.rb +31 -0
- data/lib/farce/engine/shared/vector.rb +83 -0
- data/lib/farce/engine/shared/weak_atom/base.rb +189 -0
- data/lib/farce/engine/shared/weak_atom.rb +20 -0
- data/lib/farce/engine/shared/weak_map/cell.rb +99 -0
- data/lib/farce/engine/shared/weak_map/index.rb +249 -0
- data/lib/farce/engine/shared/weak_map/lock.rb +80 -0
- data/lib/farce/engine/shared/weak_map/reference.rb +33 -0
- data/lib/farce/engine/shared.rb +63 -0
- data/lib/farce/engine/truffleruby/fiber_scheduler.rb +13 -0
- data/lib/farce/engine/truffleruby/lock.rb +121 -0
- data/lib/farce/engine/truffleruby/map.rb +656 -0
- data/lib/farce/engine/truffleruby/native/counter.rb +105 -0
- data/lib/farce/engine/truffleruby/native/flag.rb +77 -0
- data/lib/farce/engine/truffleruby/native/ordered_array_support.rb +67 -0
- data/lib/farce/engine/truffleruby/native/priority_queue.rb +388 -0
- data/lib/farce/engine/truffleruby/native/tree_map.rb +51 -0
- data/lib/farce/engine/truffleruby/native/unsafe_tree_map.rb +350 -0
- data/lib/farce/engine/truffleruby/signal.rb +77 -0
- data/lib/farce/engine/truffleruby.rb +148 -0
- data/lib/farce/envelope.rb +335 -0
- data/lib/farce/error.rb +35 -0
- data/lib/farce/exchanger.rb +41 -0
- data/lib/farce/flag.rb +27 -0
- data/lib/farce/integrations/active_support/blank.rb +68 -0
- data/lib/farce/integrations/active_support/clock.rb +17 -0
- data/lib/farce/integrations/active_support/duplicable.rb +78 -0
- data/lib/farce/integrations/active_support/map.rb +175 -0
- data/lib/farce/integrations/active_support/set.rb +60 -0
- data/lib/farce/integrations/active_support/value_serialization.rb +17 -0
- data/lib/farce/integrations/active_support/vector.rb +231 -0
- data/lib/farce/integrations/active_support.rb +9 -0
- data/lib/farce/integrations/activesupport.rb +5 -0
- data/lib/farce/integrations/bson.rb +108 -0
- data/lib/farce/integrations/cbor.rb +51 -0
- data/lib/farce/integrations/concurrent.rb +112 -0
- data/lib/farce/integrations/dry-types.rb +5 -0
- data/lib/farce/integrations/dry_types.rb +694 -0
- data/lib/farce/integrations/json.rb +7 -0
- data/lib/farce/integrations/msgpack.rb +112 -0
- data/lib/farce/integrations/oj.rb +69 -0
- data/lib/farce/integrations/psych.rb +191 -0
- data/lib/farce/integrations/ractor-sharing.rb +5 -0
- data/lib/farce/integrations/ractor-tmvar.rb +5 -0
- data/lib/farce/integrations/ractor_sharing.rb +172 -0
- data/lib/farce/integrations/ractor_tmvar.rb +64 -0
- data/lib/farce/integrations/shared/to_json.rb +42 -0
- data/lib/farce/integrations/sorted_set.rb +11 -0
- data/lib/farce/integrations/weakref.rb +38 -0
- data/lib/farce/integrations/yajl.rb +10 -0
- data/lib/farce/integrations.rb +156 -0
- data/lib/farce/internal/_frozen_config.rb +11 -0
- data/lib/farce/internal/autoloads.rb +47 -0
- data/lib/farce/internal/blocking_priority_queue.rb +122 -0
- data/lib/farce/internal/converter.rb +106 -0
- data/lib/farce/internal/copyable.rb +31 -0
- data/lib/farce/internal/delegation.rb +20 -0
- data/lib/farce/internal/external_transaction.rb +59 -0
- data/lib/farce/internal/fake_ractor.rb +179 -0
- data/lib/farce/internal/freeze.rb +118 -0
- data/lib/farce/internal/inspect.rb +157 -0
- data/lib/farce/internal/key_lock_map.rb +29 -0
- data/lib/farce/internal/key_normalizer.rb +289 -0
- data/lib/farce/internal/lease_initialization.rb +115 -0
- data/lib/farce/internal/lease_map.rb +441 -0
- data/lib/farce/internal/lease_pool_state.rb +228 -0
- data/lib/farce/internal/lease_state.rb +342 -0
- data/lib/farce/internal/lease_waiting.rb +13 -0
- data/lib/farce/internal/managed_queue.rb +26 -0
- data/lib/farce/internal/map_value_modes.rb +227 -0
- data/lib/farce/internal/marshal_support.rb +227 -0
- data/lib/farce/internal/mixin.rb +20 -0
- data/lib/farce/internal/mutable_ordered_key_lock_map.rb +63 -0
- data/lib/farce/internal/noncopyable.rb +17 -0
- data/lib/farce/internal/ordered_key_lock_map.rb +69 -0
- data/lib/farce/internal/pool_supervisor.rb +41 -0
- data/lib/farce/internal/pool_worker.rb +61 -0
- data/lib/farce/internal/portable_transaction/reservation_entry.rb +29 -0
- data/lib/farce/internal/portable_transaction/strong_map_entry.rb +137 -0
- data/lib/farce/internal/portable_transaction/strong_map_size_entry.rb +44 -0
- data/lib/farce/internal/portable_transaction/tree_entry.rb +64 -0
- data/lib/farce/internal/portable_transaction.rb +164 -0
- data/lib/farce/internal/proxy_owner_notifications.rb +29 -0
- data/lib/farce/internal/reservation_waiting.rb +24 -0
- data/lib/farce/internal/scheduled_task.rb +48 -0
- data/lib/farce/internal/scheduler_io.rb +171 -0
- data/lib/farce/internal/scheduler_lifecycle.rb +314 -0
- data/lib/farce/internal/select_scheduler.rb +235 -0
- data/lib/farce/internal/storage.rb +162 -0
- data/lib/farce/internal/strict_lease.rb +30 -0
- data/lib/farce/internal/strict_lease_map.rb +20 -0
- data/lib/farce/internal/strict_lease_pool.rb +29 -0
- data/lib/farce/internal/thread_pool.rb +166 -0
- data/lib/farce/internal/transaction_conflict.rb +9 -0
- data/lib/farce/internal/transaction_freeze_guard.rb +30 -0
- data/lib/farce/internal/transaction_map_snapshot.rb +123 -0
- data/lib/farce/internal/undefined.rb +22 -0
- data/lib/farce/internal/unshared_lease.rb +29 -0
- data/lib/farce/internal/unshared_lease_pool.rb +34 -0
- data/lib/farce/internal/unshared_queue_waiting.rb +28 -0
- data/lib/farce/internal/value_serialization.rb +13 -0
- data/lib/farce/internal/weak_map_value_modes.rb +58 -0
- data/lib/farce/internal/weak_mode_manager.rb +26 -0
- data/lib/farce/internal.rb +129 -0
- data/lib/farce/lazy.rb +100 -0
- data/lib/farce/lazy_ref.rb +40 -0
- data/lib/farce/lease.rb +28 -0
- data/lib/farce/lease_map.rb +34 -0
- data/lib/farce/lease_pool.rb +29 -0
- data/lib/farce/lfu_map.rb +53 -0
- data/lib/farce/local/atom.rb +23 -0
- data/lib/farce/local/counter.rb +88 -0
- data/lib/farce/local/flag.rb +65 -0
- data/lib/farce/local/lazy.rb +38 -0
- data/lib/farce/local/lazy_ref.rb +36 -0
- data/lib/farce/local/lease.rb +77 -0
- data/lib/farce/local/lease_map.rb +80 -0
- data/lib/farce/local/lease_pool.rb +38 -0
- data/lib/farce/local/lfu_map.rb +55 -0
- data/lib/farce/local/lru_map.rb +62 -0
- data/lib/farce/local/map.rb +47 -0
- data/lib/farce/local/molecule.rb +45 -0
- data/lib/farce/local/priority_queue.rb +53 -0
- data/lib/farce/local/queue.rb +32 -0
- data/lib/farce/local/scoped.rb +166 -0
- data/lib/farce/local/set.rb +18 -0
- data/lib/farce/local/sorted_set.rb +50 -0
- data/lib/farce/local/timer_queue.rb +41 -0
- data/lib/farce/local/tree_map.rb +47 -0
- data/lib/farce/local/vector.rb +30 -0
- data/lib/farce/local/weak_atom.rb +23 -0
- data/lib/farce/local/weak_key_map.rb +39 -0
- data/lib/farce/local/weak_map.rb +39 -0
- data/lib/farce/local/weak_set.rb +18 -0
- data/lib/farce/local/weak_value_map.rb +39 -0
- data/lib/farce/local.rb +35 -0
- data/lib/farce/lock.rb +54 -0
- data/lib/farce/lru_map.rb +63 -0
- data/lib/farce/map.rb +58 -0
- data/lib/farce/mode_manager.rb +142 -0
- data/lib/farce/molecule.rb +60 -0
- data/lib/farce/mutable.rb +171 -0
- data/lib/farce/pool.rb +332 -0
- data/lib/farce/port.rb +134 -0
- data/lib/farce/priority_queue.rb +70 -0
- data/lib/farce/proxy/register.rb +101 -0
- data/lib/farce/proxy/supervisor.rb +137 -0
- data/lib/farce/proxy/wrapper.rb +49 -0
- data/lib/farce/proxy.rb +291 -0
- data/lib/farce/queue.rb +60 -0
- data/lib/farce/ractor.rb +269 -0
- data/lib/farce/read_write_lock.rb +256 -0
- data/lib/farce/reference.rb +158 -0
- data/lib/farce/resolv/dns.rb +42 -0
- data/lib/farce/resolv.rb +85 -0
- data/lib/farce/scheduler.rb +536 -0
- data/lib/farce/set.rb +39 -0
- data/lib/farce/shareable.rb +150 -0
- data/lib/farce/signal.rb +97 -0
- data/lib/farce/sorted_set.rb +36 -0
- data/lib/farce/strict/atom.rb +34 -0
- data/lib/farce/strict/counter.rb +10 -0
- data/lib/farce/strict/exchanger.rb +25 -0
- data/lib/farce/strict/flag.rb +10 -0
- data/lib/farce/strict/lazy.rb +26 -0
- data/lib/farce/strict/lazy_ref.rb +26 -0
- data/lib/farce/strict/lease.rb +27 -0
- data/lib/farce/strict/lease_map.rb +33 -0
- data/lib/farce/strict/lease_pool.rb +28 -0
- data/lib/farce/strict/lfu_map.rb +27 -0
- data/lib/farce/strict/lru_map.rb +28 -0
- data/lib/farce/strict/map.rb +54 -0
- data/lib/farce/strict/molecule.rb +16 -0
- data/lib/farce/strict/port.rb +40 -0
- data/lib/farce/strict/priority_queue.rb +20 -0
- data/lib/farce/strict/queue.rb +17 -0
- data/lib/farce/strict/set.rb +14 -0
- data/lib/farce/strict/sorted_set.rb +19 -0
- data/lib/farce/strict/timer_queue.rb +13 -0
- data/lib/farce/strict/tree_map.rb +27 -0
- data/lib/farce/strict/vector.rb +24 -0
- data/lib/farce/strict/weak_atom.rb +31 -0
- data/lib/farce/strict/weak_key_map.rb +49 -0
- data/lib/farce/strict/weak_map.rb +49 -0
- data/lib/farce/strict/weak_set.rb +14 -0
- data/lib/farce/strict/weak_value_map.rb +48 -0
- data/lib/farce/strict.rb +28 -0
- data/lib/farce/system.rb +40 -0
- data/lib/farce/thread_scheduler.rb +70 -0
- data/lib/farce/timer_queue.rb +66 -0
- data/lib/farce/transaction/atom.rb +73 -0
- data/lib/farce/transaction/map.rb +25 -0
- data/lib/farce/transaction/map_operations.rb +143 -0
- data/lib/farce/transaction/molecule.rb +90 -0
- data/lib/farce/transaction/mutable.rb +61 -0
- data/lib/farce/transaction/set.rb +17 -0
- data/lib/farce/transaction/set_operations.rb +48 -0
- data/lib/farce/transaction/sorted_set.rb +18 -0
- data/lib/farce/transaction/tree_map.rb +78 -0
- data/lib/farce/transaction/vector.rb +139 -0
- data/lib/farce/transaction/wrapper.rb +202 -0
- data/lib/farce/transaction.rb +343 -0
- data/lib/farce/tree_map.rb +56 -0
- data/lib/farce/unsafe/lfu_map.rb +36 -0
- data/lib/farce/unsafe/lru_map.rb +36 -0
- data/lib/farce/unsafe/tree_map.rb +21 -0
- data/lib/farce/unsafe.rb +29 -0
- data/lib/farce/unshareable.rb +67 -0
- data/lib/farce/unshared/atom.rb +24 -0
- data/lib/farce/unshared/counter.rb +10 -0
- data/lib/farce/unshared/flag.rb +10 -0
- data/lib/farce/unshared/lazy.rb +38 -0
- data/lib/farce/unshared/lazy_ref.rb +26 -0
- data/lib/farce/unshared/lease.rb +27 -0
- data/lib/farce/unshared/lease_map.rb +26 -0
- data/lib/farce/unshared/lease_pool.rb +25 -0
- data/lib/farce/unshared/lfu_map.rb +20 -0
- data/lib/farce/unshared/lru_map.rb +20 -0
- data/lib/farce/unshared/map.rb +49 -0
- data/lib/farce/unshared/molecule.rb +16 -0
- data/lib/farce/unshared/priority_queue.rb +16 -0
- data/lib/farce/unshared/queue.rb +27 -0
- data/lib/farce/unshared/set.rb +14 -0
- data/lib/farce/unshared/sorted_set.rb +28 -0
- data/lib/farce/unshared/timer_queue.rb +16 -0
- data/lib/farce/unshared/tree_map.rb +21 -0
- data/lib/farce/unshared/vector.rb +19 -0
- data/lib/farce/unshared/weak_atom.rb +31 -0
- data/lib/farce/unshared/weak_key_map.rb +44 -0
- data/lib/farce/unshared/weak_map.rb +44 -0
- data/lib/farce/unshared/weak_set.rb +14 -0
- data/lib/farce/unshared/weak_value_map.rb +43 -0
- data/lib/farce/unshared.rb +28 -0
- data/lib/farce/vector.rb +228 -0
- data/lib/farce/version.rb +8 -0
- data/lib/farce/walker/definitions.rb +186 -0
- data/lib/farce/walker/modification.rb +355 -0
- data/lib/farce/walker.rb +319 -0
- data/lib/farce/weak_atom.rb +121 -0
- data/lib/farce/weak_key_map.rb +31 -0
- data/lib/farce/weak_map.rb +33 -0
- data/lib/farce/weak_ref.rb +67 -0
- data/lib/farce/weak_set.rb +82 -0
- data/lib/farce/weak_value.rb +195 -0
- data/lib/farce/weak_value_map.rb +32 -0
- data/lib/farce.rb +519 -0
- metadata +435 -8
|
@@ -0,0 +1,179 @@
|
|
|
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
|
+
module FakeRactor
|
|
9
|
+
State = Struct.new(:id, :name, :main_thread, :default_port, :status, :mutex, :monitors, :source_location)
|
|
10
|
+
|
|
11
|
+
GROUPS = {}.compare_by_identity
|
|
12
|
+
RACTOR_MAPPING = ObjectSpace::WeakKeyMap.new
|
|
13
|
+
STATES = ObjectSpace::WeakKeyMap.new
|
|
14
|
+
|
|
15
|
+
class Main
|
|
16
|
+
include Farce::Ractor
|
|
17
|
+
include Freeze::Unfreezable
|
|
18
|
+
extend RactorMethods
|
|
19
|
+
|
|
20
|
+
private_class_method :new
|
|
21
|
+
INSTANCE = Freeze.publish(new)
|
|
22
|
+
DEFAULT_PORT = BasePort.new
|
|
23
|
+
|
|
24
|
+
def default_port = DEFAULT_PORT
|
|
25
|
+
def inspect = "#<Farce::Ractor#1 running>"
|
|
26
|
+
def join = sleep
|
|
27
|
+
def main? = true
|
|
28
|
+
def monitor(_) = true # rubocop:disable Naming/PredicateMethod
|
|
29
|
+
def name = nil
|
|
30
|
+
def receive(...) = DEFAULT_PORT.receive(...)
|
|
31
|
+
def send(...) = DEFAULT_PORT.send(...)
|
|
32
|
+
def unmonitor(_) = self
|
|
33
|
+
def value = sleep
|
|
34
|
+
|
|
35
|
+
alias << send
|
|
36
|
+
alias recv receive
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class NotMain
|
|
40
|
+
include Farce::Ractor
|
|
41
|
+
include Freeze::Unfreezable
|
|
42
|
+
extend RactorMethods
|
|
43
|
+
|
|
44
|
+
@@ractor_counter = 1
|
|
45
|
+
@@ractor_counter_mutex = Mutex.new
|
|
46
|
+
|
|
47
|
+
def initialize(*, name: nil, &block)
|
|
48
|
+
raise ArgumentError, "must be called with a block" unless block_given?
|
|
49
|
+
group = ThreadGroup.new
|
|
50
|
+
state = State.new(
|
|
51
|
+
default_port: BasePort.new,
|
|
52
|
+
id: @@ractor_counter_mutex.synchronize { @@ractor_counter += 1 },
|
|
53
|
+
monitors: ::Set.new,
|
|
54
|
+
mutex: Mutex.new,
|
|
55
|
+
name: name,
|
|
56
|
+
source_location: -(block.source_location&.join(":") || "(unknown)"),
|
|
57
|
+
status: :running,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
STATES[self] = state
|
|
61
|
+
GROUPS[group] = self
|
|
62
|
+
|
|
63
|
+
state.main_thread = Thread.new do # rubocop:disable Lint/UselessSetterCall
|
|
64
|
+
current = Thread.current
|
|
65
|
+
group.add(current)
|
|
66
|
+
current.freeze
|
|
67
|
+
|
|
68
|
+
RACTOR_MAPPING[current] = self
|
|
69
|
+
result = instance_exec(*, &block)
|
|
70
|
+
|
|
71
|
+
# this will trigger a fiber scheduler main loop if one is set
|
|
72
|
+
Fiber.set_scheduler(nil) if Fiber.respond_to?(:set_scheduler)
|
|
73
|
+
state.status = :exited
|
|
74
|
+
result
|
|
75
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
76
|
+
state.status = :aborted
|
|
77
|
+
raise e
|
|
78
|
+
ensure
|
|
79
|
+
state.mutex.synchronize do
|
|
80
|
+
state.monitors.each do |monitor|
|
|
81
|
+
monitor << state.status
|
|
82
|
+
end
|
|
83
|
+
state.monitors = nil
|
|
84
|
+
end
|
|
85
|
+
group.list.each { it.kill unless it == current }
|
|
86
|
+
GROUPS.delete(group)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def [](key)
|
|
91
|
+
raise "Cannot get ractor local storage for non-current ractor" unless self == FakeRactor.current
|
|
92
|
+
Farce::Ractor[key]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def []=(key, value)
|
|
96
|
+
raise "Cannot set ractor local storage for non-current ractor" unless self == FakeRactor.current
|
|
97
|
+
Farce::Ractor[key] = value
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def monitor(port) # rubocop:disable Naming/PredicateMethod
|
|
101
|
+
state = STATES[self]
|
|
102
|
+
|
|
103
|
+
if state.status == :running
|
|
104
|
+
state.mutex.synchronize do
|
|
105
|
+
next if state.status != :running
|
|
106
|
+
state.monitors << port
|
|
107
|
+
return true
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
port << state.status
|
|
112
|
+
false
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def unmonitor(port)
|
|
116
|
+
state = STATES[self]
|
|
117
|
+
state.mutex.synchronize { state.monitors&.delete(port) }
|
|
118
|
+
self
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def inspect
|
|
122
|
+
return super unless state = STATES[self]
|
|
123
|
+
status = state.status == :running ? "running" : "terminated"
|
|
124
|
+
"#<Farce::Ractor##{state.id}#{" #{state.name}" if state.name} #{state.source_location} #{status}>"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def join
|
|
128
|
+
STATES[self].main_thread.join
|
|
129
|
+
self
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def send(...)
|
|
133
|
+
default_port.send(...)
|
|
134
|
+
self
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def default_port = STATES[self].default_port
|
|
138
|
+
def main? = false
|
|
139
|
+
def name = STATES[self].name
|
|
140
|
+
def receive(...) = default_port.receive(...)
|
|
141
|
+
def value = STATES[self].main_thread.value
|
|
142
|
+
|
|
143
|
+
alias << send
|
|
144
|
+
alias recv receive
|
|
145
|
+
alias to_s inspect
|
|
146
|
+
|
|
147
|
+
undef dup
|
|
148
|
+
undef clone
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def self.current
|
|
152
|
+
# JRuby fibers expose a backing thread with a different thread group.
|
|
153
|
+
thread = Internal.storage_thread(Thread.current)
|
|
154
|
+
override = Storage.thread(thread)[:current_ractor]
|
|
155
|
+
override || GROUPS.fetch(thread.group) { Main::INSTANCE }
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def self.main_thread = STATES[current]&.main_thread || Thread.main
|
|
159
|
+
|
|
160
|
+
# Fibers on this Ruby thread share the override. New threads do not inherit it.
|
|
161
|
+
def self.with_current(ractor)
|
|
162
|
+
storage = Storage.thread
|
|
163
|
+
previous = storage[:current_ractor]
|
|
164
|
+
storage[:current_ractor] = ractor
|
|
165
|
+
yield
|
|
166
|
+
ensure
|
|
167
|
+
storage[:current_ractor] = previous
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def self.threads
|
|
171
|
+
group = Internal.storage_thread(Thread.current).group
|
|
172
|
+
return group.list if GROUPS.key?(group)
|
|
173
|
+
list = ThreadGroup::Default.list
|
|
174
|
+
list += group.list if group != ThreadGroup::Default
|
|
175
|
+
list
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Internal
|
|
7
|
+
# Shared implementation for the explicit frozen-state policies in {Shareable}.
|
|
8
|
+
module Freeze
|
|
9
|
+
# Structurally freeze a Ruby facade, then validate and publish its object graph.
|
|
10
|
+
# This deliberately bypasses an override that controls logical frozen state.
|
|
11
|
+
def self.publish(object)
|
|
12
|
+
Object.instance_method(:freeze).bind_call(object)
|
|
13
|
+
::Ractor.make_shareable(object) if Internal.native_ractors?
|
|
14
|
+
object
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.check(object)
|
|
18
|
+
return object unless object.frozen?
|
|
19
|
+
|
|
20
|
+
raise FrozenError.new("can't modify frozen #{object.class}", receiver: object)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Delegate logical frozen state to storage owned by the wrapper.
|
|
24
|
+
module Delegated
|
|
25
|
+
def freeze
|
|
26
|
+
backend = freeze_backend
|
|
27
|
+
raise "#{self.class} is not initialized" unless backend
|
|
28
|
+
|
|
29
|
+
backend.freeze
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def frozen?
|
|
34
|
+
backend = freeze_backend
|
|
35
|
+
backend ? backend.frozen? : Object.instance_method(:frozen?).bind_call(self)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def check_frozen! = Internal::Freeze.check(self)
|
|
41
|
+
|
|
42
|
+
def publish_shareable_copy(other, operation:, freeze: nil)
|
|
43
|
+
logically_frozen = operation == :clone && (freeze.nil? ? other.frozen? : freeze)
|
|
44
|
+
self.freeze if logically_frozen
|
|
45
|
+
publish_shareable
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Track one logical frozen state shared by all storage resolved through a facade.
|
|
50
|
+
module Tracked
|
|
51
|
+
def initialize(...)
|
|
52
|
+
@farce_freeze_state = Internal::Flag.new(false)
|
|
53
|
+
super
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def freeze
|
|
57
|
+
@farce_freeze_state.set
|
|
58
|
+
self
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def frozen?
|
|
62
|
+
state = @farce_freeze_state
|
|
63
|
+
state ? state.value : Object.instance_method(:frozen?).bind_call(self)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def check_frozen! = Internal::Freeze.check(self)
|
|
69
|
+
|
|
70
|
+
def initialize_copy(other, **)
|
|
71
|
+
super
|
|
72
|
+
state = other.instance_variable_get(:@farce_freeze_state)
|
|
73
|
+
guard = state.respond_to?(:native_flag) ? state.class : Internal::Flag
|
|
74
|
+
@farce_freeze_state = guard.new(false)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def publish_shareable_copy(other, operation:, freeze: nil)
|
|
78
|
+
logically_frozen = operation == :clone && (freeze.nil? ? other.frozen? : freeze)
|
|
79
|
+
self.freeze if logically_frozen
|
|
80
|
+
publish_shareable
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Keep a live service structurally published while rejecting logical freezing.
|
|
85
|
+
module Unfreezable
|
|
86
|
+
def freeze = raise(TypeError, "#{self.class} cannot be frozen")
|
|
87
|
+
def frozen? = false
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
def publish_shareable_copy(_other, operation:, freeze: nil)
|
|
92
|
+
self.freeze if operation == :clone && freeze == true
|
|
93
|
+
publish_shareable
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Let a purpose-built native object publish itself after payload initialization.
|
|
98
|
+
module Native
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def publish_shareable = self
|
|
102
|
+
|
|
103
|
+
def publish_shareable_copy(other, operation:, freeze: nil)
|
|
104
|
+
logically_frozen = operation == :clone && (freeze.nil? ? other.frozen? : freeze)
|
|
105
|
+
self.freeze if logically_frozen
|
|
106
|
+
publish_shareable
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Keep ordinary Ruby frozen state as the public state.
|
|
111
|
+
module Immutable
|
|
112
|
+
private
|
|
113
|
+
|
|
114
|
+
def publish_shareable_copy(*) = publish_shareable
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Internal
|
|
7
|
+
module Inspect
|
|
8
|
+
module Mixin
|
|
9
|
+
def inspect
|
|
10
|
+
inspector = StringInspector.create
|
|
11
|
+
inspector.inspect(self)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def pretty_print(pp)
|
|
15
|
+
inspector = PrettyPrinter.create(pp)
|
|
16
|
+
inspector.object(self)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def pretty_print_cycle(pp)
|
|
20
|
+
inspector = PrettyPrinter.create(pp)
|
|
21
|
+
inspector.object_with_address(self)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def inspect_with(inspector, &)
|
|
25
|
+
return inspector.object_group(self, &) if block_given?
|
|
26
|
+
inspector.object_with_address(self)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class Inspector
|
|
31
|
+
def self.current = Storage.fiber[-name]
|
|
32
|
+
def self.create = current || new
|
|
33
|
+
def initialize = @seen = ::Set.new.compare_by_identity
|
|
34
|
+
def attributes(attributes, ...) = attributes.each { attribute(_1, _2, ...) }
|
|
35
|
+
def object_group(object, &) = group("#<#{object.class.name}", ">", &)
|
|
36
|
+
def object_with_address(object) = text(Kernel.instance_method(:to_s).bind_call(object))
|
|
37
|
+
|
|
38
|
+
def activate
|
|
39
|
+
name = -self.class.name
|
|
40
|
+
old = Storage.fiber[name]
|
|
41
|
+
|
|
42
|
+
begin
|
|
43
|
+
Storage.fiber[name] = self
|
|
44
|
+
yield
|
|
45
|
+
ensure
|
|
46
|
+
Storage.fiber[name] = old
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def attribute(key, value, mode_manager = nil)
|
|
51
|
+
breakable
|
|
52
|
+
text "#{key}="
|
|
53
|
+
object(value, mode_manager)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def from_envelope(envelope, prefix = nil)
|
|
57
|
+
if envelope.owned?
|
|
58
|
+
text(prefix) if prefix
|
|
59
|
+
object(envelope.value)
|
|
60
|
+
else
|
|
61
|
+
text(envelope.claimed? ? "claimed" : "unclaimed")
|
|
62
|
+
end
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def object(object, mode_manager = nil)
|
|
67
|
+
return object_with_address(object) if @seen.include?(object)
|
|
68
|
+
return from_envelope(object) if mode_manager&.managed_envelope?(object)
|
|
69
|
+
return foreign_inspect(object) unless object.is_a?(Mixin)
|
|
70
|
+
|
|
71
|
+
activate do
|
|
72
|
+
@seen << object
|
|
73
|
+
object.inspect_with(self)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
self
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def hash_pair(key, ...)
|
|
80
|
+
if Symbol === key
|
|
81
|
+
key = key.to_s.inspect if key.inspect.match?(%r{\A:["$@!]|[%&*+\-/<=>@\]^`|~]\z})
|
|
82
|
+
text("#{key}: ")
|
|
83
|
+
else
|
|
84
|
+
text("#{key.inspect} => ")
|
|
85
|
+
end
|
|
86
|
+
block_given? ? yield : object(...)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
class StringInspector < Inspector
|
|
91
|
+
def initialize
|
|
92
|
+
@output = +""
|
|
93
|
+
super
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def breakable(str = " ") = text(str)
|
|
97
|
+
def text(str) = @output << str
|
|
98
|
+
def to_s = -@output
|
|
99
|
+
|
|
100
|
+
def inspect(object)
|
|
101
|
+
previous_output = @output
|
|
102
|
+
@output = +""
|
|
103
|
+
object(object)
|
|
104
|
+
to_s
|
|
105
|
+
ensure
|
|
106
|
+
@output = previous_output
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def foreign_inspect(object)
|
|
110
|
+
text(object.inspect)
|
|
111
|
+
rescue StandardError
|
|
112
|
+
object_with_address(object)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def group(before = nil, after = nil)
|
|
116
|
+
text(before) if before
|
|
117
|
+
yield
|
|
118
|
+
text(after) if after
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def seplist(list, sep = nil, iter_method = :each)
|
|
122
|
+
sep ||= -> { text(", ") }
|
|
123
|
+
first = true
|
|
124
|
+
list.__send__(iter_method) do |*args|
|
|
125
|
+
sep.call unless first
|
|
126
|
+
first = false
|
|
127
|
+
yield(*args)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class PrettyPrinter < Inspector
|
|
133
|
+
def self.create(pp) = current&.pp == pp ? current : new(pp)
|
|
134
|
+
|
|
135
|
+
attr_reader :pp
|
|
136
|
+
|
|
137
|
+
Internal.delegate(self, :@pp, :text, :object_group, :breakable, :seplist)
|
|
138
|
+
|
|
139
|
+
def initialize(pp)
|
|
140
|
+
@pp = pp
|
|
141
|
+
super()
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def foreign_inspect(object)
|
|
145
|
+
pp.pp(object)
|
|
146
|
+
rescue StandardError
|
|
147
|
+
object_with_address(object)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def group(...) = @pp.group(1, ...)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.append_features(base) = base.include(Mixin)
|
|
154
|
+
private_constant :Mixin, :Inspector, :PrettyPrinter
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
# Coordinate equal keys without retaining entries after an operation finishes.
|
|
9
|
+
class KeyLockMap
|
|
10
|
+
include Freeze::Unfreezable
|
|
11
|
+
|
|
12
|
+
def initialize(registry_class:, **comparison_options)
|
|
13
|
+
@registry = registry_class.new(**comparison_options)
|
|
14
|
+
Freeze.publish(self) if @registry.ractor_shareable?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def synchronize(key)
|
|
18
|
+
raise LocalJumpError, "no block given" unless block_given?
|
|
19
|
+
|
|
20
|
+
completed = Object.new
|
|
21
|
+
catch(completed) do
|
|
22
|
+
# Nonlocal exit releases the reservation without publishing a value.
|
|
23
|
+
# The block result stays with the caller, even for shareable registries.
|
|
24
|
+
@registry.store_if_absent(key) { throw completed, yield }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|