farce 0.0.1.alpha2-java
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/lib/farce/_yard/internal.rb +13 -0
- data/lib/farce/_yard/macros.rb +61 -0
- data/lib/farce/_yard/ractor.rb +46 -0
- data/lib/farce/abstract/atom.rb +186 -0
- data/lib/farce/abstract/bounded_map.rb +232 -0
- data/lib/farce/abstract/collection.rb +151 -0
- data/lib/farce/abstract/concurrent_map.rb +381 -0
- data/lib/farce/abstract/counter.rb +193 -0
- data/lib/farce/abstract/duplicable_map.rb +229 -0
- data/lib/farce/abstract/exchanger.rb +26 -0
- data/lib/farce/abstract/flag.rb +71 -0
- data/lib/farce/abstract/lazy.rb +115 -0
- data/lib/farce/abstract/lease.rb +104 -0
- data/lib/farce/abstract/lease_map.rb +261 -0
- data/lib/farce/abstract/lease_pool.rb +91 -0
- data/lib/farce/abstract/lfu_map.rb +20 -0
- data/lib/farce/abstract/lru_map.rb +25 -0
- data/lib/farce/abstract/map.rb +345 -0
- data/lib/farce/abstract/molecule.rb +245 -0
- data/lib/farce/abstract/port.rb +74 -0
- data/lib/farce/abstract/priority_queue.rb +117 -0
- data/lib/farce/abstract/queue.rb +269 -0
- data/lib/farce/abstract/scheduler.rb +111 -0
- data/lib/farce/abstract/set.rb +910 -0
- data/lib/farce/abstract/sorted_set.rb +172 -0
- data/lib/farce/abstract/timer_queue.rb +136 -0
- data/lib/farce/abstract/tree_map.rb +269 -0
- data/lib/farce/abstract/value.rb +68 -0
- data/lib/farce/abstract/vector.rb +1126 -0
- data/lib/farce/abstract/weak_atom.rb +32 -0
- data/lib/farce/abstract/weak_key_map.rb +12 -0
- data/lib/farce/abstract/weak_map.rb +13 -0
- data/lib/farce/abstract/weak_set.rb +12 -0
- data/lib/farce/abstract/weak_value_map.rb +12 -0
- data/lib/farce/abstract.rb +17 -0
- data/lib/farce/atom.rb +293 -0
- data/lib/farce/class_mirror.rb +87 -0
- data/lib/farce/clock.rb +121 -0
- data/lib/farce/config.rb +229 -0
- data/lib/farce/counter.rb +71 -0
- data/lib/farce/deduper.rb +122 -0
- data/lib/farce/engine/jruby/bounded_map.rb +314 -0
- data/lib/farce/engine/jruby/fiber_scheduler.jar +0 -0
- data/lib/farce/engine/jruby/fiber_scheduler.rb +119 -0
- data/lib/farce/engine/jruby/lease_waiting.rb +19 -0
- data/lib/farce/engine/jruby/map.rb +505 -0
- data/lib/farce/engine/jruby/mutable_numeric_copy.rb +42 -0
- data/lib/farce/engine/jruby/signal.rb +147 -0
- data/lib/farce/engine/jruby.rb +63 -0
- data/lib/farce/engine/jvm/concurrent_weak_registry.rb +55 -0
- data/lib/farce/engine/jvm/counter.rb +102 -0
- data/lib/farce/engine/jvm/extension.rb +32 -0
- data/lib/farce/engine/jvm/farce.jar +0 -0
- data/lib/farce/engine/jvm/flag.rb +79 -0
- data/lib/farce/engine/jvm/priority_queue.rb +217 -0
- data/lib/farce/engine/jvm/tree_map.rb +350 -0
- data/lib/farce/engine/jvm/types.rb +180 -0
- data/lib/farce/engine/jvm.rb +19 -0
- data/lib/farce/engine/ruby/3.4/fiber_scheduler.rb +20 -0
- data/lib/farce/engine/ruby/3.4/port.rb +186 -0
- data/lib/farce/engine/ruby/3.4/ractor_methods.rb +26 -0
- data/lib/farce/engine/ruby/3.4/ractor_selector.rb +92 -0
- data/lib/farce/engine/ruby/3.4/vault.rb +56 -0
- data/lib/farce/engine/ruby/4.0/port.rb +19 -0
- data/lib/farce/engine/ruby/4.0/ractor_methods.rb +20 -0
- data/lib/farce/engine/ruby/4.0/ractor_selector.rb +108 -0
- data/lib/farce/engine/ruby/4.0/vault.rb +74 -0
- data/lib/farce/engine/ruby/4.1/port.rb +21 -0
- data/lib/farce/engine/ruby/4.1/ractor_methods.rb +22 -0
- data/lib/farce/engine/ruby/4.1/ractor_selector.rb +25 -0
- data/lib/farce/engine/ruby/4.1/vault.rb +5 -0
- data/lib/farce/engine/ruby/fiber_scheduler.rb +32 -0
- data/lib/farce/engine/ruby/key_lock_map.rb +28 -0
- data/lib/farce/engine/ruby/shared/lease.rb +26 -0
- data/lib/farce/engine/ruby/shared/lease_pool.rb +24 -0
- data/lib/farce/engine/ruby/shared/main_scheduler.rb +9 -0
- data/lib/farce/engine/ruby/shared/parallel_scheduler.rb +9 -0
- data/lib/farce/engine/ruby/shared/proxy_owner.rb +31 -0
- data/lib/farce/engine/ruby/shared/ractor_methods.rb +34 -0
- data/lib/farce/engine/ruby/shared/ractor_selector.rb +328 -0
- data/lib/farce/engine/ruby/shared/strict_map.rb +13 -0
- data/lib/farce/engine/ruby/shared/unshared_vector.rb +14 -0
- data/lib/farce/engine/ruby/shared/vault.rb +144 -0
- data/lib/farce/engine/ruby/shared/vault_weak_map.rb +336 -0
- data/lib/farce/engine/ruby/shared/weak_atom.rb +54 -0
- data/lib/farce/engine/ruby/shared/weak_map.rb +413 -0
- data/lib/farce/engine/ruby.rb +130 -0
- data/lib/farce/engine/shared/atom.rb +10 -0
- data/lib/farce/engine/shared/exchanger.rb +130 -0
- data/lib/farce/engine/shared/identity_key.rb +22 -0
- data/lib/farce/engine/shared/lease.rb +10 -0
- data/lib/farce/engine/shared/lease_pool.rb +10 -0
- data/lib/farce/engine/shared/main_scheduler.rb +20 -0
- data/lib/farce/engine/shared/map_key_coordination.rb +226 -0
- data/lib/farce/engine/shared/parallel_scheduler.rb +9 -0
- data/lib/farce/engine/shared/port.rb +44 -0
- data/lib/farce/engine/shared/portable_bounded_map.rb +619 -0
- data/lib/farce/engine/shared/proxy_owner.rb +43 -0
- data/lib/farce/engine/shared/queue.rb +233 -0
- data/lib/farce/engine/shared/ractor_methods.rb +73 -0
- data/lib/farce/engine/shared/rebindable.rb +15 -0
- data/lib/farce/engine/shared/strict_atom.rb +73 -0
- data/lib/farce/engine/shared/strict_map.rb +117 -0
- data/lib/farce/engine/shared/strict_queue_values.rb +27 -0
- data/lib/farce/engine/shared/strict_tree_map.rb +56 -0
- data/lib/farce/engine/shared/transaction_map_backend.rb +20 -0
- data/lib/farce/engine/shared/trie.rb +317 -0
- data/lib/farce/engine/shared/trie_builder.rb +199 -0
- data/lib/farce/engine/shared/unshareable.rb +14 -0
- data/lib/farce/engine/shared/unshared_atom.rb +256 -0
- data/lib/farce/engine/shared/unshared_priority_queue.rb +9 -0
- data/lib/farce/engine/shared/unshared_queue.rb +18 -0
- data/lib/farce/engine/shared/unshared_signal.rb +21 -0
- data/lib/farce/engine/shared/unshared_vector.rb +377 -0
- data/lib/farce/engine/shared/unshared_weak_atom.rb +30 -0
- data/lib/farce/engine/shared/unshared_weak_map.rb +445 -0
- data/lib/farce/engine/shared/vault.rb +31 -0
- data/lib/farce/engine/shared/vector.rb +83 -0
- data/lib/farce/engine/shared/weak_atom/base.rb +189 -0
- data/lib/farce/engine/shared/weak_atom.rb +20 -0
- data/lib/farce/engine/shared/weak_map/cell.rb +99 -0
- data/lib/farce/engine/shared/weak_map/index.rb +249 -0
- data/lib/farce/engine/shared/weak_map/lock.rb +80 -0
- data/lib/farce/engine/shared/weak_map/reference.rb +33 -0
- data/lib/farce/engine/shared.rb +63 -0
- data/lib/farce/engine/truffleruby/fiber_scheduler.rb +13 -0
- data/lib/farce/engine/truffleruby/lock.rb +121 -0
- data/lib/farce/engine/truffleruby/map.rb +656 -0
- data/lib/farce/engine/truffleruby/native/counter.rb +105 -0
- data/lib/farce/engine/truffleruby/native/flag.rb +77 -0
- data/lib/farce/engine/truffleruby/native/ordered_array_support.rb +67 -0
- data/lib/farce/engine/truffleruby/native/priority_queue.rb +388 -0
- data/lib/farce/engine/truffleruby/native/tree_map.rb +51 -0
- data/lib/farce/engine/truffleruby/native/unsafe_tree_map.rb +350 -0
- data/lib/farce/engine/truffleruby/signal.rb +77 -0
- data/lib/farce/engine/truffleruby.rb +148 -0
- data/lib/farce/envelope.rb +335 -0
- data/lib/farce/error.rb +35 -0
- data/lib/farce/exchanger.rb +41 -0
- data/lib/farce/flag.rb +27 -0
- data/lib/farce/integrations/active_support/blank.rb +68 -0
- data/lib/farce/integrations/active_support/clock.rb +17 -0
- data/lib/farce/integrations/active_support/duplicable.rb +78 -0
- data/lib/farce/integrations/active_support/map.rb +175 -0
- data/lib/farce/integrations/active_support/set.rb +60 -0
- data/lib/farce/integrations/active_support/value_serialization.rb +17 -0
- data/lib/farce/integrations/active_support/vector.rb +231 -0
- data/lib/farce/integrations/active_support.rb +9 -0
- data/lib/farce/integrations/activesupport.rb +5 -0
- data/lib/farce/integrations/bson.rb +108 -0
- data/lib/farce/integrations/cbor.rb +51 -0
- data/lib/farce/integrations/concurrent.rb +112 -0
- data/lib/farce/integrations/dry-types.rb +5 -0
- data/lib/farce/integrations/dry_types.rb +694 -0
- data/lib/farce/integrations/json.rb +7 -0
- data/lib/farce/integrations/msgpack.rb +112 -0
- data/lib/farce/integrations/oj.rb +69 -0
- data/lib/farce/integrations/psych.rb +191 -0
- data/lib/farce/integrations/ractor-sharing.rb +5 -0
- data/lib/farce/integrations/ractor-tmvar.rb +5 -0
- data/lib/farce/integrations/ractor_sharing.rb +172 -0
- data/lib/farce/integrations/ractor_tmvar.rb +64 -0
- data/lib/farce/integrations/shared/to_json.rb +42 -0
- data/lib/farce/integrations/sorted_set.rb +11 -0
- data/lib/farce/integrations/weakref.rb +38 -0
- data/lib/farce/integrations/yajl.rb +10 -0
- data/lib/farce/integrations.rb +156 -0
- data/lib/farce/internal/_frozen_config.rb +11 -0
- data/lib/farce/internal/autoloads.rb +47 -0
- data/lib/farce/internal/blocking_priority_queue.rb +122 -0
- data/lib/farce/internal/converter.rb +106 -0
- data/lib/farce/internal/copyable.rb +31 -0
- data/lib/farce/internal/delegation.rb +20 -0
- data/lib/farce/internal/external_transaction.rb +59 -0
- data/lib/farce/internal/fake_ractor.rb +179 -0
- data/lib/farce/internal/freeze.rb +118 -0
- data/lib/farce/internal/inspect.rb +157 -0
- data/lib/farce/internal/key_lock_map.rb +29 -0
- data/lib/farce/internal/key_normalizer.rb +289 -0
- data/lib/farce/internal/lease_initialization.rb +115 -0
- data/lib/farce/internal/lease_map.rb +441 -0
- data/lib/farce/internal/lease_pool_state.rb +228 -0
- data/lib/farce/internal/lease_state.rb +342 -0
- data/lib/farce/internal/lease_waiting.rb +13 -0
- data/lib/farce/internal/managed_queue.rb +26 -0
- data/lib/farce/internal/map_value_modes.rb +227 -0
- data/lib/farce/internal/marshal_support.rb +227 -0
- data/lib/farce/internal/mixin.rb +20 -0
- data/lib/farce/internal/mutable_ordered_key_lock_map.rb +63 -0
- data/lib/farce/internal/noncopyable.rb +17 -0
- data/lib/farce/internal/ordered_key_lock_map.rb +69 -0
- data/lib/farce/internal/pool_supervisor.rb +41 -0
- data/lib/farce/internal/pool_worker.rb +61 -0
- data/lib/farce/internal/portable_transaction/reservation_entry.rb +29 -0
- data/lib/farce/internal/portable_transaction/strong_map_entry.rb +137 -0
- data/lib/farce/internal/portable_transaction/strong_map_size_entry.rb +44 -0
- data/lib/farce/internal/portable_transaction/tree_entry.rb +64 -0
- data/lib/farce/internal/portable_transaction.rb +164 -0
- data/lib/farce/internal/proxy_owner_notifications.rb +29 -0
- data/lib/farce/internal/reservation_waiting.rb +24 -0
- data/lib/farce/internal/scheduled_task.rb +48 -0
- data/lib/farce/internal/scheduler_io.rb +171 -0
- data/lib/farce/internal/scheduler_lifecycle.rb +314 -0
- data/lib/farce/internal/select_scheduler.rb +235 -0
- data/lib/farce/internal/storage.rb +162 -0
- data/lib/farce/internal/strict_lease.rb +30 -0
- data/lib/farce/internal/strict_lease_map.rb +20 -0
- data/lib/farce/internal/strict_lease_pool.rb +29 -0
- data/lib/farce/internal/thread_pool.rb +166 -0
- data/lib/farce/internal/transaction_conflict.rb +9 -0
- data/lib/farce/internal/transaction_freeze_guard.rb +30 -0
- data/lib/farce/internal/transaction_map_snapshot.rb +123 -0
- data/lib/farce/internal/undefined.rb +22 -0
- data/lib/farce/internal/unshared_lease.rb +29 -0
- data/lib/farce/internal/unshared_lease_pool.rb +34 -0
- data/lib/farce/internal/unshared_queue_waiting.rb +28 -0
- data/lib/farce/internal/value_serialization.rb +13 -0
- data/lib/farce/internal/weak_map_value_modes.rb +58 -0
- data/lib/farce/internal/weak_mode_manager.rb +26 -0
- data/lib/farce/internal.rb +129 -0
- data/lib/farce/lazy.rb +100 -0
- data/lib/farce/lazy_ref.rb +40 -0
- data/lib/farce/lease.rb +28 -0
- data/lib/farce/lease_map.rb +34 -0
- data/lib/farce/lease_pool.rb +29 -0
- data/lib/farce/lfu_map.rb +53 -0
- data/lib/farce/local/atom.rb +23 -0
- data/lib/farce/local/counter.rb +88 -0
- data/lib/farce/local/flag.rb +65 -0
- data/lib/farce/local/lazy.rb +38 -0
- data/lib/farce/local/lazy_ref.rb +36 -0
- data/lib/farce/local/lease.rb +77 -0
- data/lib/farce/local/lease_map.rb +80 -0
- data/lib/farce/local/lease_pool.rb +38 -0
- data/lib/farce/local/lfu_map.rb +55 -0
- data/lib/farce/local/lru_map.rb +62 -0
- data/lib/farce/local/map.rb +47 -0
- data/lib/farce/local/molecule.rb +45 -0
- data/lib/farce/local/priority_queue.rb +53 -0
- data/lib/farce/local/queue.rb +32 -0
- data/lib/farce/local/scoped.rb +166 -0
- data/lib/farce/local/set.rb +18 -0
- data/lib/farce/local/sorted_set.rb +50 -0
- data/lib/farce/local/timer_queue.rb +41 -0
- data/lib/farce/local/tree_map.rb +47 -0
- data/lib/farce/local/vector.rb +30 -0
- data/lib/farce/local/weak_atom.rb +23 -0
- data/lib/farce/local/weak_key_map.rb +39 -0
- data/lib/farce/local/weak_map.rb +39 -0
- data/lib/farce/local/weak_set.rb +18 -0
- data/lib/farce/local/weak_value_map.rb +39 -0
- data/lib/farce/local.rb +35 -0
- data/lib/farce/lock.rb +54 -0
- data/lib/farce/lru_map.rb +63 -0
- data/lib/farce/map.rb +58 -0
- data/lib/farce/mode_manager.rb +142 -0
- data/lib/farce/molecule.rb +60 -0
- data/lib/farce/mutable.rb +171 -0
- data/lib/farce/pool.rb +332 -0
- data/lib/farce/port.rb +134 -0
- data/lib/farce/priority_queue.rb +70 -0
- data/lib/farce/proxy/register.rb +101 -0
- data/lib/farce/proxy/supervisor.rb +137 -0
- data/lib/farce/proxy/wrapper.rb +49 -0
- data/lib/farce/proxy.rb +291 -0
- data/lib/farce/queue.rb +60 -0
- data/lib/farce/ractor.rb +269 -0
- data/lib/farce/read_write_lock.rb +256 -0
- data/lib/farce/reference.rb +158 -0
- data/lib/farce/resolv/dns.rb +42 -0
- data/lib/farce/resolv.rb +85 -0
- data/lib/farce/scheduler.rb +536 -0
- data/lib/farce/set.rb +39 -0
- data/lib/farce/shareable.rb +150 -0
- data/lib/farce/signal.rb +97 -0
- data/lib/farce/sorted_set.rb +36 -0
- data/lib/farce/strict/atom.rb +34 -0
- data/lib/farce/strict/counter.rb +10 -0
- data/lib/farce/strict/exchanger.rb +25 -0
- data/lib/farce/strict/flag.rb +10 -0
- data/lib/farce/strict/lazy.rb +26 -0
- data/lib/farce/strict/lazy_ref.rb +26 -0
- data/lib/farce/strict/lease.rb +27 -0
- data/lib/farce/strict/lease_map.rb +33 -0
- data/lib/farce/strict/lease_pool.rb +28 -0
- data/lib/farce/strict/lfu_map.rb +27 -0
- data/lib/farce/strict/lru_map.rb +28 -0
- data/lib/farce/strict/map.rb +54 -0
- data/lib/farce/strict/molecule.rb +16 -0
- data/lib/farce/strict/port.rb +40 -0
- data/lib/farce/strict/priority_queue.rb +20 -0
- data/lib/farce/strict/queue.rb +17 -0
- data/lib/farce/strict/set.rb +14 -0
- data/lib/farce/strict/sorted_set.rb +19 -0
- data/lib/farce/strict/timer_queue.rb +13 -0
- data/lib/farce/strict/tree_map.rb +27 -0
- data/lib/farce/strict/vector.rb +24 -0
- data/lib/farce/strict/weak_atom.rb +31 -0
- data/lib/farce/strict/weak_key_map.rb +49 -0
- data/lib/farce/strict/weak_map.rb +49 -0
- data/lib/farce/strict/weak_set.rb +14 -0
- data/lib/farce/strict/weak_value_map.rb +48 -0
- data/lib/farce/strict.rb +28 -0
- data/lib/farce/system.rb +40 -0
- data/lib/farce/thread_scheduler.rb +70 -0
- data/lib/farce/timer_queue.rb +66 -0
- data/lib/farce/transaction/atom.rb +73 -0
- data/lib/farce/transaction/map.rb +25 -0
- data/lib/farce/transaction/map_operations.rb +143 -0
- data/lib/farce/transaction/molecule.rb +90 -0
- data/lib/farce/transaction/mutable.rb +61 -0
- data/lib/farce/transaction/set.rb +17 -0
- data/lib/farce/transaction/set_operations.rb +48 -0
- data/lib/farce/transaction/sorted_set.rb +18 -0
- data/lib/farce/transaction/tree_map.rb +78 -0
- data/lib/farce/transaction/vector.rb +139 -0
- data/lib/farce/transaction/wrapper.rb +202 -0
- data/lib/farce/transaction.rb +343 -0
- data/lib/farce/tree_map.rb +56 -0
- data/lib/farce/unsafe/lfu_map.rb +36 -0
- data/lib/farce/unsafe/lru_map.rb +36 -0
- data/lib/farce/unsafe/tree_map.rb +21 -0
- data/lib/farce/unsafe.rb +29 -0
- data/lib/farce/unshareable.rb +67 -0
- data/lib/farce/unshared/atom.rb +24 -0
- data/lib/farce/unshared/counter.rb +10 -0
- data/lib/farce/unshared/flag.rb +10 -0
- data/lib/farce/unshared/lazy.rb +38 -0
- data/lib/farce/unshared/lazy_ref.rb +26 -0
- data/lib/farce/unshared/lease.rb +27 -0
- data/lib/farce/unshared/lease_map.rb +26 -0
- data/lib/farce/unshared/lease_pool.rb +25 -0
- data/lib/farce/unshared/lfu_map.rb +20 -0
- data/lib/farce/unshared/lru_map.rb +20 -0
- data/lib/farce/unshared/map.rb +49 -0
- data/lib/farce/unshared/molecule.rb +16 -0
- data/lib/farce/unshared/priority_queue.rb +16 -0
- data/lib/farce/unshared/queue.rb +27 -0
- data/lib/farce/unshared/set.rb +14 -0
- data/lib/farce/unshared/sorted_set.rb +28 -0
- data/lib/farce/unshared/timer_queue.rb +16 -0
- data/lib/farce/unshared/tree_map.rb +21 -0
- data/lib/farce/unshared/vector.rb +19 -0
- data/lib/farce/unshared/weak_atom.rb +31 -0
- data/lib/farce/unshared/weak_key_map.rb +44 -0
- data/lib/farce/unshared/weak_map.rb +44 -0
- data/lib/farce/unshared/weak_set.rb +14 -0
- data/lib/farce/unshared/weak_value_map.rb +43 -0
- data/lib/farce/unshared.rb +28 -0
- data/lib/farce/vector.rb +228 -0
- data/lib/farce/version.rb +8 -0
- data/lib/farce/walker/definitions.rb +186 -0
- data/lib/farce/walker/modification.rb +355 -0
- data/lib/farce/walker.rb +319 -0
- data/lib/farce/weak_atom.rb +121 -0
- data/lib/farce/weak_key_map.rb +31 -0
- data/lib/farce/weak_map.rb +33 -0
- data/lib/farce/weak_ref.rb +67 -0
- data/lib/farce/weak_set.rb +82 -0
- data/lib/farce/weak_value.rb +195 -0
- data/lib/farce/weak_value_map.rb +32 -0
- data/lib/farce.rb +519 -0
- metadata +420 -0
|
@@ -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 that retains mutable elements weakly within one Ractor.
|
|
8
|
+
class WeakSet < Farce::Abstract::WeakSet
|
|
9
|
+
include Unshareable
|
|
10
|
+
|
|
11
|
+
private def new_map(...) = Farce::Unshared::WeakMap.new(...)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
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 values for use within one Ractor.
|
|
8
|
+
#
|
|
9
|
+
# @example Caching a mutable value without keeping it alive
|
|
10
|
+
# value = []
|
|
11
|
+
# map = Farce::Unshared::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 Unshareable
|
|
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: false)
|
|
29
|
+
populate = initial_mapping && ((normalizer && !restoring) || !initial_mapping.is_a?(Hash))
|
|
30
|
+
@map = Internal::UnsharedWeakValueMap.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
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# Thread-safe containers for values used within one Ractor.
|
|
7
|
+
module Unshared
|
|
8
|
+
include Internal::Autoloads
|
|
9
|
+
|
|
10
|
+
# @overload enfarce(object, freeze: nil)
|
|
11
|
+
# Converts vanilla Ruby objects into their {Farce::Unshared} equivalents.
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# Farce::Unshared.enfarce({ foo: ["bar"] })
|
|
15
|
+
# # => #<Farce::Unshared::Map {foo: #<Farce::Unshared::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/vector.rb
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# A Ractor-shareable vector with transfer modes for mutable values.
|
|
7
|
+
# Values stored through this vector's mode manager are automatically unwrapped.
|
|
8
|
+
#
|
|
9
|
+
# @example Atomically updating a collection
|
|
10
|
+
# vector = Farce::Vector.new([[]], mode: :make_shareable)
|
|
11
|
+
# vector.update(0) { |jobs| jobs + [:finished] } # => [:finished]
|
|
12
|
+
#
|
|
13
|
+
# @!method append(value, mode: nil, timeout: nil)
|
|
14
|
+
# Append one value using the same options as {#push}.
|
|
15
|
+
# @param value [BasicObject] The value to append.
|
|
16
|
+
# @param mode [Symbol, nil] The transfer mode, or nil to use the default.
|
|
17
|
+
# @param timeout [Numeric, nil] The maximum wait in seconds. Nil waits indefinitely.
|
|
18
|
+
# @return [self, false] Self on success, or false on timeout.
|
|
19
|
+
class Vector < Farce::Abstract::Vector
|
|
20
|
+
include Shareable::Delegated
|
|
21
|
+
|
|
22
|
+
# @!macro modes
|
|
23
|
+
# @param source [Array, nil] Initial values. The source array is not retained.
|
|
24
|
+
# @param mode [Symbol] The default value transfer mode.
|
|
25
|
+
# @param compare_by_identity [Boolean] Whether values are compared by identity.
|
|
26
|
+
def initialize(source = nil, mode: :copy, compare_by_identity: false)
|
|
27
|
+
raise TypeError, "source must be an Array" unless source.nil? || source.is_a?(Array)
|
|
28
|
+
unless true.equal?(compare_by_identity) || false.equal?(compare_by_identity)
|
|
29
|
+
raise ArgumentError, "compare_by_identity must be true or false"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
@compare_by_identity = compare_by_identity
|
|
33
|
+
@manager = ModeManager.new(mode:)
|
|
34
|
+
@vector = Internal::Vector.new(source&.map { @manager.wrap(it) }, compare_by_identity: true)
|
|
35
|
+
super()
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @api private
|
|
39
|
+
def transaction_wrapper(transaction) = Transaction::Vector.new(transaction, self, @vector, manager: @manager)
|
|
40
|
+
|
|
41
|
+
# @return [Symbol] The default transfer mode.
|
|
42
|
+
def mode = @manager.mode
|
|
43
|
+
|
|
44
|
+
# @api private
|
|
45
|
+
def marshal_dump
|
|
46
|
+
entries = @vector.snapshot.map { Internal::MarshalSupport.value(it) }
|
|
47
|
+
[1, entries, @manager, compare_by_identity?, frozen?]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @api private
|
|
51
|
+
def marshal_load(data)
|
|
52
|
+
entries, @manager, identity, frozen = Internal::MarshalSupport.payload(data, 4)
|
|
53
|
+
@compare_by_identity = identity
|
|
54
|
+
@vector = Internal::Vector.new(compare_by_identity: true)
|
|
55
|
+
publish_shareable
|
|
56
|
+
entries.each { @vector.push(Internal::MarshalSupport.restore_value(it)) }
|
|
57
|
+
Internal::MarshalSupport.freeze(self, frozen)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# (see Farce::Abstract::Vector#compare_by_identity?)
|
|
61
|
+
def compare_by_identity? = @compare_by_identity
|
|
62
|
+
|
|
63
|
+
# (see Farce::Abstract::Vector#shareable_values?)
|
|
64
|
+
def shareable_values? = true
|
|
65
|
+
|
|
66
|
+
# (see Farce::Abstract::Vector#[])
|
|
67
|
+
def [](index) = @manager.unwrap(@vector[index])
|
|
68
|
+
|
|
69
|
+
# (see Farce::Abstract::Vector#[]=)
|
|
70
|
+
def []=(index, value)
|
|
71
|
+
check_frozen!
|
|
72
|
+
@vector[index] = @manager.wrap(value)
|
|
73
|
+
value
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# (see Farce::Abstract::Vector#get)
|
|
77
|
+
def get(index, timeout: nil) = @manager.unwrap(@vector.get(index, timeout:))
|
|
78
|
+
|
|
79
|
+
# (see Farce::Abstract::Vector#store)
|
|
80
|
+
# @param mode [Symbol, nil] The transfer mode, or nil to use the default.
|
|
81
|
+
def store(index, value, mode: nil, timeout: nil)
|
|
82
|
+
check_frozen!
|
|
83
|
+
@manager.unwrap(@vector.store(index, @manager.wrap(value, mode:), timeout:))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# (see Farce::Abstract::Vector#push)
|
|
87
|
+
# @param mode [Symbol, nil] The transfer mode, or nil to use the default.
|
|
88
|
+
def push(value, mode: nil, timeout: nil)
|
|
89
|
+
check_frozen!
|
|
90
|
+
@vector.push(@manager.wrap(value, mode:), timeout:) ? self : false
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# (see Farce::Abstract::Vector#pop)
|
|
94
|
+
def pop(timeout: nil) = @manager.unwrap(@vector.pop(timeout:))
|
|
95
|
+
|
|
96
|
+
# (see Farce::Abstract::Vector#swap)
|
|
97
|
+
# @!macro modes
|
|
98
|
+
# @param mode [Symbol, nil] The replacement's transfer mode, or nil to use the default.
|
|
99
|
+
def swap(index, replacement, mode: nil, timeout: nil)
|
|
100
|
+
check_frozen!
|
|
101
|
+
@manager.unwrap(@vector.swap(index, @manager.wrap(replacement, mode:), timeout:))
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# (see Farce::Abstract::Vector#store_if_absent)
|
|
105
|
+
# @param mode [Symbol, nil] The result's transfer mode, or nil to use the default.
|
|
106
|
+
def store_if_absent(index, mode: nil, timeout: nil)
|
|
107
|
+
raise LocalJumpError, "no block given" unless block_given?
|
|
108
|
+
check_frozen!
|
|
109
|
+
@manager.unwrap(@vector.store_if_absent(index, timeout:) do
|
|
110
|
+
value = yield
|
|
111
|
+
check_frozen!
|
|
112
|
+
@manager.wrap(value, mode:)
|
|
113
|
+
end)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# (see Farce::Abstract::Vector#update)
|
|
117
|
+
# @!macro modes
|
|
118
|
+
# @param mode [Symbol, nil] The result's transfer mode, or nil to use the default.
|
|
119
|
+
def update(index, mode: nil, timeout: nil)
|
|
120
|
+
raise LocalJumpError, "no block given" unless block_given?
|
|
121
|
+
check_frozen!
|
|
122
|
+
@manager.unwrap(@vector.update(index, timeout:) do |current|
|
|
123
|
+
value = yield(@manager.unwrap(current))
|
|
124
|
+
check_frozen!
|
|
125
|
+
@manager.wrap(value, mode:)
|
|
126
|
+
end)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# (see Farce::Abstract::Vector#upsert)
|
|
130
|
+
# @!macro modes
|
|
131
|
+
# @param mode [Symbol, nil] The value transfer mode, or nil to use the default.
|
|
132
|
+
def upsert(index, initial, mode: nil, timeout: nil)
|
|
133
|
+
raise LocalJumpError, "no block given" unless block_given?
|
|
134
|
+
check_frozen!
|
|
135
|
+
@manager.unwrap(@vector.update(index, timeout:) do |current|
|
|
136
|
+
value = if nil.equal?(current)
|
|
137
|
+
initial
|
|
138
|
+
else
|
|
139
|
+
yielded = yield(@manager.unwrap(current))
|
|
140
|
+
check_frozen!
|
|
141
|
+
yielded
|
|
142
|
+
end
|
|
143
|
+
@manager.wrap(value, mode:)
|
|
144
|
+
end)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# (see Farce::Abstract::Vector#compare_and_set)
|
|
148
|
+
# @!macro modes
|
|
149
|
+
# @param mode [Symbol, nil] The replacement's transfer mode, or nil to use the default.
|
|
150
|
+
def compare_and_set(index, expected, replacement, mode: nil, timeout: nil)
|
|
151
|
+
check_frozen!
|
|
152
|
+
deadline = timeout_deadline(timeout)
|
|
153
|
+
expected = wrap_comparison(expected)
|
|
154
|
+
wrapped = false
|
|
155
|
+
loop do
|
|
156
|
+
current = @vector[index]
|
|
157
|
+
equal = values_equal?(current, expected)
|
|
158
|
+
check_frozen!
|
|
159
|
+
return false unless equal
|
|
160
|
+
unless wrapped
|
|
161
|
+
replacement = @manager.wrap(replacement, mode:)
|
|
162
|
+
wrapped = true
|
|
163
|
+
end
|
|
164
|
+
return true if @vector.compare_and_set(index, current, replacement, timeout: remaining_timeout(deadline))
|
|
165
|
+
return false if nil.equal?(current) || (deadline && Clock.now >= deadline)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# (see Farce::Abstract::Vector#wait_until_changed)
|
|
170
|
+
def wait_until_changed(index, expected, timeout: nil)
|
|
171
|
+
deadline = timeout_deadline(timeout)
|
|
172
|
+
expected = wrap_comparison(expected)
|
|
173
|
+
loop do
|
|
174
|
+
current = @vector[index]
|
|
175
|
+
return @manager.unwrap(current) unless values_equal?(current, expected)
|
|
176
|
+
return if deadline && Clock.now >= deadline
|
|
177
|
+
@vector.wait_until_changed(index, current, timeout: remaining_timeout(deadline))
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# (see Farce::Abstract::Vector#wait_until_non_nil)
|
|
182
|
+
def wait_until_non_nil(index, timeout: nil) = @manager.unwrap(@vector.wait_until_non_nil(index, timeout:))
|
|
183
|
+
|
|
184
|
+
protected
|
|
185
|
+
|
|
186
|
+
def logical_value(value) = @manager.unwrap(value)
|
|
187
|
+
|
|
188
|
+
def build_derived_vector(values)
|
|
189
|
+
self.class.allocate.initialize_derived_vector(values, @manager, @compare_by_identity)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def initialize_derived_vector(values, manager, compare_by_identity)
|
|
193
|
+
@manager = manager
|
|
194
|
+
@compare_by_identity = compare_by_identity
|
|
195
|
+
@vector = Internal::Vector.new(values, compare_by_identity: true)
|
|
196
|
+
publish_shareable
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
attr_reader :manager
|
|
200
|
+
|
|
201
|
+
def reusable_operand_snapshot(other)
|
|
202
|
+
return unless other.is_a?(Farce::Vector)
|
|
203
|
+
return unless other.manager.equal?(@manager)
|
|
204
|
+
other.internal_vector.snapshot
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
private
|
|
208
|
+
|
|
209
|
+
def inspect_value(inspector, value) = super(inspector, value, @manager)
|
|
210
|
+
def derived_storage(value) = @manager.wrap(value)
|
|
211
|
+
def freeze_backend = @vector
|
|
212
|
+
def wrap_comparison(value) = @manager.wrap(value, mode: compare_by_identity? ? :local : :copy)
|
|
213
|
+
def values_equal?(left, right) = @manager.same_value?(left, right, identity: compare_by_identity?)
|
|
214
|
+
|
|
215
|
+
def timeout_deadline(timeout)
|
|
216
|
+
return if timeout.nil?
|
|
217
|
+
timeout = Float(timeout)
|
|
218
|
+
raise ArgumentError, "timeout must be finite and non-negative" unless timeout.finite? && !timeout.negative?
|
|
219
|
+
Clock.now + timeout
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def remaining_timeout(deadline)
|
|
223
|
+
return unless deadline
|
|
224
|
+
remaining = deadline - Clock.now
|
|
225
|
+
remaining.negative? ? 0 : remaining
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
class Walker
|
|
7
|
+
define(BasicObject) do |object, walker|
|
|
8
|
+
names = send_to(object, :instance_variables)
|
|
9
|
+
next object if names.empty?
|
|
10
|
+
unless walker.modify
|
|
11
|
+
names.each { walker.visit(send_to(object, :instance_variable_get, it)) }
|
|
12
|
+
next object
|
|
13
|
+
end
|
|
14
|
+
values = names.map { send_to(object, :instance_variable_get, it) }
|
|
15
|
+
walker.update(object, values) do |target, results|
|
|
16
|
+
names.each_with_index do |name, index|
|
|
17
|
+
next if send_to(target, :instance_variable_get, name).equal?(results[index])
|
|
18
|
+
send_to(target, :instance_variable_set, name, results[index])
|
|
19
|
+
end
|
|
20
|
+
target
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
define(Module) do |object, walker|
|
|
25
|
+
if walker.constants
|
|
26
|
+
inherit = walker.constants == :inherited
|
|
27
|
+
constant_names = Internal.walker_constants(object, inherit).reject { object.autoload?(it, inherit) }
|
|
28
|
+
values = constant_names.map { object.const_get(it, inherit) }
|
|
29
|
+
object = walker.update(object, values) do |target, results|
|
|
30
|
+
constant_names.each_with_index do |name, index|
|
|
31
|
+
target.const_set(name, results[index]) unless target.const_get(name, inherit).equal?(results[index])
|
|
32
|
+
end
|
|
33
|
+
target
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
if walker.class_variables
|
|
37
|
+
variable_names = object.class_variables(walker.class_variables == :inherited)
|
|
38
|
+
values = variable_names.map { object.class_variable_get(it) }
|
|
39
|
+
object = walker.update(object, values) do |target, results|
|
|
40
|
+
variable_names.each_with_index do |name, index|
|
|
41
|
+
unless target.class_variable_get(name).equal?(results[index])
|
|
42
|
+
target.class_variable_set(name,
|
|
43
|
+
results[index])
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
target
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
super(object, walker)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
define(Internal::Atom, Abstract::Atom) do |object, walker|
|
|
53
|
+
walker.update(object, [object.value]) do |target, results|
|
|
54
|
+
target.value = results.first unless target.value.equal?(results.first)
|
|
55
|
+
target
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
define(Array, Internal::Vector, Abstract::Vector) do |object, walker|
|
|
60
|
+
unless walker.modify
|
|
61
|
+
values = Internal::Vector === object ? object.snapshot : object
|
|
62
|
+
values.each { walker.visit(it) }
|
|
63
|
+
next(Array === object ? super(object, walker) : object)
|
|
64
|
+
end
|
|
65
|
+
values = Internal::Vector === object ? object.snapshot : object.to_a
|
|
66
|
+
result = walker.update(object, values) do |target, results|
|
|
67
|
+
results.each_with_index { |value, index| target[index] = value unless target[index].equal?(value) }
|
|
68
|
+
target
|
|
69
|
+
end
|
|
70
|
+
Array === object ? super(result, walker) : result
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
define(::Set, Abstract::Set) do |object, walker|
|
|
74
|
+
unless walker.modify
|
|
75
|
+
object.each { walker.visit(it) }
|
|
76
|
+
next object
|
|
77
|
+
end
|
|
78
|
+
walker.update(object, object.to_a, hash_keys: !object.compare_by_identity?) do |target, results|
|
|
79
|
+
results.each { walker.check_hash_key(it) } unless target.compare_by_identity?
|
|
80
|
+
target.clear
|
|
81
|
+
results.each { target.add(it) }
|
|
82
|
+
target
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
define(Hash, Abstract::Map) do |object, walker|
|
|
87
|
+
unless walker.modify
|
|
88
|
+
object.each do |key, value|
|
|
89
|
+
walker.visit(key)
|
|
90
|
+
walker.visit(value)
|
|
91
|
+
end
|
|
92
|
+
next(Hash === object ? super(object, walker) : object)
|
|
93
|
+
end
|
|
94
|
+
values = object.each.flat_map { |key, value| [key, value] }
|
|
95
|
+
identity = Hash === object ? object.compare_by_identity? : object.compare_keys_by_identity?
|
|
96
|
+
result = walker.update(object, values, hash_keys: !identity, key_stride: 2) do |target, results|
|
|
97
|
+
results.each_slice(2) { |key, _| walker.check_hash_key(key) } unless identity
|
|
98
|
+
target.clear
|
|
99
|
+
results.each_slice(2) { |key, value| target[key] = value }
|
|
100
|
+
target
|
|
101
|
+
end
|
|
102
|
+
Hash === object ? super(result, walker) : result
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
define(Abstract::ConcurrentMap) do |object, walker|
|
|
106
|
+
values = object.each.flat_map { |key, value| [key, value] }
|
|
107
|
+
walker.update(object, values, hash_keys: !object.compare_keys_by_identity?, key_stride: 2) do |target, results|
|
|
108
|
+
if !target.compare_keys_by_identity? && values.each_slice(2).any? { |key, _| walker.changed?(key) }
|
|
109
|
+
results.each_slice(2) { |key, _| walker.check_hash_key(key) }
|
|
110
|
+
target.clear
|
|
111
|
+
results.each_slice(2) { |key, value| target[key] = value }
|
|
112
|
+
next target
|
|
113
|
+
end
|
|
114
|
+
entries = []
|
|
115
|
+
values.each_slice(2).with_index do |(key, value), index|
|
|
116
|
+
new_key, result = results[index * 2, 2]
|
|
117
|
+
walker.check_hash_key(new_key) unless target.compare_keys_by_identity?
|
|
118
|
+
if !key.equal?(new_key)
|
|
119
|
+
entries << [key, new_key, result]
|
|
120
|
+
elsif !value.equal?(result)
|
|
121
|
+
until target.compare_and_set(key, value, result)
|
|
122
|
+
value = target[key]
|
|
123
|
+
result = walker.visit(value)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
entries.each { |key, _, _| target.delete(key) }
|
|
128
|
+
entries.each { |_, key, value| target[key] = value } # rubocop:disable Style/CombinableLoops
|
|
129
|
+
target
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
define(Abstract::LeaseMap) do |object, walker|
|
|
134
|
+
object.auto_lease do
|
|
135
|
+
values = object.keys.flat_map { |key| [key, object[key]] }
|
|
136
|
+
walker.update(object, values, hash_keys: !object.compare_keys_by_identity?, key_stride: 2) do |target, results|
|
|
137
|
+
target.auto_lease do
|
|
138
|
+
results.each_slice(2) { |key, _| walker.check_hash_key(key) } unless target.compare_keys_by_identity?
|
|
139
|
+
values.each_slice(2).with_index do |(key, _), index|
|
|
140
|
+
target.delete(key) unless key.equal?(results[index * 2])
|
|
141
|
+
end
|
|
142
|
+
results.each_slice(2) { |key, value| target[key] = value }
|
|
143
|
+
end
|
|
144
|
+
target
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
define(Abstract::Lease) do |object, walker|
|
|
150
|
+
value = object.checkout
|
|
151
|
+
checked_out = true
|
|
152
|
+
walker.update(object, [value]) do |target, results|
|
|
153
|
+
unless checked_out
|
|
154
|
+
value = target.checkout
|
|
155
|
+
checked_out = true
|
|
156
|
+
end
|
|
157
|
+
begin
|
|
158
|
+
target.checkin(results.first)
|
|
159
|
+
checked_out = false
|
|
160
|
+
target
|
|
161
|
+
ensure
|
|
162
|
+
if checked_out
|
|
163
|
+
target.checkin(value)
|
|
164
|
+
checked_out = false
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
ensure
|
|
169
|
+
object.checkin(value) if checked_out
|
|
170
|
+
checked_out = false
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
define(Proc) do |object, walker|
|
|
174
|
+
if Internal.rebindable?(object)
|
|
175
|
+
object = walker.update(object, [object.binding.receiver]) do |target, results|
|
|
176
|
+
Farce.rebind(target, self: results.first)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
super(object, walker)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
define(Data) do |object, walker|
|
|
183
|
+
walker.rebuild_data(object)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|