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,261 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Abstract
|
|
7
|
+
# @abstract Shared per-key checkout, mutation, and automatic cleanup behavior for lease maps.
|
|
8
|
+
class LeaseMap < Map
|
|
9
|
+
include Internal::MarshalSupport::Reject
|
|
10
|
+
|
|
11
|
+
# Construct a lease map from a block returning key/value entries.
|
|
12
|
+
# @!macro key_normalization
|
|
13
|
+
# @yield builds the initial key and resource mapping
|
|
14
|
+
# @yieldreturn [Hash, Farce::Abstract::Map, #each] the initial mapping
|
|
15
|
+
def initialize(normalize_keys: nil)
|
|
16
|
+
raise ArgumentError, "a resource constructor block is required" unless block_given?
|
|
17
|
+
|
|
18
|
+
normalizer = Internal::KeyNormalizer.build(
|
|
19
|
+
normalize_keys,
|
|
20
|
+
shareable: Internal::KeyNormalizer.shareable_target?(self),
|
|
21
|
+
)
|
|
22
|
+
Internal::KeyNormalizer.install(self, normalizer, Internal::KeyNormalizer::LeaseOperations)
|
|
23
|
+
mapping = prepare_initial_resources(yield, normalizer)
|
|
24
|
+
@lease_map = new_internal_lease_map(mapping)
|
|
25
|
+
super()
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @api private
|
|
29
|
+
def initialize_copy(_other)
|
|
30
|
+
raise TypeError, "lease maps cannot be copied"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Acquire one key's resource, waiting until it is available.
|
|
34
|
+
# @param key [BasicObject] the key to acquire
|
|
35
|
+
# @param timeout [Numeric, nil] maximum seconds to wait
|
|
36
|
+
# @yieldparam resource [BasicObject] the acquired resource
|
|
37
|
+
# @return [BasicObject] the resource without a block, or the block result
|
|
38
|
+
# @raise [KeyError] if the key is absent or its entry is deleted while waiting
|
|
39
|
+
# @raise [Farce::TimeoutError] if the timeout expires
|
|
40
|
+
def checkout(key, timeout: nil, &) = checkout_canonical(key, missing_key: key, timeout:, &)
|
|
41
|
+
|
|
42
|
+
# Acquire one key's resource immediately if it is available.
|
|
43
|
+
# @param key [BasicObject] the key to acquire
|
|
44
|
+
# @yieldparam resource [BasicObject] the acquired resource
|
|
45
|
+
# @return [BasicObject, nil] the resource or block result, or nil when unavailable
|
|
46
|
+
# @raise [KeyError] if the key is absent
|
|
47
|
+
def try_checkout(key, &) = try_checkout_canonical(key, missing_key: key, &)
|
|
48
|
+
|
|
49
|
+
# Return an explicitly checked-out resource, replace it, or delete it with nil.
|
|
50
|
+
# @param key [BasicObject] the checked-out key
|
|
51
|
+
# @param resource [BasicObject, nil] the replacement, or nil to delete the entry
|
|
52
|
+
# @return [self]
|
|
53
|
+
# @raise [Farce::OwnershipError] unless the current Fiber owns an explicit checkout
|
|
54
|
+
# @raise [ArgumentError] if the replacement is boolean
|
|
55
|
+
def checkin(key, resource) = checkin_canonical(key, resource, missing_key: key)
|
|
56
|
+
|
|
57
|
+
# Return the Lease attached to a key's current entry.
|
|
58
|
+
# A retained handle becomes retired when its entry is deleted.
|
|
59
|
+
# @param key [BasicObject] the key to look up
|
|
60
|
+
# @return [Farce::Abstract::Lease] the current entry's Lease
|
|
61
|
+
# @raise [KeyError] if the key is absent
|
|
62
|
+
def lease_for(key) = lease_for_canonical(key, missing_key: key)
|
|
63
|
+
|
|
64
|
+
# Keep resources acquired by reads checked out until the block exits.
|
|
65
|
+
# Checkouts already owned before the scope remain owned afterward.
|
|
66
|
+
# Nested scopes return only the resources they acquire, including on exceptions and early returns.
|
|
67
|
+
#
|
|
68
|
+
# @example Nesting automatic checkout scopes
|
|
69
|
+
# map = Farce::LeaseMap.new { { a: [], b: [] } }
|
|
70
|
+
# map.auto_lease do
|
|
71
|
+
# map[:a] # Held by the outer scope
|
|
72
|
+
#
|
|
73
|
+
# map.auto_lease do
|
|
74
|
+
# map[:a] # Reuses the outer checkout
|
|
75
|
+
# map[:b] # Held by the inner scope
|
|
76
|
+
# end # Checks in b only
|
|
77
|
+
#
|
|
78
|
+
# map[:b] # Acquires b again for the outer scope
|
|
79
|
+
# end # Checks in a and b
|
|
80
|
+
#
|
|
81
|
+
# @yield the automatic checkout scope
|
|
82
|
+
# @return [BasicObject] the block result
|
|
83
|
+
def auto_lease(&) = internal_lease_map.auto_lease(&)
|
|
84
|
+
|
|
85
|
+
# Read an owned resource or acquire it through the active automatic scope.
|
|
86
|
+
def [](key) = internal_lease_map.read_entry(key).last
|
|
87
|
+
|
|
88
|
+
# (see Map#fetch)
|
|
89
|
+
def fetch(*arguments)
|
|
90
|
+
unless arguments.length.between?(1, 2)
|
|
91
|
+
raise ArgumentError, "wrong number of arguments (given #{arguments.length}, expected 1..2)"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
key, default = arguments
|
|
95
|
+
warn "block supersedes default value argument", uplevel: 1 if block_given? && arguments.length == 2
|
|
96
|
+
present, value = internal_lease_map.read_entry(key)
|
|
97
|
+
return value if present
|
|
98
|
+
return yield(key) if block_given?
|
|
99
|
+
return default if arguments.length == 2
|
|
100
|
+
|
|
101
|
+
raise KeyError.new("key not found: #{key.inspect}", receiver: self, key:)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Insert or replace a resource. Assigning nil deletes the entry.
|
|
105
|
+
# Assignment waits for another owner. An assignment to an explicitly owned
|
|
106
|
+
# entry replaces its held resource without ending the checkout. Assignment
|
|
107
|
+
# is invalid during a checkout block or an iteration yield.
|
|
108
|
+
# @return [BasicObject, nil] the supplied resource, or the deleted resource
|
|
109
|
+
# @raise [ArgumentError] if the resource is boolean
|
|
110
|
+
def []=(key, resource)
|
|
111
|
+
internal_lease_map.store(key, resource)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Read an owned resource or construct an absent resource in an automatic scope.
|
|
115
|
+
# Constructors for the same key run one at a time, outside the map lock.
|
|
116
|
+
# Missing-key assignments wait for construction. Deletion and clear only
|
|
117
|
+
# affect published entries and do not cancel a pending constructor.
|
|
118
|
+
# @param key [BasicObject] the key to read or initialize
|
|
119
|
+
# @yield builds the missing resource without arguments
|
|
120
|
+
# @yieldreturn [BasicObject] a resource other than nil or a boolean
|
|
121
|
+
# @return [BasicObject] the existing or newly constructed resource
|
|
122
|
+
# @raise [LocalJumpError] if no block is given
|
|
123
|
+
# @raise [Farce::OwnershipError] if reading requires ownership or creation lacks an automatic scope
|
|
124
|
+
# @raise [ArgumentError] if the constructor returns nil or a boolean
|
|
125
|
+
def store_if_absent(key, &) = internal_lease_map.store_if_absent(key, &)
|
|
126
|
+
|
|
127
|
+
# Delete a key after acquiring and retiring its Lease.
|
|
128
|
+
# @return [BasicObject, nil] the removed resource, or nil if absent
|
|
129
|
+
def delete(key) = internal_lease_map.delete(key)
|
|
130
|
+
|
|
131
|
+
# Delete each entry captured when clearing begins.
|
|
132
|
+
# Entries concurrently reinserted under the same key are preserved.
|
|
133
|
+
# @return [self]
|
|
134
|
+
def clear
|
|
135
|
+
internal_lease_map.clear
|
|
136
|
+
self
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# @return [Boolean] whether the key's resource is available
|
|
140
|
+
def available?(key) = internal_lease_map.available?(key)
|
|
141
|
+
|
|
142
|
+
# @return [Boolean] whether the key's resource is checked out
|
|
143
|
+
def checked_out?(key) = internal_lease_map.checked_out?(key)
|
|
144
|
+
|
|
145
|
+
# @return [Boolean] whether the current Fiber owns the key's checkout
|
|
146
|
+
def owned?(key) = internal_lease_map.owned?(key)
|
|
147
|
+
|
|
148
|
+
# (see Map#key?)
|
|
149
|
+
def key?(key) = internal_lease_map.key?(key)
|
|
150
|
+
|
|
151
|
+
# (see Map#getkey)
|
|
152
|
+
def getkey(key) = internal_lease_map.getkey(key)
|
|
153
|
+
|
|
154
|
+
# (see Map#size)
|
|
155
|
+
def size = internal_lease_map.size
|
|
156
|
+
|
|
157
|
+
# (see Map#keys)
|
|
158
|
+
def keys = internal_lease_map.keys
|
|
159
|
+
|
|
160
|
+
# LeaseMap keys use equality and values use Lease identity.
|
|
161
|
+
def compare_keys_by_identity? = internal_lease_map.compare_keys_by_identity?
|
|
162
|
+
def compare_values_by_identity? = internal_lease_map.compare_values_by_identity?
|
|
163
|
+
|
|
164
|
+
# Top-level keys must be shareable. Managed resources may be unshareable.
|
|
165
|
+
def shareable_keys? = true
|
|
166
|
+
def shareable_values? = false
|
|
167
|
+
|
|
168
|
+
# Iterate while leasing only the entry currently being yielded.
|
|
169
|
+
def each(&block)
|
|
170
|
+
return enum_for(__callee__) { size } unless block
|
|
171
|
+
|
|
172
|
+
internal_lease_map.each(&block)
|
|
173
|
+
self
|
|
174
|
+
end
|
|
175
|
+
alias each_pair each
|
|
176
|
+
|
|
177
|
+
# Iterate over a snapshot of current keys without leasing their resources.
|
|
178
|
+
def each_key(&block)
|
|
179
|
+
return enum_for(__callee__) { size } unless block
|
|
180
|
+
|
|
181
|
+
internal_lease_map.each_key(&block)
|
|
182
|
+
self
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Iterate while leasing only the value currently being yielded.
|
|
186
|
+
def each_value(&block)
|
|
187
|
+
return enum_for(__callee__) { size } unless block
|
|
188
|
+
|
|
189
|
+
internal_lease_map.each_value(&block)
|
|
190
|
+
self
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Return key and Lease handle pairs.
|
|
194
|
+
# Unlike iteration, this method never checks resources out.
|
|
195
|
+
# @return [Array<Array(BasicObject, Farce::Abstract::Lease)>]
|
|
196
|
+
def to_a = internal_lease_map.handles
|
|
197
|
+
|
|
198
|
+
# Return a key to Lease handle mapping.
|
|
199
|
+
# Unlike iteration, this method never checks resources out.
|
|
200
|
+
# A block receives each key and Lease handle and returns a pair for the new Hash.
|
|
201
|
+
# @return [Hash{BasicObject => Farce::Abstract::Lease}]
|
|
202
|
+
def to_h(&) = entries_to_hash(to_a, &)
|
|
203
|
+
|
|
204
|
+
# Return the current Lease handles.
|
|
205
|
+
# @return [Array<Farce::Abstract::Lease>]
|
|
206
|
+
def values = to_h.values
|
|
207
|
+
|
|
208
|
+
private
|
|
209
|
+
|
|
210
|
+
def prepare_initial_resources(entries, normalizer)
|
|
211
|
+
entries = convert_entries(entries)
|
|
212
|
+
raise TypeError, "lease map initializer must yield key/value pairs" unless entries
|
|
213
|
+
return entries if entries.is_a?(Hash) && !normalizer
|
|
214
|
+
|
|
215
|
+
mapping = {}
|
|
216
|
+
entries.each do |key, resource|
|
|
217
|
+
if resource.nil? || resource.equal?(true) || resource.equal?(false)
|
|
218
|
+
raise ArgumentError, "resource must not be nil or a boolean"
|
|
219
|
+
end
|
|
220
|
+
key = normalizer.call(key) if normalizer
|
|
221
|
+
mapping[key] = resource
|
|
222
|
+
end
|
|
223
|
+
mapping
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def checkout_canonical(key, missing_key:, timeout: nil, &)
|
|
227
|
+
internal_lease_map.checkout(key, timeout:, receiver: self, missing_key:, &)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def try_checkout_canonical(key, missing_key:, &)
|
|
231
|
+
internal_lease_map.try_checkout(key, receiver: self, missing_key:, &)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def checkin_canonical(key, resource, missing_key:)
|
|
235
|
+
internal_lease_map.checkin(key, resource, receiver: self, missing_key:)
|
|
236
|
+
self
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def lease_for_canonical(key, missing_key:)
|
|
240
|
+
internal_lease_map.lease_for(key, receiver: self, missing_key:)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def each_for_inspect
|
|
244
|
+
return enum_for(__method__) { size } unless block_given?
|
|
245
|
+
to_a.each { |key, lease| yield key, lease_state(lease) }
|
|
246
|
+
self
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def internal_lease_map = @lease_map
|
|
250
|
+
def new_internal_lease_map(_) = raise(NoMethodError, "abstract lease map storage")
|
|
251
|
+
def inspect_value(inspector, lease, *) = inspector.text(lease.to_s)
|
|
252
|
+
|
|
253
|
+
def lease_state(lease)
|
|
254
|
+
return :retired if lease.retired?
|
|
255
|
+
return :available if lease.available?
|
|
256
|
+
return :owned if lease.owned?
|
|
257
|
+
:checked_out
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Abstract
|
|
7
|
+
# @abstract Shared checkout, return, ownership, and capacity behavior for resource pools.
|
|
8
|
+
class LeasePool
|
|
9
|
+
include Internal::Noncopyable
|
|
10
|
+
include Internal::Inspect
|
|
11
|
+
|
|
12
|
+
# Construct an empty pool whose resources are created on demand.
|
|
13
|
+
# @param max_size [Integer] the maximum number of managed resources
|
|
14
|
+
# @yield builds one resource after capacity has been reserved
|
|
15
|
+
# @yieldreturn [BasicObject] a new resource
|
|
16
|
+
# @raise [ArgumentError] if no block is given or max_size is not a positive Integer
|
|
17
|
+
def initialize(max_size:, &factory)
|
|
18
|
+
validate_configuration!(max_size, factory)
|
|
19
|
+
@max_size = Integer(max_size)
|
|
20
|
+
@factory = prepare_factory(factory)
|
|
21
|
+
@pool = new_internal_pool(max_size)
|
|
22
|
+
super()
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Acquire a resource, waiting for availability or creation capacity.
|
|
26
|
+
# @param timeout [Numeric, nil] maximum seconds to wait before reserving a resource
|
|
27
|
+
# @yieldparam resource [BasicObject] the acquired resource
|
|
28
|
+
# @return [BasicObject] the resource without a block, or the block result
|
|
29
|
+
# @raise [Farce::TimeoutError] if the timeout expires
|
|
30
|
+
def checkout(timeout: nil, &block)
|
|
31
|
+
pool = internal_pool
|
|
32
|
+
block ? pool.checkout(@factory, timeout:, &block) : pool.checkout(@factory, timeout:)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Acquire an available resource or create one without waiting for capacity.
|
|
36
|
+
# @yieldparam resource [BasicObject] the acquired resource
|
|
37
|
+
# @return [BasicObject, nil] the resource or block result, or nil at capacity
|
|
38
|
+
def try_checkout(&block)
|
|
39
|
+
pool = internal_pool
|
|
40
|
+
block ? pool.try_checkout(@factory, &block) : pool.try_checkout(@factory)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Return an explicitly checked-out resource, a replacement, or nil to delete its slot.
|
|
44
|
+
# @param resource [BasicObject, nil] the resource to store, or nil to release capacity
|
|
45
|
+
# @return [self]
|
|
46
|
+
# @raise [Farce::OwnershipError] unless the current Fiber owns an explicit checkout
|
|
47
|
+
# @raise [ArgumentError] if resource is true or false
|
|
48
|
+
def checkin(resource)
|
|
49
|
+
internal_pool.checkin(resource)
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @return [Integer] the configured capacity
|
|
54
|
+
attr_reader :max_size
|
|
55
|
+
|
|
56
|
+
# @return [Integer] managed resources, excluding in-progress factory calls
|
|
57
|
+
def size = internal_pool.size
|
|
58
|
+
|
|
59
|
+
# @return [Integer] resources ready for checkout
|
|
60
|
+
def available_count = internal_pool.available_count
|
|
61
|
+
|
|
62
|
+
# @return [Integer] resources currently checked out
|
|
63
|
+
def checked_out_count = internal_pool.checked_out_count
|
|
64
|
+
|
|
65
|
+
# @return [Integer] capacity reserved by in-progress factory calls
|
|
66
|
+
def creating_count = internal_pool.creating_count
|
|
67
|
+
|
|
68
|
+
# @api private
|
|
69
|
+
def inspect_with(inspector)
|
|
70
|
+
super do
|
|
71
|
+
yield if block_given?
|
|
72
|
+
inspector.attribute(:size, size)
|
|
73
|
+
inspector.attribute(:max_size, max_size)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def validate_configuration!(max_size, factory)
|
|
80
|
+
raise ArgumentError, "a resource factory block is required" unless factory
|
|
81
|
+
return if max_size.is_a?(Integer) && max_size.positive?
|
|
82
|
+
|
|
83
|
+
raise ArgumentError, "max_size must be a positive Integer"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def prepare_factory(factory) = factory
|
|
87
|
+
def internal_pool = @pool
|
|
88
|
+
def new_internal_pool(_) = raise(NoMethodError, "abstract lease pool storage")
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Abstract
|
|
7
|
+
# @abstract A bounded map that evicts the least frequently accessed entry.
|
|
8
|
+
# Ties are resolved by least recent access.
|
|
9
|
+
class LFUMap < BoundedMap
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
# simplecov:disable
|
|
13
|
+
def new_bounded_map(...)
|
|
14
|
+
raise "subclass failed to implement #new_bounded_map" unless instance_of?(LFUMap)
|
|
15
|
+
raise NoMethodError, "Farce::Abstract::LFUMap should not be instantiated directly. Use a subclass instead."
|
|
16
|
+
end
|
|
17
|
+
# simplecov:enable
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
module Abstract
|
|
7
|
+
# @abstract A bounded map that evicts the least recently accessed entry.
|
|
8
|
+
class LRUMap < BoundedMap
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# @api private
|
|
12
|
+
def marshal_entries
|
|
13
|
+
map = marshal_map.dup
|
|
14
|
+
Array.new(map.size) { map.shift }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# simplecov:disable
|
|
18
|
+
def new_bounded_map(...)
|
|
19
|
+
raise "subclass failed to implement #new_bounded_map" unless instance_of?(LRUMap)
|
|
20
|
+
raise NoMethodError, "Farce::Abstract::LRUMap should not be instantiated directly. Use a subclass instead."
|
|
21
|
+
end
|
|
22
|
+
# simplecov:enable
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|