farce 0.0.1.alpha2-x64-mingw-ucrt
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,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# Implements the staged reads and writes shared by Map and TreeMap wrappers.
|
|
8
|
+
#
|
|
9
|
+
# The participant supplies key normalization and value transfer rules.
|
|
10
|
+
# Operations use the backend snapshot enrolled in the transaction, so they
|
|
11
|
+
# see earlier staged writes without modifying the participant before commit.
|
|
12
|
+
#
|
|
13
|
+
# @!visibility private
|
|
14
|
+
module MapOperations # :nodoc: all
|
|
15
|
+
include Wrapper
|
|
16
|
+
|
|
17
|
+
READ_HELPERS = %i[
|
|
18
|
+
assoc compare_by_identity? dig length value? has_value? key rassoc has_key? member? include?
|
|
19
|
+
fetch_values to_a to_h to_hash deconstruct_keys values_at weak_keys? weak_values? inspect to_s
|
|
20
|
+
pretty_print values flatten to_proc
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
def [](key) = access { unwrap_stored(@working[prepare(key)]) }
|
|
24
|
+
|
|
25
|
+
def []=(key, value)
|
|
26
|
+
store(key, value)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def fetch(key, *defaults)
|
|
30
|
+
access do
|
|
31
|
+
raise ArgumentError, "expected at most one default" if defaults.size > 1
|
|
32
|
+
canonical = prepare(key)
|
|
33
|
+
next unwrap_stored(@working[canonical]) if @working.key?(canonical)
|
|
34
|
+
next yield(key) if block_given?
|
|
35
|
+
next defaults.first unless defaults.empty?
|
|
36
|
+
raise KeyError.new("key not found: #{key.inspect}", receiver: @object, key:)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def compare_keys_by_identity? = access { @object.compare_keys_by_identity? }
|
|
41
|
+
def compare_values_by_identity? = access { @object.compare_values_by_identity? }
|
|
42
|
+
def delete(key) = write { unwrap_stored(@working.delete(prepare(key))) }
|
|
43
|
+
def empty? = size.zero?
|
|
44
|
+
def get(key) = self[key]
|
|
45
|
+
def getkey(key) = access { @working.getkey(prepare(key)) }
|
|
46
|
+
def key?(key) = access { @working.key?(prepare(key)) }
|
|
47
|
+
def keys = access { @working.keys }
|
|
48
|
+
def shareable_keys? = access { @object.shareable_keys? }
|
|
49
|
+
def shareable_values? = access { @object.shareable_values? }
|
|
50
|
+
def size = access { @working.size }
|
|
51
|
+
def store(key, value, mode: nil) = write { unwrap_stored(store_value(prepare(key), wrap(value, mode:))) }
|
|
52
|
+
def swap(key, value, mode: nil) = write { unwrap_stored(@working.swap(prepare(key), wrap(value, mode:))) }
|
|
53
|
+
|
|
54
|
+
def each
|
|
55
|
+
return enum_for(__method__) unless block_given?
|
|
56
|
+
access { @working.each { |key, value| yield key, unwrap_stored(value) } }
|
|
57
|
+
self
|
|
58
|
+
end
|
|
59
|
+
alias each_pair each
|
|
60
|
+
alias each_live each
|
|
61
|
+
|
|
62
|
+
def clear
|
|
63
|
+
write { @working.clear }
|
|
64
|
+
self
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def update(key, mode: nil)
|
|
68
|
+
require_block!(block_given?)
|
|
69
|
+
write do
|
|
70
|
+
canonical = prepare(key)
|
|
71
|
+
unwrap_stored(store_value(canonical, wrap(yield(unwrap_stored(@working[canonical])), mode:)))
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def store_if_absent(key, mode: nil)
|
|
76
|
+
require_block!(block_given?)
|
|
77
|
+
write do
|
|
78
|
+
canonical = prepare(key)
|
|
79
|
+
next unwrap_stored(@working[canonical]) if @working.key?(canonical)
|
|
80
|
+
unwrap_stored(store_value(canonical, wrap(yield, mode:)))
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def upsert(key, initial, mode: nil)
|
|
85
|
+
require_block!(block_given?)
|
|
86
|
+
write do
|
|
87
|
+
canonical = prepare(key)
|
|
88
|
+
value = @working.key?(canonical) ? yield(unwrap_stored(@working[canonical])) : initial
|
|
89
|
+
unwrap_stored(store_value(canonical, wrap(value, mode:)))
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def compare_and_set(key, expected, replacement, mode: nil)
|
|
94
|
+
write do
|
|
95
|
+
canonical = prepare(key)
|
|
96
|
+
next compared(@working.compare_and_set(canonical, expected, replacement)) unless @manager
|
|
97
|
+
next compared(false) unless @working.key?(canonical) &&
|
|
98
|
+
matches?(@working[canonical], expected, identity: @object.compare_values_by_identity?)
|
|
99
|
+
store_value(canonical, wrap(replacement, mode:))
|
|
100
|
+
true
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def each_key
|
|
105
|
+
return enum_for(__method__) { size } unless block_given?
|
|
106
|
+
each { |key, _| yield key }
|
|
107
|
+
self
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def each_value
|
|
111
|
+
return enum_for(__method__) { size } unless block_given?
|
|
112
|
+
each { |_, value| yield value }
|
|
113
|
+
self
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
private
|
|
117
|
+
|
|
118
|
+
def store_value(key, value) = @working.store(key, value)
|
|
119
|
+
|
|
120
|
+
def modify_entry(key, canonical: false)
|
|
121
|
+
write do
|
|
122
|
+
key = prepare(key) unless canonical
|
|
123
|
+
present = @working.key?(key)
|
|
124
|
+
replacement = yield(present, present ? unwrap_stored(@working[key]) : nil)
|
|
125
|
+
next false if Internal::MAP_KEEP.equal?(replacement)
|
|
126
|
+
if Internal::MAP_DELETE.equal?(replacement)
|
|
127
|
+
@working.delete(key)
|
|
128
|
+
present
|
|
129
|
+
else
|
|
130
|
+
store_value(key, wrap(replacement))
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def prepare(key)
|
|
136
|
+
return @backend.transaction_key(key) if @backend.respond_to?(:transaction_key)
|
|
137
|
+
@backend.respond_to?(:normalize_external_key) ? @backend.normalize_external_key(key) : key
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private_constant :MapOperations
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# A {Abstract::Molecule Molecule} that is part of a transaction.
|
|
8
|
+
class Molecule < Abstract::Molecule
|
|
9
|
+
include Wrapper
|
|
10
|
+
|
|
11
|
+
# @api private
|
|
12
|
+
def initialize(transaction, object)
|
|
13
|
+
super
|
|
14
|
+
@members = object.members
|
|
15
|
+
@atoms = object.each_atom.to_h.transform_values { transaction[it] }
|
|
16
|
+
@fields = @members.to_h { [it, @atoms.fetch(:"#{it}_atom")] }
|
|
17
|
+
@writers = @members.to_h { [:"#{it}=", @atoms.fetch(:"#{it}_atom")] }
|
|
18
|
+
# A field named map or count must read its atom, not call the inherited
|
|
19
|
+
# Enumerable method. Define those readers before method_missing is needed.
|
|
20
|
+
@members.each do |field|
|
|
21
|
+
next unless Enumerable.method_defined?(field)
|
|
22
|
+
atom = @fields.fetch(field)
|
|
23
|
+
define_singleton_method(field) { access { atom.value } }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# (see Abstract::Molecule#compare_by_identity?)
|
|
28
|
+
# @see Abstract::Molecule#compare_by_identity?
|
|
29
|
+
def compare_by_identity? = access { @object.compare_by_identity? }
|
|
30
|
+
|
|
31
|
+
# (see Abstract::Molecule#members)
|
|
32
|
+
# @see Abstract::Molecule#members
|
|
33
|
+
def members = access { @members }
|
|
34
|
+
|
|
35
|
+
# (see Abstract::Molecule#atoms)
|
|
36
|
+
# @see Abstract::Molecule#atoms
|
|
37
|
+
def atoms = access { @atoms.keys.freeze }
|
|
38
|
+
|
|
39
|
+
# (see Abstract::Molecule#each)
|
|
40
|
+
# @see Abstract::Molecule#each
|
|
41
|
+
def each
|
|
42
|
+
return enum_for(__method__) unless block_given?
|
|
43
|
+
access { @members.each { yield it, @atoms.fetch(:"#{it}_atom").value } }
|
|
44
|
+
self
|
|
45
|
+
end
|
|
46
|
+
alias each_pair each
|
|
47
|
+
|
|
48
|
+
# (see Abstract::Molecule#each_atom)
|
|
49
|
+
# @see Abstract::Molecule#each_atom
|
|
50
|
+
def each_atom
|
|
51
|
+
return enum_for(__method__) unless block_given?
|
|
52
|
+
access { @atoms.each { yield _1, _2 } }
|
|
53
|
+
self
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# (see Abstract::Molecule#each_member)
|
|
57
|
+
# @see Abstract::Molecule#each_member
|
|
58
|
+
def each_member
|
|
59
|
+
return enum_for(__method__) unless block_given?
|
|
60
|
+
access { @members.each { yield it } }
|
|
61
|
+
self
|
|
62
|
+
end
|
|
63
|
+
alias each_key each_member
|
|
64
|
+
|
|
65
|
+
# (see Abstract::Molecule#each_value)
|
|
66
|
+
# @see Abstract::Molecule#each_value
|
|
67
|
+
def each_value
|
|
68
|
+
return enum_for(__method__) unless block_given?
|
|
69
|
+
each { |_, value| yield value }
|
|
70
|
+
self
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def method_missing(name, *arguments, **options, &block)
|
|
76
|
+
return access { @atoms.fetch(name) } if @atoms.key?(name) && arguments.empty? && options.empty? && !block
|
|
77
|
+
return super unless options.empty? && !block
|
|
78
|
+
return access { @fields.fetch(name).value } if @fields.key?(name) && arguments.empty?
|
|
79
|
+
return write { @writers.fetch(name).value = arguments.first } if @writers.key?(name) && arguments.size == 1
|
|
80
|
+
super
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def respond_to_missing?(name, include_private = false)
|
|
84
|
+
@atoms.key?(name) || @fields.key?(name) || @writers.key?(name) || super
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
Wrapper.inherit(self, :compare_by_identity?)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# A {Farce::Mutable} that stages method calls within a transaction.
|
|
8
|
+
#
|
|
9
|
+
# Reads use the attempt's current snapshot. Mutations replace only its staged
|
|
10
|
+
# value and are published with the other participants when the attempt commits.
|
|
11
|
+
# Snapshots must be frozen. Use a dedicated transaction participant for a
|
|
12
|
+
# shareable object whose state can change while it remains unfrozen.
|
|
13
|
+
class Mutable < Farce::Mutable
|
|
14
|
+
include Wrapper
|
|
15
|
+
|
|
16
|
+
# @api private
|
|
17
|
+
def initialize(transaction, object, backend)
|
|
18
|
+
super
|
|
19
|
+
@atom = Atom.new(transaction, object, backend)
|
|
20
|
+
return if @atom.value.frozen?
|
|
21
|
+
::Kernel.raise(::TypeError, "mutable transactions require a frozen snapshot")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @api private
|
|
25
|
+
def marshal_dump = ::Kernel.raise(::TypeError, "transaction wrappers cannot be marshaled")
|
|
26
|
+
|
|
27
|
+
# @api private
|
|
28
|
+
def respond_to?(name, include_private = false) # rubocop:disable Style/OptionalBooleanParameter
|
|
29
|
+
access { name != :freeze && super }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @api private
|
|
33
|
+
def frozen? = access { @object.frozen? }
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
# Wrapper's error guards must raise locally rather than delegate to the value.
|
|
38
|
+
def raise(...) = ::Kernel.raise(...)
|
|
39
|
+
|
|
40
|
+
def method_missing(name, ...) # rubocop:disable Style/MissingRespondToMissing
|
|
41
|
+
access do
|
|
42
|
+
::Kernel.raise(::NoMethodError, "transaction wrappers cannot be frozen") if name == :freeze
|
|
43
|
+
begin
|
|
44
|
+
@atom.value.__send__(name, ...)
|
|
45
|
+
rescue ::FrozenError
|
|
46
|
+
result = nil
|
|
47
|
+
@atom.update do |current|
|
|
48
|
+
copy = current.dup
|
|
49
|
+
result = copy.__send__(name, ...)
|
|
50
|
+
result = self if result.equal?(copy)
|
|
51
|
+
copy.freeze
|
|
52
|
+
end
|
|
53
|
+
result
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
Wrapper.inherit(self, :is_a?, :pretty_print_cycle)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# A {Abstract::Set Set} that is part of a transaction.
|
|
8
|
+
#
|
|
9
|
+
# Membership reads and changes validate the members they access.
|
|
10
|
+
# Size reads validate cardinality. Enumeration captures the full set.
|
|
11
|
+
class Set < Abstract::Set
|
|
12
|
+
include SetOperations
|
|
13
|
+
|
|
14
|
+
Wrapper.inherit(self, *SetOperations::READ_HELPERS, writes: SetOperations::WRITE_HELPERS)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# Initializes Set and SortedSet wrappers with a transactional backing map.
|
|
8
|
+
# Abstract::Set's methods operate directly on this wrapper's @map. The map
|
|
9
|
+
# owns the snapshot and commit logic. Only membership settings and transfer
|
|
10
|
+
# checks belong here, because some transfers change values before insertion.
|
|
11
|
+
# @!visibility private
|
|
12
|
+
module SetOperations # :nodoc: all
|
|
13
|
+
include Wrapper
|
|
14
|
+
|
|
15
|
+
READ_HELPERS = %i[
|
|
16
|
+
each size length empty? count include? member? === compare_by_identity? weak?
|
|
17
|
+
== eql? hash subset? proper_subset? superset? proper_superset? intersect? disjoint? <=>
|
|
18
|
+
<= < >= > join inspect to_s to_set each_stored equality_index ordered? public_stored
|
|
19
|
+
].freeze
|
|
20
|
+
WRITE_HELPERS = %i[add << add? delete delete? clear merge subtract].freeze
|
|
21
|
+
|
|
22
|
+
def initialize(transaction, object, map)
|
|
23
|
+
super(transaction, object)
|
|
24
|
+
compose(:normalizer, :compare_by_identity, :manager, map:)
|
|
25
|
+
@value_modes = object.method(:value_modes?).call
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def value_modes? = access { @value_modes }
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def add_mode_value?(element, mode:)
|
|
33
|
+
selected = UNDEFINED.equal?(mode) || mode.nil? ? @manager.mode : mode
|
|
34
|
+
if %i[move make_shareable dedup proxy].include?(selected)
|
|
35
|
+
raise TypeError, "#{selected} transfers do not support transactions"
|
|
36
|
+
end
|
|
37
|
+
super
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def unwrap_entry(key, entry)
|
|
41
|
+
raise TypeError, "move envelopes do not support transactions" if Envelope::Move === entry.payload
|
|
42
|
+
super
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private_constant :SetOperations
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# A {Abstract::SortedSet SortedSet} that is part of a transaction.
|
|
8
|
+
class SortedSet < Abstract::SortedSet
|
|
9
|
+
include SetOperations
|
|
10
|
+
|
|
11
|
+
Wrapper.inherit(self, *SetOperations::READ_HELPERS, :ordered_keys, writes: SetOperations::WRITE_HELPERS)
|
|
12
|
+
|
|
13
|
+
# SortedSet builds temporary membership indexes for comparisons. Use the
|
|
14
|
+
# participant's map factory to retain support for mutable Local keys.
|
|
15
|
+
private def new_map(...) = @object.method(:new_map).call(...)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# A {Abstract::TreeMap TreeMap} that is part of a transaction.
|
|
8
|
+
class TreeMap < Abstract::TreeMap
|
|
9
|
+
include MapOperations
|
|
10
|
+
|
|
11
|
+
# (see Abstract::TreeMap#first_key)
|
|
12
|
+
# @see Abstract::TreeMap#first_key
|
|
13
|
+
def first_key = access { @working.first_key }
|
|
14
|
+
|
|
15
|
+
# (see Abstract::TreeMap#last_key)
|
|
16
|
+
# @see Abstract::TreeMap#last_key
|
|
17
|
+
def last_key = access { @working.last_key }
|
|
18
|
+
|
|
19
|
+
# (see Abstract::TreeMap#getkey)
|
|
20
|
+
# @see Abstract::TreeMap#getkey
|
|
21
|
+
def getkey(key) = access { @working.getkey(prepare(key)) }
|
|
22
|
+
|
|
23
|
+
# (see Abstract::TreeMap#keys)
|
|
24
|
+
# @see Abstract::TreeMap#keys
|
|
25
|
+
def keys = access { @working.each.map { |key, _| key }.freeze }
|
|
26
|
+
|
|
27
|
+
# (see Abstract::TreeMap#pop)
|
|
28
|
+
# @see Abstract::TreeMap#pop
|
|
29
|
+
def pop = write { public_pair(@working.pop) }
|
|
30
|
+
|
|
31
|
+
# (see Abstract::TreeMap#shift)
|
|
32
|
+
# @see Abstract::TreeMap#shift
|
|
33
|
+
def shift = write { public_pair(@working.shift) }
|
|
34
|
+
|
|
35
|
+
# (see Abstract::TreeMap#swap)
|
|
36
|
+
# @see Abstract::TreeMap#swap
|
|
37
|
+
def swap(key, value, mode: nil)
|
|
38
|
+
write do
|
|
39
|
+
canonical = prepare(key)
|
|
40
|
+
previous = unwrap_stored(@working[canonical])
|
|
41
|
+
store_value(canonical, wrap(value, mode:))
|
|
42
|
+
previous
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# (see Abstract::TreeMap#compare_and_set)
|
|
47
|
+
# @see Abstract::TreeMap#compare_and_set
|
|
48
|
+
def compare_and_set(key, expected, replacement, mode: nil)
|
|
49
|
+
write do
|
|
50
|
+
canonical = prepare(key)
|
|
51
|
+
next compared(false) unless @working.key?(canonical)
|
|
52
|
+
current = @working[canonical]
|
|
53
|
+
matches = @manager ? matches?(current, expected, identity: false) : current == expected
|
|
54
|
+
next compared(false) unless matches
|
|
55
|
+
store_value(canonical, wrap(replacement, mode:))
|
|
56
|
+
true
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def store_value(key, value)
|
|
63
|
+
@working[key] = value
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def prepare(key)
|
|
67
|
+
normalizer = @object.instance_variable_get(:@key_normalizer)
|
|
68
|
+
@working.prepare_key(normalizer ? normalizer.call(key) : key)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def public_pair(pair)
|
|
72
|
+
[pair.first, unwrap_stored(pair.last)] if pair
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
Wrapper.inherit(self, *MapOperations::READ_HELPERS)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Transaction
|
|
7
|
+
# A {Abstract::Vector Vector} that is part of a transaction.
|
|
8
|
+
class Vector < Abstract::Vector
|
|
9
|
+
include Wrapper
|
|
10
|
+
|
|
11
|
+
# (see Abstract::Vector#compare_by_identity?)
|
|
12
|
+
# @see Abstract::Vector#compare_by_identity?
|
|
13
|
+
def compare_by_identity? = access { @object.compare_by_identity? }
|
|
14
|
+
|
|
15
|
+
# (see Abstract::Vector#shareable_values?)
|
|
16
|
+
# @see Abstract::Vector#shareable_values?
|
|
17
|
+
def shareable_values? = access { @object.shareable_values? }
|
|
18
|
+
|
|
19
|
+
# (see Abstract::Vector#[])
|
|
20
|
+
# @see Abstract::Vector#[]
|
|
21
|
+
def [](index) = access { unwrap_stored(@working[index]) }
|
|
22
|
+
|
|
23
|
+
# (see Abstract::Vector#get)
|
|
24
|
+
# @see Abstract::Vector#get
|
|
25
|
+
def get(index) = self[index]
|
|
26
|
+
|
|
27
|
+
# (see Abstract::Vector#size)
|
|
28
|
+
# @see Abstract::Vector#size
|
|
29
|
+
def size = access { @working.size }
|
|
30
|
+
|
|
31
|
+
# (see Abstract::Vector#empty?)
|
|
32
|
+
# @see Abstract::Vector#empty?
|
|
33
|
+
def empty? = size.zero?
|
|
34
|
+
|
|
35
|
+
# (see Abstract::Vector#[]=)
|
|
36
|
+
# @see Abstract::Vector#[]=
|
|
37
|
+
def []=(index, value)
|
|
38
|
+
store(index, value)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# (see Abstract::Vector#store)
|
|
42
|
+
# @see Abstract::Vector#store
|
|
43
|
+
def store(index, value, mode: nil)
|
|
44
|
+
write { unwrap_stored(@working.store(index, wrap(value, mode:))) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# (see Abstract::Vector#swap)
|
|
48
|
+
# @see Abstract::Vector#swap
|
|
49
|
+
def swap(index, value, mode: nil)
|
|
50
|
+
write { unwrap_stored(@working.swap(index, wrap(value, mode:))) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# (see Abstract::Vector#push)
|
|
54
|
+
# @see Abstract::Vector#push
|
|
55
|
+
def push(value, mode: nil)
|
|
56
|
+
write { @working.push(wrap(value, mode:)) }
|
|
57
|
+
self
|
|
58
|
+
end
|
|
59
|
+
alias << push
|
|
60
|
+
|
|
61
|
+
# (see Abstract::Vector#pop)
|
|
62
|
+
# @see Abstract::Vector#pop
|
|
63
|
+
def pop = write { unwrap_stored(@working.pop) }
|
|
64
|
+
|
|
65
|
+
# (see Abstract::Vector#clear)
|
|
66
|
+
# @see Abstract::Vector#clear
|
|
67
|
+
def clear
|
|
68
|
+
write { @working.clear }
|
|
69
|
+
self
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# (see Abstract::Vector#each)
|
|
73
|
+
# @see Abstract::Vector#each
|
|
74
|
+
def each
|
|
75
|
+
return enum_for(__method__) unless block_given?
|
|
76
|
+
access { @working.snapshot.each { |value| yield unwrap_stored(value) } }
|
|
77
|
+
self
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# (see Abstract::Vector#update)
|
|
81
|
+
# @see Abstract::Vector#update
|
|
82
|
+
def update(index, mode: nil)
|
|
83
|
+
require_block!(block_given?)
|
|
84
|
+
write { unwrap_stored(@working.update(index) { |value| wrap(yield(unwrap_stored(value)), mode:) }) }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# (see Abstract::Vector#store_if_absent)
|
|
88
|
+
# @see Abstract::Vector#store_if_absent
|
|
89
|
+
def store_if_absent(index, mode: nil)
|
|
90
|
+
require_block!(block_given?)
|
|
91
|
+
write { unwrap_stored(@working.store_if_absent(index) { wrap(yield, mode:) }) }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# (see Abstract::Vector#upsert)
|
|
95
|
+
# @see Abstract::Vector#upsert
|
|
96
|
+
def upsert(index, initial, mode: nil)
|
|
97
|
+
require_block!(block_given?)
|
|
98
|
+
write do
|
|
99
|
+
unwrap_stored(@working.upsert(index, wrap(initial, mode:)) do |value|
|
|
100
|
+
wrap(yield(unwrap_stored(value)), mode:)
|
|
101
|
+
end)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# (see Abstract::Vector#compare_and_set)
|
|
106
|
+
# @see Abstract::Vector#compare_and_set
|
|
107
|
+
def compare_and_set(index, expected, replacement, mode: nil)
|
|
108
|
+
write do
|
|
109
|
+
next compared(@working.compare_and_set(index, expected, replacement)) unless @manager
|
|
110
|
+
index = Integer(index)
|
|
111
|
+
next compared(false) unless index >= -@working.size && index < @working.size &&
|
|
112
|
+
matches?(@working[index], expected, identity: @object.compare_by_identity?)
|
|
113
|
+
@working.store(index, wrap(replacement, mode:))
|
|
114
|
+
true
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
protected
|
|
119
|
+
|
|
120
|
+
def internal_vector = @working
|
|
121
|
+
def logical_value(value) = unwrap_stored(value)
|
|
122
|
+
|
|
123
|
+
# Slice helpers return independent data rather than another participant.
|
|
124
|
+
# Use an ordinary vector that remains usable after the attempt ends.
|
|
125
|
+
def build_derived_vector(values)
|
|
126
|
+
Unshared::Vector.new(values.map { unwrap_stored(it) }, compare_by_identity: compare_by_identity?)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
private
|
|
130
|
+
|
|
131
|
+
def inspect_value(inspector, value) = super(inspector, value, @manager)
|
|
132
|
+
def derived_storage(value) = wrap(value)
|
|
133
|
+
|
|
134
|
+
Wrapper.inherit(self, :each_index, :reverse_each, :to_a, :deconstruct, :to_h, :join, :dig, :assoc,
|
|
135
|
+
:rassoc, :at, :fetch, :fetch_values, :values_at, :slice, :rfind, :bsearch, :bsearch_index, :pack,
|
|
136
|
+
:length, :count, :compare_by_identity?, :shareable_values?)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|