farce 0.0.1.alpha2-x86-linux-musl
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
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Strict
|
|
7
|
+
# A priority queue that stores and returns values directly.
|
|
8
|
+
class PriorityQueue < Abstract::PriorityQueue
|
|
9
|
+
include Internal::StrictQueueValues unless Internal.native_ractors?
|
|
10
|
+
include Shareable::Unfreezable
|
|
11
|
+
|
|
12
|
+
def initialize(capacity: nil, default_priority: 0, order: :ascending, track_age: false)
|
|
13
|
+
unless Ractor.shareable?(default_priority)
|
|
14
|
+
raise Ractor::IsolationError, "default priority is not Ractor-shareable"
|
|
15
|
+
end
|
|
16
|
+
super
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Strict
|
|
7
|
+
# A FIFO queue that stores and returns values directly.
|
|
8
|
+
class Queue < Abstract::Queue
|
|
9
|
+
include Shareable::Unfreezable
|
|
10
|
+
|
|
11
|
+
def initialize(capacity: 1024, track_age: false)
|
|
12
|
+
@queue = Internal::Queue.new(capacity:, track_age:)
|
|
13
|
+
super()
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
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 Strict
|
|
7
|
+
# A Ractor-shareable concurrent set of shareable elements.
|
|
8
|
+
class Set < Farce::Abstract::Set
|
|
9
|
+
include Shareable::Delegated
|
|
10
|
+
|
|
11
|
+
private def new_map(...) = Farce::Strict::Map.new(...)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
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 Strict
|
|
7
|
+
# A Ractor-shareable concurrent set maintained in ascending order.
|
|
8
|
+
class SortedSet < Farce::Abstract::SortedSet
|
|
9
|
+
include Shareable::Delegated
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def new_map(entries = nil, compare_keys_by_identity: false, **)
|
|
14
|
+
raise ArgumentError, "sorted sets do not support identity comparison" if compare_keys_by_identity
|
|
15
|
+
Farce::Strict::TreeMap.new(entries)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Strict
|
|
7
|
+
# A timer queue that stores and returns values directly.
|
|
8
|
+
class TimerQueue < Abstract::TimerQueue
|
|
9
|
+
include Internal::StrictQueueValues unless Internal.native_ractors?
|
|
10
|
+
include Shareable::Unfreezable
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
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 Strict
|
|
7
|
+
# A Ractor-shareable map that keeps shareable entries sorted by key.
|
|
8
|
+
# Mutable string keys become immutable. Other keys and all values must already be Ractor-shareable.
|
|
9
|
+
#
|
|
10
|
+
# @example Keeping direct values in key order
|
|
11
|
+
# map = Farce::Strict::TreeMap.new(2 => "two".freeze, 1 => "one".freeze)
|
|
12
|
+
#
|
|
13
|
+
# map.to_a # => [[1, "one"], [2, "two"]]
|
|
14
|
+
class TreeMap < Abstract::TreeMap
|
|
15
|
+
include Shareable::Delegated
|
|
16
|
+
|
|
17
|
+
# Values must already be Ractor-shareable.
|
|
18
|
+
# @return [true]
|
|
19
|
+
def shareable_values? = true
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def new_tree_map(...) = Internal::StrictTreeMap.new(...)
|
|
24
|
+
def freeze_backend = internal_map
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
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 Strict
|
|
7
|
+
# A Ractor-shareable vector that stores and returns shareable values directly.
|
|
8
|
+
class Vector < Abstract::Vector
|
|
9
|
+
include Shareable::Delegated
|
|
10
|
+
|
|
11
|
+
# @param source [Array, nil] Initial values. The source array is not retained.
|
|
12
|
+
# @param compare_by_identity [Boolean] Whether values are compared by identity.
|
|
13
|
+
def initialize(source = nil, compare_by_identity: false)
|
|
14
|
+
@vector = Internal::Vector.new(source, compare_by_identity:)
|
|
15
|
+
super()
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# (see Farce::Abstract::Vector#shareable_values?)
|
|
19
|
+
def shareable_values? = true
|
|
20
|
+
|
|
21
|
+
private def freeze_backend = @vector
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
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 Strict
|
|
7
|
+
# A Ractor-shareable weak atomic reference that stores shareable values directly.
|
|
8
|
+
#
|
|
9
|
+
# @example Referencing a shareable object without keeping it alive
|
|
10
|
+
# resource = Object.new.freeze
|
|
11
|
+
# atom = Farce::Strict::WeakAtom.new(resource, compare_by_identity: true)
|
|
12
|
+
# atom.value.equal?(resource) # => true
|
|
13
|
+
#
|
|
14
|
+
# resource = nil
|
|
15
|
+
# # Once the object is collected, atom.value returns nil.
|
|
16
|
+
#
|
|
17
|
+
# @example Lazily storing a shareable value
|
|
18
|
+
# atom = Farce::Strict::WeakAtom.new
|
|
19
|
+
# value = atom.store_if_absent { [1, 2, 3].freeze }
|
|
20
|
+
# atom.value.equal?(value) # => true
|
|
21
|
+
# # Keeping value referenced also keeps the atom's referent alive.
|
|
22
|
+
class WeakAtom < Abstract::WeakAtom
|
|
23
|
+
include Shareable::Delegated
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def internal_atom_class = Internal::WeakAtom
|
|
28
|
+
def freeze_backend = @atom
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
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 Strict
|
|
7
|
+
# A Ractor-shareable concurrent map with weak shareable keys and strong shareable values.
|
|
8
|
+
#
|
|
9
|
+
# @example Associating metadata without retaining its owner
|
|
10
|
+
# owner = Object.new.freeze
|
|
11
|
+
# map = Farce::Strict::WeakKeyMap.new
|
|
12
|
+
# map[owner] = :active
|
|
13
|
+
# map[owner] # => :active
|
|
14
|
+
#
|
|
15
|
+
# # The entry can disappear once its key is collected.
|
|
16
|
+
# owner = nil
|
|
17
|
+
class WeakKeyMap < Abstract::WeakKeyMap
|
|
18
|
+
include Shareable::Delegated
|
|
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: true)
|
|
30
|
+
populate = initial_mapping && ((normalizer && !restoring) || !initial_mapping.is_a?(Hash))
|
|
31
|
+
@map = Internal::StrictWeakKeyMap.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
|
+
|
|
43
|
+
def shareable_keys? = true
|
|
44
|
+
def shareable_values? = true
|
|
45
|
+
|
|
46
|
+
private def freeze_backend = internal_map
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
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 Strict
|
|
7
|
+
# A Ractor-shareable concurrent map that retains shareable keys and values weakly.
|
|
8
|
+
#
|
|
9
|
+
# @example Keeping a relationship while both objects remain alive
|
|
10
|
+
# key = Object.new.freeze
|
|
11
|
+
# value = Object.new.freeze
|
|
12
|
+
# map = Farce::Strict::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 Shareable::Delegated
|
|
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: true)
|
|
30
|
+
populate = initial_mapping && ((normalizer && !restoring) || !initial_mapping.is_a?(Hash))
|
|
31
|
+
@map = Internal::StrictWeakMap.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
|
+
|
|
43
|
+
def shareable_keys? = true
|
|
44
|
+
def shareable_values? = true
|
|
45
|
+
|
|
46
|
+
private def freeze_backend = internal_map
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
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 Strict
|
|
7
|
+
# A Ractor-shareable concurrent set that retains shareable elements weakly.
|
|
8
|
+
class WeakSet < Farce::Abstract::WeakSet
|
|
9
|
+
include Shareable::Delegated
|
|
10
|
+
|
|
11
|
+
private def new_map(...) = Farce::Strict::WeakMap.new(...)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Strict
|
|
7
|
+
# A Ractor-shareable concurrent map with strong shareable keys and weak shareable values.
|
|
8
|
+
#
|
|
9
|
+
# @example Caching a value without keeping it alive
|
|
10
|
+
# value = Object.new.freeze
|
|
11
|
+
# map = Farce::Strict::WeakValueMap.new({ result: value })
|
|
12
|
+
# map[:result].equal?(value) # => true
|
|
13
|
+
#
|
|
14
|
+
# # The entry can disappear once its value is collected.
|
|
15
|
+
# value = nil
|
|
16
|
+
class WeakValueMap < Abstract::WeakValueMap
|
|
17
|
+
include Shareable::Delegated
|
|
18
|
+
|
|
19
|
+
def initialize(
|
|
20
|
+
initial_mapping = nil,
|
|
21
|
+
normalize_keys: nil,
|
|
22
|
+
compare_by_identity: false,
|
|
23
|
+
compare_keys_by_identity: compare_by_identity,
|
|
24
|
+
compare_values_by_identity: compare_by_identity
|
|
25
|
+
)
|
|
26
|
+
initial_mapping = convert_entries(initial_mapping)
|
|
27
|
+
restoring = Internal::KeyNormalizer.restoration?(normalize_keys)
|
|
28
|
+
normalizer = Internal::KeyNormalizer.build(normalize_keys, shareable: true)
|
|
29
|
+
populate = initial_mapping && ((normalizer && !restoring) || !initial_mapping.is_a?(Hash))
|
|
30
|
+
@map = Internal::StrictWeakValueMap.new(
|
|
31
|
+
populate ? nil : initial_mapping,
|
|
32
|
+
compare_by_identity:,
|
|
33
|
+
compare_keys_by_identity:,
|
|
34
|
+
compare_values_by_identity:,
|
|
35
|
+
)
|
|
36
|
+
Internal::KeyNormalizer.install_concurrent(self, normalizer) unless restoring
|
|
37
|
+
initial_mapping.each { |key, value| self[key] = value } if populate
|
|
38
|
+
Internal::KeyNormalizer.install_concurrent(self, normalizer) if restoring
|
|
39
|
+
super()
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def shareable_keys? = true
|
|
43
|
+
def shareable_values? = true
|
|
44
|
+
|
|
45
|
+
private def freeze_backend = internal_map
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/farce/strict.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# Shareable containers that store shareable values directly.
|
|
7
|
+
module Strict
|
|
8
|
+
include Internal::Autoloads
|
|
9
|
+
|
|
10
|
+
# @overload enfarce(object, freeze: nil)
|
|
11
|
+
# Converts vanilla Ruby objects into their {Farce::Strict} equivalents.
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# Farce::Strict.enfarce({ foo: ["bar"] }) { Ractor.make_shareable(it) }
|
|
15
|
+
# # => #<Farce::Strict::Map {foo: #<Farce::Strict::Vector ["bar"]>}>
|
|
16
|
+
#
|
|
17
|
+
# @yield [object] Optional block, called with any object that doesn't have a specific conversion defined.
|
|
18
|
+
# @yieldparam object [BasicObject] the object to convert
|
|
19
|
+
# @yieldreturn [BasicObject] the converted object
|
|
20
|
+
# @param object [BasicObject] The root object to convert
|
|
21
|
+
# @param freeze [Boolean, nil]
|
|
22
|
+
# Whether to freeze the converted objects.
|
|
23
|
+
# If set to `nil` (default), the freezing behavior will depend on the original object's frozen state.
|
|
24
|
+
# @return [BasicObject] the converted object
|
|
25
|
+
# @see Farce.enfarce
|
|
26
|
+
def self.enfarce(object, **, &) = Internal::Converter.new(self, **, &).convert(object)
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/farce/system.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
require "etc"
|
|
6
|
+
|
|
7
|
+
module Farce
|
|
8
|
+
# Information about the system running Farce.
|
|
9
|
+
module System
|
|
10
|
+
WINDOWS = Gem.win_platform?
|
|
11
|
+
private_constant :WINDOWS
|
|
12
|
+
|
|
13
|
+
# Whether the current operating system is Windows.
|
|
14
|
+
# Safe to call from any Ractor.
|
|
15
|
+
# @return [Boolean]
|
|
16
|
+
def self.windows? = WINDOWS
|
|
17
|
+
|
|
18
|
+
# Number of logical CPUs, optionally limited to a CPU type.
|
|
19
|
+
# Returns nil when the platform cannot report the requested CPU type.
|
|
20
|
+
# Safe to call from any Ractor.
|
|
21
|
+
# @param type [nil, Symbol] nil for all CPUs, :performance, or :efficiency
|
|
22
|
+
# @return [Integer, nil]
|
|
23
|
+
# @raise [ArgumentError] if the CPU type is invalid
|
|
24
|
+
def self.cpu_count(type = nil)
|
|
25
|
+
case type
|
|
26
|
+
when nil
|
|
27
|
+
if defined?(Internal::Darwin) && Internal::Darwin.respond_to?(:cpu_count)
|
|
28
|
+
Internal::Darwin.cpu_count
|
|
29
|
+
else
|
|
30
|
+
Etc.nprocessors
|
|
31
|
+
end
|
|
32
|
+
when :performance, :efficiency
|
|
33
|
+
method = :"#{type}_cpu_count"
|
|
34
|
+
Internal::Darwin.public_send(method) if defined?(Internal::Darwin) && Internal::Darwin.respond_to?(method)
|
|
35
|
+
else
|
|
36
|
+
raise ArgumentError, "invalid CPU type: #{type.inspect}"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# A scheduler that starts a new thread for each scheduled task. Executes synchronous tasks inline.
|
|
7
|
+
# Creating an instance starts no threads. Blocks and arguments stay local to the caller.
|
|
8
|
+
# Tasks are not tracked, and closing this stateless scheduler has no effect.
|
|
9
|
+
# Default instances support Marshal. Instances with a custom thread factory reject dumping.
|
|
10
|
+
class ThreadScheduler < Farce::Abstract::Scheduler
|
|
11
|
+
include Shareable::Immutable
|
|
12
|
+
include Internal::Inspect
|
|
13
|
+
|
|
14
|
+
def initialize(&factory)
|
|
15
|
+
@factory = factory
|
|
16
|
+
super()
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @api private
|
|
20
|
+
def marshal_dump
|
|
21
|
+
raise TypeError, "scheduler factories cannot be marshaled" if @factory
|
|
22
|
+
[1]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @api private
|
|
26
|
+
def marshal_load(data)
|
|
27
|
+
Internal::MarshalSupport.payload(data, 0)
|
|
28
|
+
initialize
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Starts a thread in the caller's Ractor, preserving the block and arguments.
|
|
32
|
+
#
|
|
33
|
+
# @overload schedule(*args, **options)
|
|
34
|
+
# @param args [Array<Object>] Arguments passed to the block.
|
|
35
|
+
# @param options [Hash] Scheduler options are ignored. All tasks use local arguments.
|
|
36
|
+
# @yield [*args] The task to run.
|
|
37
|
+
# @return [self]
|
|
38
|
+
def schedule(*, **, &)
|
|
39
|
+
raise LocalJumpError, "Cannot schedule without a block" unless block_given?
|
|
40
|
+
@factory ? @factory.call(*, &) : Thread.new(*, &)
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Runs the block on the caller's thread and fiber. Exceptions propagate to the caller.
|
|
45
|
+
#
|
|
46
|
+
# @overload execute(*args, **options)
|
|
47
|
+
# @param args [Array<Object>] Arguments passed to the block.
|
|
48
|
+
# @param options [Hash] Scheduler options are ignored. All tasks use local arguments.
|
|
49
|
+
# @yield [*args] The task to run.
|
|
50
|
+
# @return [self]
|
|
51
|
+
def execute(*, **)
|
|
52
|
+
raise LocalJumpError, "Cannot yield without a block" unless block_given?
|
|
53
|
+
yield(*)
|
|
54
|
+
self
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @return [self] Does not wait for or stop task threads.
|
|
58
|
+
def close = self
|
|
59
|
+
|
|
60
|
+
# @return [false] This stateless scheduler is always available.
|
|
61
|
+
def closed? = false
|
|
62
|
+
|
|
63
|
+
# @return [Symbol] Always `:running`.
|
|
64
|
+
def state = :running
|
|
65
|
+
|
|
66
|
+
# @param wait [Boolean] Ignored because tasks always run in the caller's Ractor.
|
|
67
|
+
# @return [true]
|
|
68
|
+
def local?(wait: true) = true # rubocop:disable Lint/UnusedMethodArgument
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# A shareable timer queue with transfer modes for unshareable values.
|
|
7
|
+
class TimerQueue < Abstract::TimerQueue
|
|
8
|
+
include Internal::ManagedQueue
|
|
9
|
+
include Shareable::Unfreezable
|
|
10
|
+
|
|
11
|
+
# (see Farce::Abstract::TimerQueue#initialize)
|
|
12
|
+
# @!macro modes
|
|
13
|
+
# @param mode [Symbol] the transfer mode for unshareable values
|
|
14
|
+
def initialize(capacity: nil, mode: :copy, track_age: false)
|
|
15
|
+
@manager = ModeManager.new(mode:)
|
|
16
|
+
super(capacity:, track_age:)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# (see Farce::Abstract::TimerQueue#push)
|
|
20
|
+
# @!macro modes
|
|
21
|
+
# @param mode [Symbol] the transfer mode for unshareable values
|
|
22
|
+
def push(value, non_block = false, mode: nil, timeout: nil, **time_options) # rubocop:disable Style/OptionalBooleanParameter
|
|
23
|
+
at = Clock.parse(time_options)
|
|
24
|
+
push_to_storage(at, non_block, @manager.wrap(value, mode:), timeout:)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# (see Farce::Abstract::TimerQueue#try_push)
|
|
28
|
+
# @!macro modes
|
|
29
|
+
# @param mode [Symbol] the transfer mode for unshareable values
|
|
30
|
+
def try_push(value, mode: nil, **time_options)
|
|
31
|
+
at = Clock.parse(time_options)
|
|
32
|
+
return true if @queue.push(at, @manager.wrap(value, mode:))
|
|
33
|
+
block_given? ? yield : false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# (see Farce::Abstract::TimerQueue#pop)
|
|
37
|
+
def pop(non_block = false, timeout: nil) # rubocop:disable Style/OptionalBooleanParameter
|
|
38
|
+
return try_pop { raise ThreadError, "queue empty" } if non_block
|
|
39
|
+
deadline = timeout_at(timeout) unless timeout.nil?
|
|
40
|
+
|
|
41
|
+
while true
|
|
42
|
+
empty = false
|
|
43
|
+
value = @queue.pop_before(Clock.now) { empty = true }
|
|
44
|
+
return @manager.unwrap(value) unless empty
|
|
45
|
+
return block_given? ? yield : nil if UNDEFINED.equal?(wait_for_timestamp(deadline))
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# (see Farce::Abstract::TimerQueue#try_pop)
|
|
50
|
+
def try_pop
|
|
51
|
+
empty = false
|
|
52
|
+
value = @queue.pop_before(Clock.now) { empty = true }
|
|
53
|
+
return @manager.unwrap(value) unless empty
|
|
54
|
+
yield if block_given?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# (see Farce::Abstract::TimerQueue#peek)
|
|
58
|
+
# @note Peeking at a moved value claims it for this Ractor while leaving it queued.
|
|
59
|
+
def peek
|
|
60
|
+
empty = false
|
|
61
|
+
value = @queue.peek { empty = true }
|
|
62
|
+
return @manager.unwrap(value) unless empty
|
|
63
|
+
yield if block_given?
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# An {Abstract::Atom Atom} that is part of a transaction.
|
|
8
|
+
class Atom < Abstract::Atom
|
|
9
|
+
include Wrapper
|
|
10
|
+
|
|
11
|
+
# (see Abstract::Atom#compare_by_identity?)
|
|
12
|
+
# @see Abstract::Atom#compare_by_identity?
|
|
13
|
+
def compare_by_identity? = access { @object.compare_by_identity? }
|
|
14
|
+
|
|
15
|
+
# (see Abstract::Atom#value)
|
|
16
|
+
# @see Abstract::Atom#value
|
|
17
|
+
def value = access { unwrap_stored(@working.value) }
|
|
18
|
+
alias get value
|
|
19
|
+
|
|
20
|
+
# (see Abstract::Atom#value=)
|
|
21
|
+
# @see Abstract::Atom#value=
|
|
22
|
+
def value=(value)
|
|
23
|
+
store(value)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# (see Abstract::Atom#store)
|
|
27
|
+
# @see Abstract::Atom#store
|
|
28
|
+
def store(value, mode: nil)
|
|
29
|
+
write { unwrap_stored(@working.store(wrap(value, mode:))) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# (see Abstract::Atom#swap)
|
|
33
|
+
# @see Abstract::Atom#swap
|
|
34
|
+
def swap(value, mode: nil)
|
|
35
|
+
write { unwrap_stored(@working.swap(wrap(value, mode:))) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# (see Abstract::Atom#update)
|
|
39
|
+
# @see Abstract::Atom#update
|
|
40
|
+
def update(mode: nil)
|
|
41
|
+
require_block!(block_given?)
|
|
42
|
+
write { unwrap_stored(@working.store(wrap(yield(unwrap_stored(@working.value)), mode:))) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# (see Abstract::Atom#store_if_absent)
|
|
46
|
+
# @see Abstract::Atom#store_if_absent
|
|
47
|
+
def store_if_absent(mode: nil)
|
|
48
|
+
require_block!(block_given?)
|
|
49
|
+
write { value.nil? ? store(yield, mode:) : value }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# (see Abstract::Atom#upsert)
|
|
53
|
+
# @see Abstract::Atom#upsert
|
|
54
|
+
def upsert(initial, mode: nil)
|
|
55
|
+
require_block!(block_given?)
|
|
56
|
+
write { store(value.nil? ? initial : yield(value), mode:) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# (see Abstract::Atom#compare_and_set)
|
|
60
|
+
# @see Abstract::Atom#compare_and_set
|
|
61
|
+
def compare_and_set(expected, replacement, mode: nil)
|
|
62
|
+
write do
|
|
63
|
+
next compared(@working.compare_and_set(expected, replacement)) unless @manager
|
|
64
|
+
next compared(false) unless matches?(@working.value, expected, identity: @object.compare_by_identity?)
|
|
65
|
+
@working.store(wrap(replacement, mode:))
|
|
66
|
+
true
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
Wrapper.inherit(self, :compare_by_identity?, :unwrap)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# A {Abstract::ConcurrentMap ConcurrentMap} that is part of a transaction.
|
|
8
|
+
#
|
|
9
|
+
# Reads and writes validate the keys they access, allowing concurrent changes
|
|
10
|
+
# to other keys. Size reads validate cardinality without observing contents.
|
|
11
|
+
# Enumeration, keys, getkey, and clear capture and validate the full map.
|
|
12
|
+
# Staged changes are visible through this wrapper and publish only on commit.
|
|
13
|
+
# Key validation compares current values by identity, not per-key write history.
|
|
14
|
+
# Commit captures a full snapshot for maps accessed by key. Changes after
|
|
15
|
+
# that snapshot is captured can still cause the attempt to fail.
|
|
16
|
+
class Map < Abstract::ConcurrentMap
|
|
17
|
+
include MapOperations
|
|
18
|
+
|
|
19
|
+
Wrapper.inherit(self, *MapOperations::READ_HELPERS, :delete_if, :reject!, :compact!, :keep_if,
|
|
20
|
+
:select!, :filter!, :transform_values!, :merge!)
|
|
21
|
+
|
|
22
|
+
private def enlist(backend) = @transaction.enlist(backend, per_key: true)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|