farce 0.0.1.alpha2-x86-linux-gnu
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +26 -0
- data/CONTRIBUTING.md +71 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1524 -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/farce.so +0 -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/rebind.so +0 -0
- data/lib/farce/engine/ruby/3.4/vault.rb +56 -0
- data/lib/farce/engine/ruby/4.0/farce.so +0 -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/rebind.so +0 -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 +468 -0
data/lib/farce/unsafe.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# Module holding classes with instances which are not thread-safe and cannot be shared between Ractors.
|
|
7
|
+
module Unsafe
|
|
8
|
+
include Unshared
|
|
9
|
+
include Internal::Autoloads
|
|
10
|
+
|
|
11
|
+
# @overload enfarce(object, freeze: nil)
|
|
12
|
+
# Converts vanilla Ruby objects into their {Farce::Unsafe} equivalents.
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# Farce::Unsafe.enfarce({ foo: ["bar"] })
|
|
16
|
+
# # => #<Farce::Unsafe::Map {foo: #<Farce::Unsafe::Vector ["bar"]>}>
|
|
17
|
+
#
|
|
18
|
+
# @yield [object] Optional block, called with any object that doesn't have a specific conversion defined.
|
|
19
|
+
# @yieldparam object [BasicObject] the object to convert
|
|
20
|
+
# @yieldreturn [BasicObject] the converted object
|
|
21
|
+
# @param object [BasicObject] The root object to convert
|
|
22
|
+
# @param freeze [Boolean, nil]
|
|
23
|
+
# Whether to freeze the converted objects.
|
|
24
|
+
# If set to `nil` (default), the freezing behavior will depend on the original object's frozen state.
|
|
25
|
+
# @return [BasicObject] the converted object
|
|
26
|
+
# @see Farce.enfarce
|
|
27
|
+
def self.enfarce(object, **, &) = Internal::Converter.new(self, **, &).convert(object)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# Mixin that makes sure instances cannot be shared between Ractors.
|
|
7
|
+
# @note Mixin in this module will remove the `freeze` method from the class.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# class MyClass
|
|
11
|
+
# include Farce::Unshareable
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# object = MyClass.new
|
|
15
|
+
# object.freeze # this would normally make it shareable
|
|
16
|
+
#
|
|
17
|
+
# Ractor.shareable?(object) # => false
|
|
18
|
+
module Unshareable
|
|
19
|
+
# @api private
|
|
20
|
+
module UndefFreeze # :nodoc: all
|
|
21
|
+
# @api private
|
|
22
|
+
def append_features(mod)
|
|
23
|
+
super
|
|
24
|
+
if mod.is_a?(Class)
|
|
25
|
+
mod.class_eval { undef freeze if method_defined?(:freeze) }
|
|
26
|
+
else
|
|
27
|
+
mod.extend(UndefFreeze)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private_constant :UndefFreeze
|
|
33
|
+
extend UndefFreeze
|
|
34
|
+
|
|
35
|
+
# Mixin for classes that cannot be shared across Ractors, but may be moved between them.
|
|
36
|
+
module Movable
|
|
37
|
+
include Unshareable
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Mixin for classes that cannot be shared across Ractors, but may be copied between them.
|
|
41
|
+
module Copyable
|
|
42
|
+
include Unshareable
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Make sure to call `super` if you include this module.
|
|
46
|
+
# Accepts any arguments and passes them on to the superclass initializer.
|
|
47
|
+
def initialize(...)
|
|
48
|
+
pin_unshareable
|
|
49
|
+
super
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @return [Boolean] false
|
|
53
|
+
# @see Shareable#ractor_shareable?
|
|
54
|
+
def ractor_shareable? = false
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def pin_unshareable
|
|
59
|
+
return unless Internal.native_ractors?
|
|
60
|
+
case self
|
|
61
|
+
when Movable then Internal::Unshareable.prevent_copyable(self) unless is_a?(Copyable)
|
|
62
|
+
when Copyable then Internal::Unshareable.prevent_movable(self)
|
|
63
|
+
else Internal::Unshareable.pin_to_current_ractor(self)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe atomic reference that retains values directly within one Ractor.
|
|
8
|
+
# Mutable values keep their identity. Updates are serialized between threads.
|
|
9
|
+
#
|
|
10
|
+
# @example Updating an array atomically
|
|
11
|
+
# atom = Farce::Unshared::Atom.new([])
|
|
12
|
+
# atom.update { |items| items + [:job] }
|
|
13
|
+
class Atom < Abstract::Atom
|
|
14
|
+
include Unshareable
|
|
15
|
+
|
|
16
|
+
# @param value [BasicObject, nil] the initial value
|
|
17
|
+
# @param compare_by_identity [Boolean] whether comparisons use object identity
|
|
18
|
+
def initialize(value = nil, compare_by_identity: false)
|
|
19
|
+
@atom = Internal::UnsharedAtom.new(value, compare_by_identity:)
|
|
20
|
+
super()
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe lazy value within one Ractor.
|
|
8
|
+
# Its factory may capture mutable state. The result retains its identity.
|
|
9
|
+
# Factory failures can be retried on the next access.
|
|
10
|
+
#
|
|
11
|
+
# @example Build a mutable cache on first access
|
|
12
|
+
# lazy = Farce::Unshared::Lazy.new { {} }
|
|
13
|
+
# lazy.value[:job] = :ready
|
|
14
|
+
#
|
|
15
|
+
# @!parse
|
|
16
|
+
# class Lazy < Abstract::Lazy
|
|
17
|
+
# # Without `self:`, the block keeps its original receiver.
|
|
18
|
+
# # @overload initialize(factory)
|
|
19
|
+
# # @param factory [Class, Proc, #call] the factory, which may retain mutable state
|
|
20
|
+
# # @overload initialize(self: nil)
|
|
21
|
+
# # @param self [BasicObject] the receiver to bind to the block
|
|
22
|
+
# # @yield computes the value on first access, preserving captured state
|
|
23
|
+
# # @yieldreturn [BasicObject] the cached result
|
|
24
|
+
# def initialize(...) = nil
|
|
25
|
+
# end
|
|
26
|
+
class Lazy < Abstract::Lazy
|
|
27
|
+
include Unshareable
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def new_internal_atom = Internal::UnsharedAtom.new
|
|
32
|
+
|
|
33
|
+
def prepare_proc(factory, **options)
|
|
34
|
+
options.empty? ? factory : Farce.rebind(factory, **options)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# @!parse
|
|
8
|
+
# # A {Reference} for a {Unshared::Lazy} value.
|
|
9
|
+
# # Delegates to the result after computing it on first access.
|
|
10
|
+
# # Calling `freeze` resolves and freezes the target.
|
|
11
|
+
# #
|
|
12
|
+
# # @example
|
|
13
|
+
# # reference = Farce::Unshared::LazyRef.new { [] }
|
|
14
|
+
# # reference.push(:ready) # => [:ready]
|
|
15
|
+
# class LazyRef < Farce::Reference
|
|
16
|
+
# # @overload initialize(factory)
|
|
17
|
+
# # @param factory [Class, Proc, #call] the factory for the lazy value
|
|
18
|
+
# # @overload initialize(self: nil)
|
|
19
|
+
# # @param self [BasicObject] the receiver to bind to the block
|
|
20
|
+
# # @yield computes the value on first access
|
|
21
|
+
# # @yieldreturn [BasicObject] the computed result
|
|
22
|
+
# def initialize(...) = nil
|
|
23
|
+
# end
|
|
24
|
+
LazyRef = Reference[Farce::Unshared::Lazy]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe lease that passes one resource directly within a Ractor.
|
|
8
|
+
#
|
|
9
|
+
# @example Updating one object from multiple threads
|
|
10
|
+
# lease = Farce::Unshared::Lease.new { { count: 0 } }
|
|
11
|
+
# workers = 3.times.map do
|
|
12
|
+
# Thread.new do
|
|
13
|
+
# lease.checkout { |state| state[:count] += 1 }
|
|
14
|
+
# end
|
|
15
|
+
# end
|
|
16
|
+
# workers.each(&:join)
|
|
17
|
+
#
|
|
18
|
+
# lease.checkout { |state| state[:count] } # => 3
|
|
19
|
+
class Lease < Abstract::Lease
|
|
20
|
+
include Unshareable
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def new_internal_lease(resource) = Internal::UnsharedLease.new(resource)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe map that passes independently leased resources within one Ractor.
|
|
8
|
+
#
|
|
9
|
+
# @example Coordinating mutable resources between threads
|
|
10
|
+
# leases = Farce::Unshared::LeaseMap.new { { jobs: [] } }
|
|
11
|
+
# workers = 2.times.map do
|
|
12
|
+
# Thread.new { leases.checkout(:jobs) { |jobs| jobs << :finished } }
|
|
13
|
+
# end
|
|
14
|
+
# workers.each(&:join)
|
|
15
|
+
# leases.checkout(:jobs, &:length) # => 2
|
|
16
|
+
class LeaseMap < Abstract::LeaseMap
|
|
17
|
+
include Unshareable
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def new_internal_lease_map(mapping)
|
|
22
|
+
Internal::LeaseMap.new(mapping, lease_class: Farce::Unshared::Lease, registry_class: Farce::Unshared::Map)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe pool that passes resource references within one Ractor.
|
|
8
|
+
#
|
|
9
|
+
# @example Reusing objects from multiple threads
|
|
10
|
+
# pool = Farce::Unshared::LeasePool.new(max_size: 1) { { uses: 0 } }
|
|
11
|
+
# workers = 2.times.map do
|
|
12
|
+
# Thread.new { pool.checkout { |state| state[:uses] += 1 } }
|
|
13
|
+
# end
|
|
14
|
+
# workers.each(&:join)
|
|
15
|
+
#
|
|
16
|
+
# pool.checkout { |state| state[:uses] } # => 2
|
|
17
|
+
class LeasePool < Abstract::LeasePool
|
|
18
|
+
include Unshareable
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def new_internal_pool(max_size) = Internal::UnsharedLeasePool.new(max_size)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe LFU map for mutable keys and values used within one Ractor.
|
|
8
|
+
class LFUMap < Abstract::LFUMap
|
|
9
|
+
include Unshareable
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def new_bounded_map(...) = Internal::LFUMap.new(...)
|
|
14
|
+
|
|
15
|
+
def new_key_locks(compare_keys_by_identity:)
|
|
16
|
+
Internal::KeyLockMap.new(registry_class: Farce::Unshared::Map, compare_keys_by_identity:)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe LRU map for mutable keys and values used within one Ractor.
|
|
8
|
+
class LRUMap < Abstract::LRUMap
|
|
9
|
+
include Unshareable
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def new_bounded_map(...) = Internal::LRUMap.new(...)
|
|
14
|
+
|
|
15
|
+
def new_key_locks(compare_keys_by_identity:)
|
|
16
|
+
Internal::KeyLockMap.new(registry_class: Farce::Unshared::Map, compare_keys_by_identity:)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe concurrent map for mutable objects used within one Ractor.
|
|
8
|
+
# Updates on different keys can run concurrently.
|
|
9
|
+
#
|
|
10
|
+
# Clearing the map invalidates unfinished updates so they cannot restore removed entries.
|
|
11
|
+
#
|
|
12
|
+
# `dup` and `clone` copy entries into independent storage while sharing stored values.
|
|
13
|
+
class Map < Abstract::ConcurrentMap
|
|
14
|
+
include Unshareable
|
|
15
|
+
|
|
16
|
+
# @!macro map_initialization
|
|
17
|
+
#
|
|
18
|
+
# @example Atomically updating a mutable value
|
|
19
|
+
# counters = Farce::Unshared::Map.new({ jobs: [] })
|
|
20
|
+
# counters.update(:jobs) { |jobs| jobs << :finished }
|
|
21
|
+
# counters[:jobs] # => [:finished]
|
|
22
|
+
#
|
|
23
|
+
def initialize(
|
|
24
|
+
initial_mapping = nil,
|
|
25
|
+
normalize_keys: nil,
|
|
26
|
+
compare_by_identity: false,
|
|
27
|
+
compare_keys_by_identity: compare_by_identity,
|
|
28
|
+
compare_values_by_identity: compare_by_identity
|
|
29
|
+
)
|
|
30
|
+
initial_mapping = convert_entries(initial_mapping)
|
|
31
|
+
restoring = Internal::KeyNormalizer.restoration?(normalize_keys)
|
|
32
|
+
normalizer = Internal::KeyNormalizer.build(normalize_keys, shareable: false)
|
|
33
|
+
populate = initial_mapping && ((normalizer && !restoring) || !initial_mapping.is_a?(Hash))
|
|
34
|
+
@map = Internal::UnsharedMap.new(
|
|
35
|
+
populate ? nil : initial_mapping,
|
|
36
|
+
compare_by_identity:,
|
|
37
|
+
compare_keys_by_identity:,
|
|
38
|
+
compare_values_by_identity:,
|
|
39
|
+
)
|
|
40
|
+
Internal::KeyNormalizer.install_concurrent(self, normalizer) unless restoring
|
|
41
|
+
initial_mapping.each { |key, value| self[key] = value } if populate
|
|
42
|
+
Internal::KeyNormalizer.install_concurrent(self, normalizer) if restoring
|
|
43
|
+
super()
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
Internal.prepare_map_access(self, :unshared)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe record whose atoms retain values directly within one Ractor.
|
|
8
|
+
# Use {Abstract::Molecule.define} to declare named fields.
|
|
9
|
+
# Explicitly supplied atoms keep their own storage and comparison policies.
|
|
10
|
+
class Molecule < Abstract::Molecule
|
|
11
|
+
include Unshareable
|
|
12
|
+
|
|
13
|
+
private def create_atom(_, value) = Atom.new(value, compare_by_identity: compare_by_identity?)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A priority queue that stores and returns values directly.
|
|
8
|
+
class PriorityQueue < Abstract::PriorityQueue
|
|
9
|
+
include Unshareable
|
|
10
|
+
include Internal::UnsharedQueueWaiting
|
|
11
|
+
|
|
12
|
+
# @return [Symbol] always returns :local
|
|
13
|
+
def mode = :local
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A FIFO queue that stores and returns values directly.
|
|
8
|
+
class Queue < Abstract::Queue
|
|
9
|
+
include Unshareable
|
|
10
|
+
|
|
11
|
+
# @overload initialize(capacity: 1024, track_age: false)
|
|
12
|
+
# (see Farce::Abstract::Queue#initialize)
|
|
13
|
+
def initialize(capacity: 1024, fiber_wait: :auto, track_age: false)
|
|
14
|
+
@queue = Internal::UnsharedQueue.new(capacity:, fiber_wait:, track_age:)
|
|
15
|
+
super()
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# (see Farce::Abstract::Queue#mode)
|
|
19
|
+
# @return [Symbol] always returns :local
|
|
20
|
+
def mode = :local
|
|
21
|
+
|
|
22
|
+
# The resolved fiber waiting strategy. Other Ruby engines may return :auto.
|
|
23
|
+
# @api private
|
|
24
|
+
def fiber_wait = @queue.fiber_wait
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe set for mutable elements used within one Ractor.
|
|
8
|
+
class Set < Farce::Abstract::Set
|
|
9
|
+
include Unshareable
|
|
10
|
+
|
|
11
|
+
private def new_map(...) = Farce::Unshared::Map.new(...)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
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 Unshared
|
|
7
|
+
# A thread-safe set maintained in ascending order within one Ractor.
|
|
8
|
+
class SortedSet < Farce::Abstract::SortedSet
|
|
9
|
+
include Unshareable
|
|
10
|
+
|
|
11
|
+
class MutableTreeMap < Farce::Unshared::TreeMap # :nodoc:
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def prepare_key(key) = key
|
|
15
|
+
def new_key_locks = Internal::MutableOrderedKeyLockMap.new
|
|
16
|
+
def new_tree_map(...) = Internal::MutableTreeMap.new(...)
|
|
17
|
+
end
|
|
18
|
+
private_constant :MutableTreeMap
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def new_map(entries = nil, compare_keys_by_identity: false, **)
|
|
23
|
+
raise ArgumentError, "sorted sets do not support identity comparison" if compare_keys_by_identity
|
|
24
|
+
MutableTreeMap.new(entries)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A timer queue that stores and returns values directly.
|
|
8
|
+
class TimerQueue < Abstract::TimerQueue
|
|
9
|
+
include Unshareable
|
|
10
|
+
include Internal::UnsharedQueueWaiting
|
|
11
|
+
|
|
12
|
+
# @return [Symbol] always returns :local
|
|
13
|
+
def mode = :local
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe map that keeps entries sorted by key within one Ractor.
|
|
8
|
+
# Mutable string keys become immutable. Values are stored directly and may be mutable.
|
|
9
|
+
#
|
|
10
|
+
# @example Keeping mutable values in key order
|
|
11
|
+
# value = []
|
|
12
|
+
# map = Farce::Unshared::TreeMap.new(2 => value, 1 => [])
|
|
13
|
+
#
|
|
14
|
+
# map[2].equal?(value) # => true
|
|
15
|
+
class TreeMap < Abstract::TreeMap
|
|
16
|
+
include Unshareable
|
|
17
|
+
|
|
18
|
+
private def new_tree_map(...) = Internal::TreeMap.new(...)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe vector for mutable values used within one Ractor.
|
|
8
|
+
class Vector < Abstract::Vector
|
|
9
|
+
include Unshareable
|
|
10
|
+
|
|
11
|
+
# @param source [Array, nil] Initial values. Values are retained directly.
|
|
12
|
+
# @param compare_by_identity [Boolean] Whether values are compared by identity.
|
|
13
|
+
def initialize(source = nil, compare_by_identity: false)
|
|
14
|
+
@vector = Internal::UnsharedVector.new(source, compare_by_identity:)
|
|
15
|
+
super()
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe weak atomic reference for values used within one Ractor.
|
|
8
|
+
#
|
|
9
|
+
# @example Referencing a mutable object within one Ractor
|
|
10
|
+
# items = []
|
|
11
|
+
# atom = Farce::Unshared::WeakAtom.new(items)
|
|
12
|
+
# atom.value.equal?(items) # => true
|
|
13
|
+
# items << :job
|
|
14
|
+
# atom.value # => [:job]
|
|
15
|
+
#
|
|
16
|
+
# items = nil
|
|
17
|
+
# # Once the array is collected, atom.value returns nil.
|
|
18
|
+
#
|
|
19
|
+
# @example Atomically replacing the referenced object
|
|
20
|
+
# original = []
|
|
21
|
+
# replacement = [:job]
|
|
22
|
+
# atom = Farce::Unshared::WeakAtom.new(original, compare_by_identity: true)
|
|
23
|
+
# atom.compare_and_set(original, replacement) # => true
|
|
24
|
+
# atom.value.equal?(replacement) # => true
|
|
25
|
+
class WeakAtom < Abstract::WeakAtom
|
|
26
|
+
include Unshareable
|
|
27
|
+
|
|
28
|
+
private def internal_atom_class = Internal::UnsharedWeakAtom
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe map with weak keys for use within one Ractor.
|
|
8
|
+
#
|
|
9
|
+
# @example Associating data with a mutable object
|
|
10
|
+
# owner = Object.new
|
|
11
|
+
# map = Farce::Unshared::WeakKeyMap.new
|
|
12
|
+
# map[owner] = []
|
|
13
|
+
# map[owner] << :job
|
|
14
|
+
#
|
|
15
|
+
# # The entry can disappear once its key is collected.
|
|
16
|
+
# owner = nil
|
|
17
|
+
class WeakKeyMap < Abstract::WeakKeyMap
|
|
18
|
+
include Unshareable
|
|
19
|
+
|
|
20
|
+
def initialize(
|
|
21
|
+
initial_mapping = nil,
|
|
22
|
+
normalize_keys: nil,
|
|
23
|
+
compare_by_identity: false,
|
|
24
|
+
compare_keys_by_identity: compare_by_identity,
|
|
25
|
+
compare_values_by_identity: compare_by_identity
|
|
26
|
+
)
|
|
27
|
+
initial_mapping = convert_entries(initial_mapping)
|
|
28
|
+
restoring = Internal::KeyNormalizer.restoration?(normalize_keys)
|
|
29
|
+
normalizer = Internal::KeyNormalizer.build(normalize_keys, shareable: false)
|
|
30
|
+
populate = initial_mapping && ((normalizer && !restoring) || !initial_mapping.is_a?(Hash))
|
|
31
|
+
@map = Internal::UnsharedWeakKeyMap.new(
|
|
32
|
+
populate ? nil : initial_mapping,
|
|
33
|
+
compare_by_identity:,
|
|
34
|
+
compare_keys_by_identity:,
|
|
35
|
+
compare_values_by_identity:,
|
|
36
|
+
)
|
|
37
|
+
Internal::KeyNormalizer.install_concurrent(self, normalizer) unless restoring
|
|
38
|
+
initial_mapping.each { |key, value| self[key] = value } if populate
|
|
39
|
+
Internal::KeyNormalizer.install_concurrent(self, normalizer) if restoring
|
|
40
|
+
super()
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Unshared
|
|
7
|
+
# A thread-safe map with weak keys and values for use within one Ractor.
|
|
8
|
+
#
|
|
9
|
+
# @example Keeping a relationship while both mutable objects remain alive
|
|
10
|
+
# key = Object.new
|
|
11
|
+
# value = Object.new
|
|
12
|
+
# map = Farce::Unshared::WeakMap.new({ key => value })
|
|
13
|
+
# map[key].equal?(value) # => true
|
|
14
|
+
#
|
|
15
|
+
# # The entry can disappear once its key or value is collected
|
|
16
|
+
# value = nil
|
|
17
|
+
class WeakMap < Abstract::WeakMap
|
|
18
|
+
include Unshareable
|
|
19
|
+
|
|
20
|
+
def initialize(
|
|
21
|
+
initial_mapping = nil,
|
|
22
|
+
normalize_keys: nil,
|
|
23
|
+
compare_by_identity: false,
|
|
24
|
+
compare_keys_by_identity: compare_by_identity,
|
|
25
|
+
compare_values_by_identity: compare_by_identity
|
|
26
|
+
)
|
|
27
|
+
initial_mapping = convert_entries(initial_mapping)
|
|
28
|
+
restoring = Internal::KeyNormalizer.restoration?(normalize_keys)
|
|
29
|
+
normalizer = Internal::KeyNormalizer.build(normalize_keys, shareable: false)
|
|
30
|
+
populate = initial_mapping && ((normalizer && !restoring) || !initial_mapping.is_a?(Hash))
|
|
31
|
+
@map = Internal::UnsharedWeakMap.new(
|
|
32
|
+
populate ? nil : initial_mapping,
|
|
33
|
+
compare_by_identity:,
|
|
34
|
+
compare_keys_by_identity:,
|
|
35
|
+
compare_values_by_identity:,
|
|
36
|
+
)
|
|
37
|
+
Internal::KeyNormalizer.install_concurrent(self, normalizer) unless restoring
|
|
38
|
+
initial_mapping.each { |key, value| self[key] = value } if populate
|
|
39
|
+
Internal::KeyNormalizer.install_concurrent(self, normalizer) if restoring
|
|
40
|
+
super()
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|