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,30 @@
|
|
|
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
|
+
# Lease storage that retains shareable resource references directly.
|
|
9
|
+
class StrictLease < LeaseState
|
|
10
|
+
include Freeze::Unfreezable
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def initialize_resource(resource)
|
|
15
|
+
@resource = StrictAtom.new(resource)
|
|
16
|
+
Freeze.publish(self)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def take_resource = @resource.swap(nil)
|
|
20
|
+
def return_resource(resource) = @resource.store(resource)
|
|
21
|
+
|
|
22
|
+
def validate_resource!(resource)
|
|
23
|
+
super
|
|
24
|
+
return if Ractor.shareable?(resource)
|
|
25
|
+
|
|
26
|
+
raise Ractor::IsolationError, "lease resource must be Ractor-shareable"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
# Validate shareable resources before publishing or replacing map leases.
|
|
9
|
+
class StrictLeaseMap < LeaseMap
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def validate_resource!(resource)
|
|
13
|
+
super
|
|
14
|
+
return if Ractor.shareable?(resource)
|
|
15
|
+
|
|
16
|
+
raise Ractor::IsolationError, "lease resource must be Ractor-shareable"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
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
|
+
# Lease pool storage that retains shareable resource references directly.
|
|
9
|
+
class StrictLeasePool < LeasePoolState
|
|
10
|
+
include Freeze::Unfreezable
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def initialize_storage = @resources = StrictMap.new(compare_by_identity: true)
|
|
15
|
+
def finalize_initialization = Freeze.publish(self)
|
|
16
|
+
def store_resource(token, resource) = @resources.store(token, resource)
|
|
17
|
+
def take_resource(token) = @resources.delete(token)
|
|
18
|
+
def return_resource(token, resource) = store_resource(token, resource)
|
|
19
|
+
def discard_resource(token) = @resources.delete(token)
|
|
20
|
+
|
|
21
|
+
def validate_resource!(resource)
|
|
22
|
+
super
|
|
23
|
+
return if Ractor.shareable?(resource)
|
|
24
|
+
|
|
25
|
+
raise Ractor::IsolationError, "lease pool resource must be Ractor-shareable"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Internal
|
|
7
|
+
# Run blocks on a bounded set of reusable threads.
|
|
8
|
+
# Workers start on demand. Capacity limits the total running and queued jobs.
|
|
9
|
+
# Each caller waits for its block's result and receives any exception it raises.
|
|
10
|
+
# Queue waits can yield through Ruby's scheduler hooks when those are available.
|
|
11
|
+
#
|
|
12
|
+
# An interrupted caller cancels its job if it has not started. Once a job has
|
|
13
|
+
# started, the caller waits for it to finish before unwinding its own cleanup.
|
|
14
|
+
# Closing stops new submissions, finishes accepted jobs, and joins the workers.
|
|
15
|
+
class ThreadPool
|
|
16
|
+
# Fetch or create the pool shared by all threads and fibers in this Ractor.
|
|
17
|
+
# Closing it is explicit and terminal. Later calls return the same closed pool.
|
|
18
|
+
def self.current
|
|
19
|
+
Ractor.store_if_absent(name) { new }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Read the configured worker limit for the current Ractor.
|
|
23
|
+
def self.default_max_threads
|
|
24
|
+
Ractor.main? ? FROZEN_CONFIG.main_thread_pool_size : FROZEN_CONFIG.additional_thread_pool_size
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Job
|
|
28
|
+
def initialize(operation)
|
|
29
|
+
@operation = operation
|
|
30
|
+
@mutex = Thread::Mutex.new
|
|
31
|
+
@result = Thread::Queue.new
|
|
32
|
+
@done = Thread::Queue.new
|
|
33
|
+
@started = @cancelled = false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def run
|
|
37
|
+
operation = @mutex.synchronize do
|
|
38
|
+
@started = true
|
|
39
|
+
@operation unless @cancelled
|
|
40
|
+
end
|
|
41
|
+
@value = operation&.call
|
|
42
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- deliver job failures without losing a worker
|
|
43
|
+
@error = e
|
|
44
|
+
ensure
|
|
45
|
+
@operation = nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def finish
|
|
49
|
+
@done << true
|
|
50
|
+
@result << [@value, @error]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def value
|
|
54
|
+
value, error = @result.pop
|
|
55
|
+
raise error if error
|
|
56
|
+
value
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def cancel_and_wait
|
|
60
|
+
# Skip a job that has not started. Otherwise wait for its block to finish
|
|
61
|
+
# before the caller can clean up resources that the block still uses.
|
|
62
|
+
Thread.handle_interrupt(INTERRUPT_MASK) do
|
|
63
|
+
skipped = @mutex.synchronize do
|
|
64
|
+
unless @started
|
|
65
|
+
@cancelled = true
|
|
66
|
+
@operation = nil
|
|
67
|
+
true
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
unless skipped
|
|
71
|
+
Fiber.respond_to?(:blocking) ? Fiber.blocking { @done.pop } : @done.pop
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
private_constant :Job
|
|
77
|
+
|
|
78
|
+
attr_reader :max_threads, :capacity
|
|
79
|
+
|
|
80
|
+
# Limit worker threads and accepted jobs. Capacity defaults to twice the thread limit.
|
|
81
|
+
def initialize(max_threads: ThreadPool.default_max_threads, capacity: nil)
|
|
82
|
+
@max_threads = Integer(max_threads)
|
|
83
|
+
@capacity = capacity.nil? ? @max_threads * 2 : Integer(capacity)
|
|
84
|
+
|
|
85
|
+
raise ArgumentError, "max_threads must be positive" unless @max_threads.positive?
|
|
86
|
+
raise ArgumentError, "capacity must be at least max_threads" if @capacity < @max_threads
|
|
87
|
+
|
|
88
|
+
@mutex = Thread::Mutex.new
|
|
89
|
+
@jobs = Thread::Queue.new
|
|
90
|
+
@slots = Thread::SizedQueue.new(@capacity)
|
|
91
|
+
@workers = []
|
|
92
|
+
@pending = 0
|
|
93
|
+
@closed = false
|
|
94
|
+
|
|
95
|
+
@capacity.times { @slots << true }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Wait for capacity, run the block on a worker, and return its value or raise its exception.
|
|
99
|
+
def call(&operation)
|
|
100
|
+
raise ArgumentError, "no block given" unless operation
|
|
101
|
+
admitted = @slots.pop
|
|
102
|
+
raise IOError, "thread pool is closed" unless admitted
|
|
103
|
+
job = Job.new(operation)
|
|
104
|
+
submitted = false
|
|
105
|
+
Thread.handle_interrupt(INTERRUPT_MASK) do
|
|
106
|
+
submit(job)
|
|
107
|
+
submitted = true
|
|
108
|
+
end
|
|
109
|
+
job.value
|
|
110
|
+
ensure
|
|
111
|
+
if submitted
|
|
112
|
+
job.cancel_and_wait
|
|
113
|
+
elsif admitted
|
|
114
|
+
release_slot
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Return the number of workers created so far.
|
|
119
|
+
def size = @mutex.synchronize { @workers.size }
|
|
120
|
+
|
|
121
|
+
# Report whether the pool has stopped accepting jobs.
|
|
122
|
+
def closed? = @mutex.synchronize { @closed }
|
|
123
|
+
|
|
124
|
+
# Stop accepting jobs, wake callers waiting for capacity, and finish accepted jobs.
|
|
125
|
+
def close
|
|
126
|
+
workers = @mutex.synchronize do
|
|
127
|
+
raise ThreadError, "a worker cannot close its own pool" if @workers.include?(Thread.current)
|
|
128
|
+
@closed = true
|
|
129
|
+
@slots.close
|
|
130
|
+
@jobs.close
|
|
131
|
+
@workers.dup
|
|
132
|
+
end
|
|
133
|
+
Fiber.respond_to?(:blocking) ? Fiber.blocking { workers.each(&:join) } : workers.each(&:join)
|
|
134
|
+
nil
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
|
|
139
|
+
def submit(job)
|
|
140
|
+
@mutex.synchronize do
|
|
141
|
+
raise IOError, "thread pool is closed" if @closed
|
|
142
|
+
@workers << Thread.new { work } if @workers.size < @max_threads && @workers.size <= @pending
|
|
143
|
+
@pending += 1
|
|
144
|
+
@jobs << job
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def work
|
|
149
|
+
while job = @jobs.pop
|
|
150
|
+
job.run
|
|
151
|
+
@mutex.synchronize { @pending -= 1 }
|
|
152
|
+
release_slot
|
|
153
|
+
job.finish
|
|
154
|
+
job = nil
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def release_slot
|
|
159
|
+
@slots << true
|
|
160
|
+
rescue ::ClosedQueueError
|
|
161
|
+
# Closing the pool has already woken callers waiting for capacity.
|
|
162
|
+
nil
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Internal # :nodoc: all
|
|
7
|
+
# Keep a Local handle's shared freeze state stable across a foreign commit.
|
|
8
|
+
# Reads retain the atomic flag. Only freeze and mixed commits take the lock.
|
|
9
|
+
class TransactionFreezeGuard
|
|
10
|
+
include Shareable::Immutable
|
|
11
|
+
|
|
12
|
+
attr_reader :native_flag, :lock
|
|
13
|
+
|
|
14
|
+
def initialize(value)
|
|
15
|
+
@native_flag = Flag.new(value)
|
|
16
|
+
@lock = Farce::Lock.new
|
|
17
|
+
super()
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def value = @native_flag.value
|
|
21
|
+
|
|
22
|
+
def set
|
|
23
|
+
@lock.synchronize do
|
|
24
|
+
yield if block_given?
|
|
25
|
+
@native_flag.set
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Internal # :nodoc: all
|
|
7
|
+
# Records map dependencies without copying unobserved entries during the block.
|
|
8
|
+
# Full-map operations validate those dependencies before capturing all entries.
|
|
9
|
+
# Commit overlays staged writes onto a current snapshot for atomic publication.
|
|
10
|
+
class TransactionMapSnapshot
|
|
11
|
+
ABSENT = Object.new.freeze
|
|
12
|
+
private_constant :ABSENT
|
|
13
|
+
|
|
14
|
+
def initialize(source)
|
|
15
|
+
@source = source
|
|
16
|
+
@partial = source.class.new(
|
|
17
|
+
compare_keys_by_identity: source.compare_keys_by_identity?,
|
|
18
|
+
compare_values_by_identity: source.compare_values_by_identity?,
|
|
19
|
+
)
|
|
20
|
+
@observations = {}
|
|
21
|
+
@writes = {}
|
|
22
|
+
if source.compare_keys_by_identity?
|
|
23
|
+
@observations.compare_by_identity
|
|
24
|
+
@writes.compare_by_identity
|
|
25
|
+
end
|
|
26
|
+
@observed_present = 0
|
|
27
|
+
@base_size = nil
|
|
28
|
+
@dirty = false
|
|
29
|
+
@full = nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def working = self
|
|
33
|
+
|
|
34
|
+
def write!
|
|
35
|
+
@dirty = true
|
|
36
|
+
@full&.write!
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def [](key) = observe(key)[key]
|
|
40
|
+
def key?(key) = observe(key).key?(key)
|
|
41
|
+
def store(key, value) = changed(key).store(key, value)
|
|
42
|
+
def swap(key, value) = changed(key).swap(key, value)
|
|
43
|
+
def compare_and_set(key, expected, replacement) = changed(key).compare_and_set(key, expected, replacement)
|
|
44
|
+
|
|
45
|
+
def delete(key)
|
|
46
|
+
map = changed(key)
|
|
47
|
+
@writes[key] = true unless @full
|
|
48
|
+
map.delete(key)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def size
|
|
52
|
+
return @full.working.size if @full
|
|
53
|
+
@base_size ||= @source.respond_to?(:transaction_size) ? @source.transaction_size : @source.size
|
|
54
|
+
@base_size + @partial.size - @observed_present
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def getkey(key) = promote.working.getkey(key)
|
|
58
|
+
def keys = promote.working.keys
|
|
59
|
+
def clear = promote.working.clear
|
|
60
|
+
def each(&) = promote.working.each(&)
|
|
61
|
+
|
|
62
|
+
def prepare_commit
|
|
63
|
+
return @full if @full
|
|
64
|
+
if !@dirty && @observations.empty?
|
|
65
|
+
return unless @base_size
|
|
66
|
+
return @source.transaction_size_snapshot(@base_size) if @source.respond_to?(:transaction_size_snapshot)
|
|
67
|
+
end
|
|
68
|
+
promote
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def read(source, key)
|
|
74
|
+
return source.transaction_read(key) if source.respond_to?(:transaction_read)
|
|
75
|
+
value = source.fetch(key, ABSENT)
|
|
76
|
+
[!PortableTransaction.same?(value, ABSENT), value]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def observe(key)
|
|
80
|
+
return @full.working if @full
|
|
81
|
+
unless @observations.key?(key)
|
|
82
|
+
present, value = read(@source, key)
|
|
83
|
+
@observations[key] = [present, value]
|
|
84
|
+
if present
|
|
85
|
+
@partial.store(key, value)
|
|
86
|
+
@observed_present += 1
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
@partial
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def changed(key)
|
|
93
|
+
map = observe(key)
|
|
94
|
+
@writes[key] = false unless @full || @writes.key?(key)
|
|
95
|
+
map
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def promote
|
|
99
|
+
return @full if @full
|
|
100
|
+
snapshot = @source.transaction_snapshot
|
|
101
|
+
current = snapshot.working
|
|
102
|
+
raise TransactionConflict, "map size changed" if @base_size && current.size != @base_size
|
|
103
|
+
@observations.each do |key, (present, value)|
|
|
104
|
+
current_present, current_value = read(current, key)
|
|
105
|
+
unless present == current_present && (!present || PortableTransaction.same?(value, current_value))
|
|
106
|
+
raise TransactionConflict, "map observation changed"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
@writes.each do |key, deleted|
|
|
110
|
+
# Deletion followed by reinsertion must replace the stored key object.
|
|
111
|
+
current.delete(key) if deleted
|
|
112
|
+
if @partial.key?(key)
|
|
113
|
+
current.store(@partial.getkey(key), @partial[key])
|
|
114
|
+
else
|
|
115
|
+
current.delete(key)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
snapshot.write! if @dirty
|
|
119
|
+
@full = snapshot
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Farce
|
|
4
|
+
# @!visibility private
|
|
5
|
+
module Internal # :nodoc: all
|
|
6
|
+
class Undefined < BasicObject
|
|
7
|
+
define_method(:freeze, ::Object.instance_method(:freeze))
|
|
8
|
+
define_method(:frozen?, ::Object.instance_method(:frozen?))
|
|
9
|
+
|
|
10
|
+
def initialize(inspect)
|
|
11
|
+
@inspect = inspect
|
|
12
|
+
Ractor.make_shareable(self) if defined?(Ractor)
|
|
13
|
+
freeze
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
attr_reader :inspect
|
|
17
|
+
|
|
18
|
+
def nil? = false
|
|
19
|
+
alias === equal?
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
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
|
+
# Lease storage that passes its resource directly within one Ractor.
|
|
9
|
+
class UnsharedLease < LeaseState
|
|
10
|
+
include Freeze::Unfreezable
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def initialize_resource(resource)
|
|
15
|
+
@resource = resource
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def take_resource
|
|
19
|
+
resource = @resource
|
|
20
|
+
@resource = nil
|
|
21
|
+
resource
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def return_resource(resource)
|
|
25
|
+
@resource = resource
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
# Lease pool storage that passes resource references within one Ractor.
|
|
9
|
+
class UnsharedLeasePool < LeasePoolState
|
|
10
|
+
include Freeze::Unfreezable
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def initialize_storage
|
|
15
|
+
@resource_lock = Mutex.new
|
|
16
|
+
@resources = {}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def store_resource(token, resource)
|
|
20
|
+
@resource_lock.synchronize { @resources[token] = resource }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def take_resource(token)
|
|
24
|
+
@resource_lock.synchronize { @resources.delete(token) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
alias return_resource store_resource
|
|
28
|
+
|
|
29
|
+
def discard_resource(token)
|
|
30
|
+
@resource_lock.synchronize { @resources.delete(token) }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Internal # :nodoc: all
|
|
7
|
+
module UnsharedQueueWaiting
|
|
8
|
+
# The resolved fiber waiting strategy. Other Ruby engines may return :auto.
|
|
9
|
+
attr_reader :fiber_wait
|
|
10
|
+
|
|
11
|
+
# @param fiber_wait [:auto, :io, :block] how scheduled fibers wait on CRuby
|
|
12
|
+
def initialize(fiber_wait: :auto, **)
|
|
13
|
+
@fiber_wait = fiber_wait
|
|
14
|
+
super(**)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def queue_signal
|
|
20
|
+
signal = Internal::UnsharedSignal.for(@fiber_wait)
|
|
21
|
+
@fiber_wait = signal.fiber_wait
|
|
22
|
+
signal
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def queue_storage_class = Internal::UnsharedPriorityQueue
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
# Extension point for integrations that serialize a container's current value.
|
|
9
|
+
# @api private
|
|
10
|
+
module ValueSerialization
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
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 WeakMapValueModes
|
|
9
|
+
include MapValueModes
|
|
10
|
+
|
|
11
|
+
# Values follow the selected mode. Keys must already be shareable.
|
|
12
|
+
# @param mode [Symbol] :raise, :make_shareable, or :dedup
|
|
13
|
+
def initialize(initial_mapping = nil, mode: :raise, **options)
|
|
14
|
+
super
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def store(key, value, mode: nil, **)
|
|
18
|
+
@manager.validate_mode!(mode)
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def swap(key, replacement, mode: nil, **)
|
|
23
|
+
@manager.validate_mode!(mode)
|
|
24
|
+
super
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def store_if_absent(key, mode: nil, **)
|
|
28
|
+
raise LocalJumpError, "no block given" unless block_given?
|
|
29
|
+
@manager.validate_mode!(mode)
|
|
30
|
+
super
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def update(key, mode: nil, **)
|
|
34
|
+
raise LocalJumpError, "no block given" unless block_given?
|
|
35
|
+
@manager.validate_mode!(mode)
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def upsert(key, initial, mode: nil, **)
|
|
40
|
+
raise LocalJumpError, "no block given" unless block_given?
|
|
41
|
+
@manager.validate_mode!(mode)
|
|
42
|
+
super
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def compare_and_set(key, expected, replacement, mode: nil, **)
|
|
46
|
+
@manager.validate_mode!(mode)
|
|
47
|
+
super
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def new_mode_manager(mode:) = WeakModeManager.new(mode:)
|
|
53
|
+
|
|
54
|
+
# Expected values are comparison operands, not values to publish.
|
|
55
|
+
def wrap_comparison(value) = nil.equal?(value) ? NIL_VALUE : value
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
# Prepare values without introducing a wrapper with an independent lifetime.
|
|
9
|
+
class WeakModeManager < ModeManager
|
|
10
|
+
MODES = %i[raise make_shareable dedup].freeze
|
|
11
|
+
|
|
12
|
+
def initialize(mode: :raise)
|
|
13
|
+
validate_mode!(mode)
|
|
14
|
+
super
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def validate_mode!(mode)
|
|
18
|
+
selected = nil.equal?(mode) ? self.mode : mode
|
|
19
|
+
return selected if MODES.include?(selected)
|
|
20
|
+
raise ArgumentError, "unsupported weak value mode: #{selected.inspect}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def wrap(value, mode: nil) = super(value, mode: validate_mode!(mode))
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|